Skip to content

Commit d8ef0f7

Browse files
Fan GongNipaLocal
authored andcommitted
hinic3: Add netdev register interfaces
Add netdev notifier to accept netdev event. Refine port event type to change link status. Co-developed-by: Zhu Yikai <[email protected]> Signed-off-by: Zhu Yikai <[email protected]> Signed-off-by: Fan Gong <[email protected]> Signed-off-by: NipaLocal <nipa@local>
1 parent 3eb9802 commit d8ef0f7

File tree

6 files changed

+220
-3
lines changed

6 files changed

+220
-3
lines changed

drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ enum hinic3_event_service_type {
1717
HINIC3_EVENT_SRV_NIC = 1
1818
};
1919

20+
enum hinic3_comm_event_type {
21+
HINIC3_COMM_EVENT_PCIE_LINK_DOWN = 0,
22+
HINIC3_COMM_EVENT_HEART_LOST = 1,
23+
HINIC3_COMM_EVENT_FAULT = 2,
24+
HINIC3_COMM_EVENT_SRIOV_STATE_CHANGE = 3,
25+
HINIC3_COMM_EVENT_CARD_REMOVE = 4,
26+
HINIC3_COMM_EVENT_MGMT_WATCHDOG = 5,
27+
};
28+
2029
enum hinic3_fault_err_level {
2130
HINIC3_FAULT_LEVEL_SERIOUS_FLR = 3,
2231
};

drivers/net/ethernet/huawei/hinic3/hinic3_irq.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ static void hinic3_auto_moderation_work(struct work_struct *work)
215215
nic_dev = container_of(delay, struct hinic3_nic_dev, moderation_task);
216216
period = (unsigned long)(jiffies - nic_dev->last_moder_jiffies);
217217
netdev = nic_dev->netdev;
218+
if (!test_bit(HINIC3_INTF_UP, &nic_dev->flags))
219+
return;
218220

219221
queue_delayed_work(nic_dev->workq, &nic_dev->moderation_task,
220222
HINIC3_MODERATONE_DELAY);

drivers/net/ethernet/huawei/hinic3/hinic3_main.c

Lines changed: 177 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,65 @@
2929
#define HINIC3_DEFAULT_TXRX_MSIX_COALESC_TIMER_CFG 25
3030
#define HINIC3_DEFAULT_TXRX_MSIX_RESEND_TIMER_CFG 7
3131

