Skip to content

Commit 1e00718

Browse files
Xue Chaojingdavem330
authored andcommitted
hinic: add LRO support
This patch adds LRO support for the HiNIC driver. Reported-by: kbuild test robot <[email protected]> Reviewed-by: Jesse Brandeburg <[email protected]> Signed-off-by: Xue Chaojing <[email protected]> Reviewed-by: Jesse Brandeburg <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 600bb03 commit 1e00718

File tree

10 files changed

+348
-13
lines changed

10 files changed

+348
-13
lines changed

drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,8 @@ static int set_hw_ioctxt(struct hinic_hwdev *hwdev, unsigned int rq_depth,
313313
hw_ioctxt.set_cmdq_depth = HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT;
314314
hw_ioctxt.cmdq_depth = 0;
315315

316+
hw_ioctxt.lro_en = 1;
317+
316318
hw_ioctxt.rq_depth = ilog2(rq_depth);
317319

318320
hw_ioctxt.rx_buf_sz_idx = HINIC_RX_BUF_SZ_IDX;

drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ enum hinic_port_cmd {
5050

5151
HINIC_PORT_CMD_GET_LINK_STATE = 24,
5252

53+
HINIC_PORT_CMD_SET_LRO = 25,
54+
5355
HINIC_PORT_CMD_SET_RX_CSUM = 26,
5456

5557
HINIC_PORT_CMD_SET_PORT_STATE = 41,
@@ -62,7 +64,11 @@ enum hinic_port_cmd {
6264

6365
HINIC_PORT_CMD_SET_TSO = 112,
6466

67+
HINIC_PORT_CMD_SET_RQ_IQ_MAP = 115,
68+
6569
HINIC_PORT_CMD_GET_CAP = 170,
70+
71+
HINIC_PORT_CMD_SET_LRO_TIMER = 244,
6672
};
6773

6874
enum hinic_mgmt_msg_cmd {
@@ -106,7 +112,7 @@ struct hinic_cmd_hw_ioctxt {
106112
u8 set_cmdq_depth;
107113
u8 cmdq_depth;
108114

109-
u8 rsvd2;
115+
u8 lro_en;
110116
u8 rsvd3;
111117
u8 rsvd4;
112118
u8 rsvd5;

drivers/net/ethernet/huawei/hinic/hinic_hw_io.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545

4646
enum io_cmd {
4747
IO_CMD_MODIFY_QUEUE_CTXT = 0,
48+
IO_CMD_CLEAN_QUEUE_CTXT,
4849
};
4950

5051
static void init_db_area_idx(struct hinic_free_db_area *free_db_area)
@@ -210,6 +211,59 @@ static int write_qp_ctxts(struct hinic_func_to_io *func_to_io, u16 base_qpn,
210211
write_rq_ctxts(func_to_io, base_qpn, num_qps));
211212
}
212213

214+
static int hinic_clean_queue_offload_ctxt(struct hinic_func_to_io *func_to_io,
215+
enum hinic_qp_ctxt_type ctxt_type)
216+
{
217+
struct hinic_hwif *hwif = func_to_io->hwif;
218+
struct hinic_clean_queue_ctxt *ctxt_block;
219+
struct pci_dev *pdev = hwif->pdev;
220+
struct hinic_cmdq_buf cmdq_buf;
221+
u64 out_param = 0;
222+
int err;
223+
224+
err = hinic_alloc_cmdq_buf(&func_to_io->cmdqs, &cmdq_buf);
225+
if (err) {
226+
dev_err(&pdev->dev, "Failed to allocate cmdq buf\n");
227+
return err;
228+
}
229+
230+
ctxt_block = cmdq_buf.buf;
231+
ctxt_block->cmdq_hdr.num_queues = func_to_io->max_qps;
232+
ctxt_block->cmdq_hdr.queue_type = ctxt_type;
233+
ctxt_block->cmdq_hdr.addr_offset = 0;
234+
235+
/* TSO/LRO ctxt size: 0x0:0B; 0x1:160B; 0x2:200B; 0x3:240B */
236+
ctxt_block->ctxt_size = 0x3;
237+
238+
hinic_cpu_to_be32(ctxt_block, sizeof(*ctxt_block));
239+
240+
cmdq_buf.size = sizeof(*ctxt_block);
241+
242+
err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,
243+
IO_CMD_CLEAN_QUEUE_CTXT,
244+
&cmdq_buf, &out_param);
245+
246+
if (err || out_param) {
247+
dev_err(&pdev->dev, "Failed to clean offload ctxts, err: %d, out_param: 0x%llx\n",
248+
err, out_param);
249+
250+
err = -EFAULT;
251+
}
252+
253+
hinic_free_cmdq_buf(&func_to_io->cmdqs, &cmdq_buf);
254+
255+
return err;
256+
}
257+
258+
static int hinic_clean_qp_offload_ctxt(struct hinic_func_to_io *func_to_io)
259+
{
260+
/* clean LRO/TSO context space */
261+
return (hinic_clean_queue_offload_ctxt(func_to_io,
262+
HINIC_QP_CTXT_TYPE_SQ) ||
263+
hinic_clean_queue_offload_ctxt(func_to_io,
264+
HINIC_QP_CTXT_TYPE_RQ));
265+
}
266+
213267
/**
214268
* init_qp - Initialize a Queue Pair
215269
* @func_to_io: func to io channel that holds the IO components
@@ -381,6 +435,12 @@ int hinic_io_create_qps(struct hinic_func_to_io *func_to_io,
381435
goto err_write_qp_ctxts;
382436
}
383437

438+
err = hinic_clean_qp_offload_ctxt(func_to_io);
439+
if (err) {
440+
dev_err(&pdev->dev, "Failed to clean QP contexts space\n");
441+
goto err_write_qp_ctxts;
442+
}
443+
384444
return 0;
385445

386446
err_write_qp_ctxts:

drivers/net/ethernet/huawei/hinic/hinic_hw_qp_ctxt.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,11 @@ struct hinic_rq_ctxt {
201201
u32 wq_block_lo_pfn;
202202
};
203203

204+
struct hinic_clean_queue_ctxt {
205+
struct hinic_qp_ctxt_header cmdq_hdr;
206+
u32 ctxt_size;
207+
};
208+
204209
struct hinic_sq_ctxt_block {
205210
struct hinic_qp_ctxt_header hdr;
206211
struct hinic_sq_ctxt sq_ctxt[HINIC_Q_CTXT_MAX];

drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,26 @@
219219
#define HINIC_MSS_DEFAULT 0x3E00
220220
#define HINIC_MSS_MIN 0x50
221221

222+
#define RQ_CQE_STATUS_NUM_LRO_SHIFT 16
223+
#define RQ_CQE_STATUS_NUM_LRO_MASK 0xFFU
224+
225+
#define RQ_CQE_STATUS_GET(val, member) (((val) >> \
226+
RQ_CQE_STATUS_##member##_SHIFT) & \
227+
RQ_CQE_STATUS_##member##_MASK)
228+
229+
#define HINIC_GET_RX_NUM_LRO(status) \
230+
RQ_CQE_STATUS_GET(status, NUM_LRO)
231+
232+
#define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_SHIFT 0
233+
#define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_MASK 0xFFFU
234+
235+
#define RQ_CQE_OFFOLAD_TYPE_GET(val, member) (((val) >> \
236+
RQ_CQE_OFFOLAD_TYPE_##member##_SHIFT) & \
237+
RQ_CQE_OFFOLAD_TYPE_##member##_MASK)
238+
239+
#define HINIC_GET_RX_PKT_TYPE(offload_type) \
240+
RQ_CQE_OFFOLAD_TYPE_GET(offload_type, PKT_TYPE)
241+
222242
enum hinic_l4offload_type {
223243
HINIC_L4_OFF_DISABLE = 0,
224244
HINIC_TCP_OFFLOAD_ENABLE = 1,
@@ -372,7 +392,7 @@ struct hinic_rq_cqe {
372392
u32 status;
373393
u32 len;
374394

375-
u32 rsvd2;
395+
u32 offload_type;
376396
u32 rsvd3;
377397
u32 rsvd4;
378398
u32 rsvd5;

drivers/net/ethernet/huawei/hinic/hinic_main.c

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ MODULE_PARM_DESC(rx_weight, "Number Rx packets for NAPI budget (default=64)");
6262
NETIF_MSG_IFUP | \
6363
NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR)
6464

65+
#define HINIC_LRO_MAX_WQE_NUM_DEFAULT 8
66+
67+
#define HINIC_LRO_RX_TIMER_DEFAULT 16
68+
6569
#define VLAN_BITMAP_SIZE(nic_dev) (ALIGN(VLAN_N_VID, 8) / 8)
6670

6771
#define work_to_rx_mode_work(work) \
@@ -72,6 +76,10 @@ MODULE_PARM_DESC(rx_weight, "Number Rx packets for NAPI budget (default=64)");
7276

7377
static int change_mac_addr(struct net_device *netdev, const u8 *addr);
7478

79+
static int set_features(struct hinic_dev *nic_dev,
80+
netdev_features_t pre_features,
81+
netdev_features_t features, bool force_change);
82+
7583
static void set_link_speed(struct ethtool_link_ksettings *link_ksettings,
7684
enum hinic_speed speed)
7785
{
@@ -372,6 +380,17 @@ static void free_rxqs(struct hinic_dev *nic_dev)
372380
nic_dev->rxqs = NULL;
373381
}
374382

383+
static int hinic_configure_max_qnum(struct hinic_dev *nic_dev)
384+
{
385+
int err;
386+
387+
err = hinic_set_max_qnum(nic_dev, nic_dev->hwdev->nic_cap.max_qps);
388+
if (err)
389+
return err;
390+
391+
return 0;
392+
}
393+
375394
static int hinic_open(struct net_device *netdev)
376395
{
377396
struct hinic_dev *nic_dev = netdev_priv(netdev);
@@ -401,6 +420,13 @@ static int hinic_open(struct net_device *netdev)
401420
goto err_create_rxqs;
402421
}
403422

423+
err = hinic_configure_max_qnum(nic_dev);
424+
if (err) {
425+
netif_err(nic_dev, drv, nic_dev->netdev,
426+
"Failed to configure the maximum number of queues\n");
427+
goto err_port_state;
428+
}
429+
404430
num_qps = hinic_hwdev_num_qps(nic_dev->hwdev);
405431
netif_set_real_num_tx_queues(netdev, num_qps);
406432
netif_set_real_num_rx_queues(netdev, num_qps);
@@ -787,6 +813,29 @@ static void hinic_get_stats64(struct net_device *netdev,
787813
stats->tx_errors = nic_tx_stats->tx_dropped;
788814
}
789815

816+
static int hinic_set_features(struct net_device *netdev,
817+
netdev_features_t features)
818+
{
819+
struct hinic_dev *nic_dev = netdev_priv(netdev);
820+
821+
return set_features(nic_dev, nic_dev->netdev->features,
822+
features, false);
823+
}
824+
825+
static netdev_features_t hinic_fix_features(struct net_device *netdev,
826+
netdev_features_t features)
827+
{
828+
struct hinic_dev *nic_dev = netdev_priv(netdev);
829+
830+
/* If Rx checksum is disabled, then LRO should also be disabled */
831+
if (!(features & NETIF_F_RXCSUM)) {
832+
netif_info(nic_dev, drv, netdev, "disabling LRO as RXCSUM is off\n");
833+
features &= ~NETIF_F_LRO;
834+
}
835+
836+
return features;
837+
}
838+
790839
static const struct net_device_ops hinic_netdev_ops = {
791840
.ndo_open = hinic_open,
792841
.ndo_stop = hinic_close,
@@ -799,13 +848,16 @@ static const struct net_device_ops hinic_netdev_ops = {
799848
.ndo_start_xmit = hinic_xmit_frame,
800849
.ndo_tx_timeout = hinic_tx_timeout,
801850
.ndo_get_stats64 = hinic_get_stats64,
851+
.ndo_fix_features = hinic_fix_features,
852+
.ndo_set_features = hinic_set_features,
853+
802854
};
803855

804856
static void netdev_features_init(struct net_device *netdev)
805857
{
806858
netdev->hw_features = NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM |
807859
NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6 |
808-
NETIF_F_RXCSUM;
860+
NETIF_F_RXCSUM | NETIF_F_LRO;
809861

810862
netdev->vlan_features = netdev->hw_features;
811863

@@ -878,6 +930,13 @@ static int set_features(struct hinic_dev *nic_dev,
878930
if (changed & NETIF_F_RXCSUM)
879931
err = hinic_set_rx_csum_offload(nic_dev, csum_en);
880932

933+
if (changed & NETIF_F_LRO) {
934+
err = hinic_set_rx_lro_state(nic_dev,
935+
!!(features & NETIF_F_LRO),
936+
HINIC_LRO_RX_TIMER_DEFAULT,
937+
HINIC_LRO_MAX_WQE_NUM_DEFAULT);
938+
}
939+
881940
return err;
882941
}
883942

0 commit comments

Comments
 (0)