Skip to content

Commit

Permalink
net-next/hinic:add rx checksum offload for HiNIC
Browse files Browse the repository at this point in the history
In order to improve performance, this patch adds rx checksum offload
for the HiNIC driver. Performance test(Iperf) shows more than 80%
improvement in TCP streams.

Signed-off-by: Xue Chaojing <xuechaojing@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Xue Chaojing authored and David S. Miller committed Nov 20, 2018
1 parent ebda9b4 commit 4a61abb
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 1 deletion.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ enum hinic_port_cmd {

HINIC_PORT_CMD_GET_LINK_STATE = 24,

HINIC_PORT_CMD_SET_RX_CSUM = 26,

HINIC_PORT_CMD_SET_PORT_STATE = 41,

HINIC_PORT_CMD_FWCTXT_INIT = 69,
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,10 @@

#define HINIC_RQ_CQE_STATUS_RXDONE_MASK 0x1

#define HINIC_RQ_CQE_STATUS_CSUM_ERR_SHIFT 0

#define HINIC_RQ_CQE_STATUS_CSUM_ERR_MASK 0xFFFFU

#define HINIC_RQ_CQE_STATUS_GET(val, member) \
(((val) >> HINIC_RQ_CQE_STATUS_##member##_SHIFT) & \
HINIC_RQ_CQE_STATUS_##member##_MASK)
Expand Down
7 changes: 6 additions & 1 deletion drivers/net/ethernet/huawei/hinic/hinic_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,8 @@ static const struct net_device_ops hinic_netdev_ops = {
static void netdev_features_init(struct net_device *netdev)
{
netdev->hw_features = NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6 |
NETIF_F_RXCSUM;

netdev->vlan_features = netdev->hw_features;

Expand Down Expand Up @@ -869,12 +870,16 @@ static int set_features(struct hinic_dev *nic_dev,
netdev_features_t features, bool force_change)
{
netdev_features_t changed = force_change ? ~0 : pre_features ^ features;
u32 csum_en = HINIC_RX_CSUM_OFFLOAD_EN;
int err = 0;

if (changed & NETIF_F_TSO)
err = hinic_port_set_tso(nic_dev, (features & NETIF_F_TSO) ?
HINIC_TSO_ENABLE : HINIC_TSO_DISABLE);

if (changed & NETIF_F_RXCSUM)
err = hinic_set_rx_csum_offload(nic_dev, csum_en);

return err;
}

Expand Down
28 changes: 28 additions & 0 deletions drivers/net/ethernet/huawei/hinic/hinic_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,3 +409,31 @@ int hinic_port_set_tso(struct hinic_dev *nic_dev, enum hinic_tso_state state)

return 0;
}

int hinic_set_rx_csum_offload(struct hinic_dev *nic_dev, u32 en)
{
struct hinic_checksum_offload rx_csum_cfg = {0};
struct hinic_hwdev *hwdev = nic_dev->hwdev;
struct hinic_hwif *hwif = hwdev->hwif;
struct pci_dev *pdev = hwif->pdev;
u16 out_size;
int err;

if (!hwdev)
return -EINVAL;

rx_csum_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
rx_csum_cfg.rx_csum_offload = en;

err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_CSUM,
&rx_csum_cfg, sizeof(rx_csum_cfg),
&rx_csum_cfg, &out_size);
if (err || !out_size || rx_csum_cfg.status) {
dev_err(&pdev->dev,
"Failed to set rx csum offload, ret = %d\n",
rx_csum_cfg.status);
return -EINVAL;
}

return 0;
}
10 changes: 10 additions & 0 deletions drivers/net/ethernet/huawei/hinic/hinic_port.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,15 @@ struct hinic_tso_config {
u8 resv2[3];
};

struct hinic_checksum_offload {
u8 status;
u8 version;
u8 rsvd0[6];

u16 func_id;
u16 rsvd1;
u32 rx_csum_offload;
};
int hinic_port_add_mac(struct hinic_dev *nic_dev, const u8 *addr,
u16 vlan_id);

Expand Down Expand Up @@ -213,4 +222,5 @@ int hinic_port_get_cap(struct hinic_dev *nic_dev,

int hinic_port_set_tso(struct hinic_dev *nic_dev, enum hinic_tso_state state);

int hinic_set_rx_csum_offload(struct hinic_dev *nic_dev, u32 en);
#endif
24 changes: 24 additions & 0 deletions drivers/net/ethernet/huawei/hinic/hinic_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,28 @@ static void rxq_stats_init(struct hinic_rxq *rxq)
hinic_rxq_clean_stats(rxq);
}

static void rx_csum(struct hinic_rxq *rxq, u16 cons_idx,
struct sk_buff *skb)
{
struct net_device *netdev = rxq->netdev;
struct hinic_rq_cqe *cqe;
struct hinic_rq *rq;
u32 csum_err;
u32 status;

rq = rxq->rq;
cqe = rq->cqe[cons_idx];
status = be32_to_cpu(cqe->status);
csum_err = HINIC_RQ_CQE_STATUS_GET(status, CSUM_ERR);

if (!(netdev->features & NETIF_F_RXCSUM))
return;

if (!csum_err)
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb->ip_summed = CHECKSUM_NONE;
}
/**
* rx_alloc_skb - allocate skb and map it to dma address
* @rxq: rx queue
Expand Down Expand Up @@ -328,6 +350,8 @@ static int rxq_recv(struct hinic_rxq *rxq, int budget)

rx_unmap_skb(rxq, hinic_sge_to_dma(&sge));

rx_csum(rxq, ci, skb);

prefetch(skb->data);

pkt_len = sge.len;
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/huawei/hinic/hinic_rx.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@

#include "hinic_hw_qp.h"

#define HINIC_RX_CSUM_OFFLOAD_EN 0xFFF
#define HINIC_RX_CSUM_HW_CHECK_NONE BIT(7)
#define HINIC_RX_CSUM_IPSU_OTHER_ERR BIT(8)

struct hinic_rxq_stats {
u64 pkts;
u64 bytes;
Expand Down

0 comments on commit 4a61abb

Please sign in to comment.