32+
#define HINIC3_MAX_VLAN_DEPTH_OFFLOAD_SUPPORT 1
33+
#define HINIC3_VLAN_CLEAR_OFFLOAD \
34+
(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
35+
NETIF_F_SCTP_CRC | NETIF_F_RXCSUM | NETIF_F_ALL_TSO)
36+
37+
/* used for netdev notifier register/unregister */
38+
static DEFINE_MUTEX(hinic3_netdev_notifiers_mutex);
39+
static int hinic3_netdev_notifiers_ref_cnt;
40+
41+
static u16 hinic3_get_vlan_depth(struct net_device *netdev)
42+
{
43+
u16 vlan_depth = 0;
44+
45+
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
46+
while (is_vlan_dev(netdev)) {
47+
netdev = vlan_dev_priv(netdev)->real_dev;
48+
vlan_depth++;
49+
}
50+
#endif
51+
return vlan_depth;
52+
}
53+
54+
static int hinic3_netdev_event(struct notifier_block *notifier,
55+
unsigned long event, void *ptr)
56+
{
57+
struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
58+
struct hinic3_nic_dev *nic_dev = netdev_priv(ndev);
59+
u16 vlan_depth;
60+
61+
if (!is_vlan_dev(ndev))
62+
return NOTIFY_DONE;
63+
64+
netdev_hold(ndev, &nic_dev->tracker, GFP_ATOMIC);
65+
66+
switch (event) {
67+
case NETDEV_REGISTER:
68+
vlan_depth = hinic3_get_vlan_depth(ndev);
69+
if (vlan_depth == HINIC3_MAX_VLAN_DEPTH_OFFLOAD_SUPPORT) {
70+
ndev->vlan_features &= (~HINIC3_VLAN_CLEAR_OFFLOAD);
71+
} else if (vlan_depth > HINIC3_MAX_VLAN_DEPTH_OFFLOAD_SUPPORT) {
72+
ndev->hw_features &= (~HINIC3_VLAN_CLEAR_OFFLOAD);
73+
ndev->features &= (~HINIC3_VLAN_CLEAR_OFFLOAD);
74+
}
75+
76+
break;
77+
78+
default:
79+
break;
80+
}
81+
82+
netdev_put(ndev, &nic_dev->tracker);
83+
84+
return NOTIFY_DONE;
85+
}
86+
87+
static struct notifier_block hinic3_netdev_notifier = {
88+
.notifier_call = hinic3_netdev_event,
89+
};
90+
3291
static void init_intr_coal_param(struct net_device *netdev)
3392
{
3493
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
@@ -161,6 +220,14 @@ static int hinic3_init_nic_dev(struct net_device *netdev,
161220
return 0;
162221
}
163222

223+
static void hinic3_free_nic_dev(struct net_device *netdev)
224+
{
225+
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
226+
227+
destroy_workqueue(nic_dev->workq);
228+
kfree(nic_dev->vlan_bitmap);
229+
}
230+
164231
static int hinic3_sw_init(struct net_device *netdev)
165232
{
166233
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
@@ -238,6 +305,8 @@ static void hinic3_assign_netdev_ops(struct net_device *netdev)
238305
static void netdev_feature_init(struct net_device *netdev)
239306
{
240307
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
308+
netdev_features_t hw_features = 0;
309+
netdev_features_t vlan_fts = 0;
241310
netdev_features_t cso_fts = 0;
242311
netdev_features_t tso_fts = 0;
243312
netdev_features_t dft_fts;
@@ -250,7 +319,29 @@ static void netdev_feature_init(struct net_device *netdev)
250319
if (hinic3_test_support(nic_dev, HINIC3_NIC_F_TSO))
251320
tso_fts |= NETIF_F_TSO | NETIF_F_TSO6;
252321

253-
netdev->features |= dft_fts | cso_fts | tso_fts;
322+
if (hinic3_test_support(nic_dev, HINIC3_NIC_F_RX_VLAN_STRIP |
323+
HINIC3_NIC_F_TX_VLAN_INSERT))
324+
vlan_fts |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
325+
326+
if (hinic3_test_support(nic_dev, HINIC3_NIC_F_RX_VLAN_FILTER))
327+
vlan_fts |= NETIF_F_HW_VLAN_CTAG_FILTER;
328+
329+
if (hinic3_test_support(nic_dev, HINIC3_NIC_F_VXLAN_OFFLOAD))
330+
tso_fts |= NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM;
331+
332+
/* LRO is disabled by default, only set hw features */
333+
if (hinic3_test_support(nic_dev, HINIC3_NIC_F_LRO))
334+
hw_features |= NETIF_F_LRO;
335+
336+
netdev->features |= dft_fts | cso_fts | tso_fts | vlan_fts;
337+
netdev->vlan_features |= dft_fts | cso_fts | tso_fts;
338+
hw_features |= netdev->hw_features | netdev->features;
339+
netdev->hw_features = hw_features;
340+
netdev->priv_flags |= IFF_UNICAST_FLT;
341+
342+
netdev->hw_enc_features |= dft_fts;
343+
if (hinic3_test_support(nic_dev, HINIC3_NIC_F_VXLAN_OFFLOAD))
344+
netdev->hw_enc_features |= cso_fts | tso_fts | NETIF_F_TSO_ECN;
254345
}
255346

256347
static int hinic3_set_default_hw_feature(struct net_device *netdev)
@@ -275,6 +366,36 @@ static int hinic3_set_default_hw_feature(struct net_device *netdev)
275366
return 0;
276367
}
277368

369+
static void hinic3_register_notifier(struct net_device *netdev)
370+
{
371+
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
372+
int err;
373+
374+
mutex_lock(&hinic3_netdev_notifiers_mutex);
375+
hinic3_netdev_notifiers_ref_cnt++;
376+
if (hinic3_netdev_notifiers_ref_cnt == 1) {
377+
err = register_netdevice_notifier(&hinic3_netdev_notifier);
378+
if (err) {
379+
dev_dbg(nic_dev->hwdev->dev,
380+
"Register netdevice notifier failed, err: %d\n",
381+
err);
382+
hinic3_netdev_notifiers_ref_cnt--;
383+
}
384+
}
385+
mutex_unlock(&hinic3_netdev_notifiers_mutex);
386+
}
387+
388+
static void hinic3_unregister_notifier(void)
389+
{
390+
mutex_lock(&hinic3_netdev_notifiers_mutex);
391+
if (hinic3_netdev_notifiers_ref_cnt == 1)
392+
unregister_netdevice_notifier(&hinic3_netdev_notifier);
393+
394+
if (hinic3_netdev_notifiers_ref_cnt)
395+
hinic3_netdev_notifiers_ref_cnt--;
396+
mutex_unlock(&hinic3_netdev_notifiers_mutex);
397+
}
398+
278399
static void hinic3_link_status_change(struct net_device *netdev,
279400
bool link_status_up)
280401
{
@@ -297,6 +418,42 @@ static void hinic3_link_status_change(struct net_device *netdev,
297418
}
298419
}
299420

421+
static void hinic3_port_module_event_handler(struct net_device *netdev,
422+
struct hinic3_event_info *event)
423+
{
424+
const char *g_hinic3_module_link_err[LINK_ERR_NUM] = { "Unrecognized module" };
425+
struct hinic3_port_module_event *module_event;
426+
enum port_module_event_type type;
427+
enum link_err_type err_type;
428+
429+
module_event = (struct hinic3_port_module_event *)event->event_data;
430+
type = module_event->type;
431+
err_type = module_event->err_type;
432+
433+
switch (type) {
434+
case HINIC3_PORT_MODULE_CABLE_PLUGGED:
435+
case HINIC3_PORT_MODULE_CABLE_UNPLUGGED:
436+
netdev_info(netdev, "Port module event: Cable %s\n",
437+
type == HINIC3_PORT_MODULE_CABLE_PLUGGED ?
438+
"plugged" : "unplugged");
439+
break;
440+
case HINIC3_PORT_MODULE_LINK_ERR:
441+
if (err_type >= LINK_ERR_NUM) {
442+
netdev_info(netdev, "Link failed, Unknown error type: 0x%x\n",
443+
err_type);
444+
} else {
445+
netdev_info(netdev,
446+
"Link failed, error type: 0x%x: %s\n",
447+
err_type,
448+
g_hinic3_module_link_err[err_type]);
449+
}
450+
break;
451+
default:
452+
netdev_err(netdev, "Unknown port module type %d\n", type);
453+
break;
454+
}
455+
}
456+
300457
static void hinic3_nic_event(struct auxiliary_device *adev,
301458
struct hinic3_event_info *event)
302459
{
@@ -310,8 +467,20 @@ static void hinic3_nic_event(struct auxiliary_device *adev,
310467
HINIC3_NIC_EVENT_LINK_UP):
311468
hinic3_link_status_change(netdev, true);
312469
break;
470+
case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_NIC,
471+
HINIC3_NIC_EVENT_PORT_MODULE_EVENT):
472+
hinic3_port_module_event_handler(netdev, event);
473+
break;
313474
case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_NIC,
314475
HINIC3_NIC_EVENT_LINK_DOWN):
476+
case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_COMM,
477+
HINIC3_COMM_EVENT_FAULT):
478+
case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_COMM,
479+
HINIC3_COMM_EVENT_PCIE_LINK_DOWN):
480+
case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_COMM,
481+
HINIC3_COMM_EVENT_HEART_LOST):
482+
case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_COMM,
483+
HINIC3_COMM_EVENT_MGMT_WATCHDOG):
315484
hinic3_link_status_change(netdev, false);
316485
break;
317486
default:
@@ -359,7 +528,7 @@ static int hinic3_nic_probe(struct auxiliary_device *adev,
359528

360529
err = hinic3_init_nic_io(nic_dev);
361530
if (err)
362-
goto err_free_netdev;
531+
goto err_free_nic_dev;
363532

364533
err = hinic3_sw_init(netdev);
365534
if (err)
@@ -372,6 +541,8 @@ static int hinic3_nic_probe(struct auxiliary_device *adev,
372541
if (err)
373542
goto err_uninit_sw;
374543

544+
hinic3_register_notifier(netdev);
545+
375546
queue_delayed_work(nic_dev->workq, &nic_dev->periodic_work, HZ);
376547
netif_carrier_off(netdev);
377548

@@ -382,6 +553,7 @@ static int hinic3_nic_probe(struct auxiliary_device *adev,
382553
return 0;
383554

384555
err_uninit_nic_feature:
556+
hinic3_unregister_notifier();
385557
hinic3_update_nic_feature(nic_dev, 0);
386558
hinic3_set_nic_feature_to_hw(nic_dev);
387559

@@ -390,7 +562,8 @@ static int hinic3_nic_probe(struct auxiliary_device *adev,
390562

391563
err_free_nic_io:
392564
hinic3_free_nic_io(nic_dev);
393-
565+
err_free_nic_dev:
566+
hinic3_free_nic_dev(netdev);
394567
err_free_netdev:
395568
free_netdev(netdev);
396569

@@ -411,6 +584,7 @@ static void hinic3_nic_remove(struct auxiliary_device *adev)
411584

412585
netdev = nic_dev->netdev;
413586
unregister_netdev(netdev);
587+
hinic3_unregister_notifier();
414588

415589
disable_delayed_work_sync(&nic_dev->periodic_work);
416590
cancel_work_sync(&nic_dev->rx_mode_work);

drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,11 @@ static int hinic3_open(struct net_device *netdev)
435435
struct hinic3_dyna_qp_params qp_params;
436436
int err;
437437

438+
if (test_bit(HINIC3_INTF_UP, &nic_dev->flags)) {
439+
netdev_dbg(netdev, "Netdev already open, do nothing\n");
440+
return 0;
441+
}
442+
438443
err = hinic3_init_nicio_res(nic_dev);
439444
if (err) {
440445
netdev_err(netdev, "Failed to init nicio resources\n");
@@ -462,6 +467,8 @@ static int hinic3_open(struct net_device *netdev)
462467
if (err)
463468
goto err_close_channel;
464469

470+
set_bit(HINIC3_INTF_UP, &nic_dev->flags);
471+
465472
return 0;
466473

467474
err_close_channel:
@@ -482,6 +489,11 @@ static int hinic3_close(struct net_device *netdev)
482489
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
483490
struct hinic3_dyna_qp_params qp_params;
484491

492+
if (!test_and_clear_bit(HINIC3_INTF_UP, &nic_dev->flags)) {
493+
netdev_dbg(netdev, "Netdev already close, do nothing\n");
494+
return 0;
495+
}
496+
485497
hinic3_vport_down(netdev);
486498
hinic3_close_channel(netdev);
487499
hinic3_uninit_qps(nic_dev, &qp_params);

drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct hinic3_nic_dev;
2222
enum hinic3_nic_event_type {
2323
HINIC3_NIC_EVENT_LINK_DOWN = 0,
2424
HINIC3_NIC_EVENT_LINK_UP = 1,
25+
HINIC3_NIC_EVENT_PORT_MODULE_EVENT = 2,
2526
};
2627

2728
struct hinic3_sq_attr {
@@ -51,6 +52,23 @@ struct mag_cmd_set_port_enable {
5152
u8 rsvd1[3];
5253
};
5354

55+
enum link_err_type {
56+
LINK_ERR_MODULE_UNRECOGENIZED,
57+
LINK_ERR_NUM,
58+
};
59+
60+
enum port_module_event_type {
61+
HINIC3_PORT_MODULE_CABLE_PLUGGED,
62+
HINIC3_PORT_MODULE_CABLE_UNPLUGGED,
63+
HINIC3_PORT_MODULE_LINK_ERR,
64+
HINIC3_PORT_MODULE_MAX_EVENT,
65+
};
66+
67+
struct hinic3_port_module_event {
68+
enum port_module_event_type type;
69+
enum link_err_type err_type;
70+
};
71+
5472
int hinic3_get_nic_feature_from_hw(struct hinic3_nic_dev *nic_dev);
5573
int hinic3_set_nic_feature_to_hw(struct hinic3_nic_dev *nic_dev);
5674
bool hinic3_test_support(struct hinic3_nic_dev *nic_dev,

drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#define HINIC3_MODERATONE_DELAY HZ
1818

1919
enum hinic3_flags {
20+
HINIC3_INTF_UP,
2021
HINIC3_MAC_FILTER_CHANGED,
2122
HINIC3_RSS_ENABLE,
2223
HINIC3_UPDATE_MAC_FILTER,
@@ -119,6 +120,7 @@ struct hinic3_intr_coal_info {
119120
struct hinic3_nic_dev {
120121
struct pci_dev *pdev;
121122
struct net_device *netdev;
123+
netdevice_tracker tracker;
122124
struct hinic3_hwdev *hwdev;
123125
struct hinic3_nic_io *nic_io;
124126

0 commit comments

Comments
 (0)