Skip to content

Commit 41ccedf

Browse files
dmertmananguy11
authored andcommitted
ice: implement lag netdev event handler
The event handler for LAG will create a work item to place on the ordered workqueue to be processed. Add in defines for training packets and new recipes to be used by the switching block of the HW for LAG packet steering. Update the ice_lag struct to reflect the new processing methodology. Signed-off-by: Dave Ertman <[email protected]> Tested-by: Sujai Buvaneswaran <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent 23ccae5 commit 41ccedf

File tree

2 files changed

+140
-14
lines changed

2 files changed

+140
-14
lines changed

drivers/net/ethernet/intel/ice/ice_lag.c

Lines changed: 111 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,10 @@ static void ice_lag_set_backup(struct ice_lag *lag)
5656
*/
5757
static void ice_display_lag_info(struct ice_lag *lag)
5858
{
59-
const char *name, *peer, *upper, *role, *bonded, *primary;
59+
const char *name, *upper, *role, *bonded, *primary;
6060
struct device *dev = &lag->pf->pdev->dev;
6161

6262
name = lag->netdev ? netdev_name(lag->netdev) : "unset";
63-
peer = lag->peer_netdev ? netdev_name(lag->peer_netdev) : "unset";
6463
upper = lag->upper_netdev ? netdev_name(lag->upper_netdev) : "unset";
6564
primary = lag->primary ? "TRUE" : "FALSE";
6665
bonded = lag->bonded ? "BONDED" : "UNBONDED";
@@ -82,8 +81,8 @@ static void ice_display_lag_info(struct ice_lag *lag)
8281
role = "ERROR";
8382
}
8483

85-
dev_dbg(dev, "%s %s, peer:%s, upper:%s, role:%s, primary:%s\n", name,
86-
bonded, peer, upper, role, primary);
84+
dev_dbg(dev, "%s %s, upper:%s, role:%s, primary:%s\n", name, bonded,
85+
upper, role, primary);
8786
}
8887

8988
/**
@@ -198,7 +197,6 @@ ice_lag_unlink(struct ice_lag *lag,
198197
lag->upper_netdev = NULL;
199198
}
200199

201-
lag->peer_netdev = NULL;
202200
ice_set_rdma_cap(pf);
203201
lag->bonded = false;
204202
lag->role = ICE_LAG_NONE;
@@ -288,6 +286,59 @@ static void ice_lag_changeupper_event(struct ice_lag *lag, void *ptr)
288286
ice_display_lag_info(lag);
289287
}
290288

289+
/**
290+
* ice_lag_process_event - process a task assigned to the lag_wq
291+
* @work: pointer to work_struct
292+
*/
293+
static void ice_lag_process_event(struct work_struct *work)
294+
{
295+
struct netdev_notifier_changeupper_info *info;
296+
struct ice_lag_work *lag_work;
297+
struct net_device *netdev;
298+
struct list_head *tmp, *n;
299+
struct ice_pf *pf;
300+
301+
lag_work = container_of(work, struct ice_lag_work, lag_task);
302+
pf = lag_work->lag->pf;
303+
304+
mutex_lock(&pf->lag_mutex);
305+
lag_work->lag->netdev_head = &lag_work->netdev_list.node;
306+
307+
switch (lag_work->event) {
308+
case NETDEV_CHANGEUPPER:
309+
info = &lag_work->info.changeupper_info;
310+
ice_lag_changeupper_event(lag_work->lag, info);
311+
break;
312+
case NETDEV_BONDING_INFO:
313+
ice_lag_info_event(lag_work->lag, &lag_work->info.bonding_info);
314+
break;
315+
case NETDEV_UNREGISTER:
316+
if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG)) {
317+
netdev = lag_work->info.bonding_info.info.dev;
318+
if ((netdev == lag_work->lag->netdev ||
319+
lag_work->lag->primary) && lag_work->lag->bonded)
320+
ice_lag_unregister(lag_work->lag, netdev);
321+
}
322+
break;
323+
default:
324+
break;
325+
}
326+
327+
/* cleanup resources allocated for this work item */
328+
list_for_each_safe(tmp, n, &lag_work->netdev_list.node) {
329+
struct ice_lag_netdev_list *entry;
330+
331+
entry = list_entry(tmp, struct ice_lag_netdev_list, node);
332+
list_del(&entry->node);
333+
kfree(entry);
334+
}
335+
lag_work->lag->netdev_head = NULL;
336+
337+
mutex_unlock(&pf->lag_mutex);
338+
339+
kfree(lag_work);
340+
}
341+
291342
/**
292343
* ice_lag_event_handler - handle LAG events from netdev
293344
* @notif_blk: notifier block registered by this netdev
@@ -299,31 +350,79 @@ ice_lag_event_handler(struct notifier_block *notif_blk, unsigned long event,
299350
void *ptr)
300351
{
301352
struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
353+
struct net_device *upper_netdev;
354+
struct ice_lag_work *lag_work;
302355
struct ice_lag *lag;
303356

304-
lag = container_of(notif_blk, struct ice_lag, notif_block);
357+
if (!netif_is_ice(netdev))
358+
return NOTIFY_DONE;
359+
360+
if (event != NETDEV_CHANGEUPPER && event != NETDEV_BONDING_INFO &&
361+
event != NETDEV_UNREGISTER)
362+
return NOTIFY_DONE;
305363

364+
if (!(netdev->priv_flags & IFF_BONDING))
365+
return NOTIFY_DONE;
366+
367+
lag = container_of(notif_blk, struct ice_lag, notif_block);
306368
if (!lag->netdev)
307369
return NOTIFY_DONE;
308370

309-
/* Check that the netdev is in the working namespace */
310371
if (!net_eq(dev_net(netdev), &init_net))
311372
return NOTIFY_DONE;
312373

374+
/* This memory will be freed at the end of ice_lag_process_event */
375+
lag_work = kzalloc(sizeof(*lag_work), GFP_KERNEL);
376+
if (!lag_work)
377+
return -ENOMEM;
378+
379+
lag_work->event_netdev = netdev;
380+
lag_work->lag = lag;
381+
lag_work->event = event;
382+
if (event == NETDEV_CHANGEUPPER) {
383+
struct netdev_notifier_changeupper_info *info;
384+
385+
info = ptr;
386+
upper_netdev = info->upper_dev;
387+
} else {
388+
upper_netdev = netdev_master_upper_dev_get(netdev);
389+
}
390+
391+
INIT_LIST_HEAD(&lag_work->netdev_list.node);
392+
if (upper_netdev) {
393+
struct ice_lag_netdev_list *nd_list;
394+
struct net_device *tmp_nd;
395+
396+
rcu_read_lock();
397+
for_each_netdev_in_bond_rcu(upper_netdev, tmp_nd) {
398+
nd_list = kzalloc(sizeof(*nd_list), GFP_KERNEL);
399+
if (!nd_list)
400+
break;
401+
402+
nd_list->netdev = tmp_nd;
403+
list_add(&nd_list->node, &lag_work->netdev_list.node);
404+
}
405+
rcu_read_unlock();
406+
}
407+
313408
switch (event) {
314409
case NETDEV_CHANGEUPPER:
315-
ice_lag_changeupper_event(lag, ptr);
410+
lag_work->info.changeupper_info =
411+
*((struct netdev_notifier_changeupper_info *)ptr);
316412
break;
317413
case NETDEV_BONDING_INFO:
318-
ice_lag_info_event(lag, ptr);
319-
break;
320-
case NETDEV_UNREGISTER:
321-
ice_lag_unregister(lag, netdev);
414+
lag_work->info.bonding_info =
415+
*((struct netdev_notifier_bonding_info *)ptr);
322416
break;
323417
default:
418+
lag_work->info.notifier_info =
419+
*((struct netdev_notifier_info *)ptr);
324420
break;
325421
}
326422

423+
INIT_WORK(&lag_work->lag_task, ice_lag_process_event);
424+
queue_work(ice_lag_wq, &lag_work->lag_task);
425+
327426
return NOTIFY_DONE;
328427
}
329428

@@ -398,7 +497,6 @@ int ice_init_lag(struct ice_pf *pf)
398497
lag->netdev = vsi->netdev;
399498
lag->role = ICE_LAG_NONE;
400499
lag->bonded = false;
401-
lag->peer_netdev = NULL;
402500
lag->upper_netdev = NULL;
403501
lag->notif_block.notifier_call = NULL;
404502

drivers/net/ethernet/intel/ice/ice_lag.h

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,48 @@ enum ice_lag_role {
1414
ICE_LAG_UNSET
1515
};
1616

17+
#define ICE_LAG_INVALID_PORT 0xFF
18+
1719
struct ice_pf;
20+
struct ice_vf;
21+
22+
struct ice_lag_netdev_list {
23+
struct list_head node;
24+
struct net_device *netdev;
25+
};
1826

1927
/* LAG info struct */
2028
struct ice_lag {
2129
struct ice_pf *pf; /* backlink to PF struct */
2230
struct net_device *netdev; /* this PF's netdev */
23-
struct net_device *peer_netdev;
2431
struct net_device *upper_netdev; /* upper bonding netdev */
32+
struct list_head *netdev_head;
2533
struct notifier_block notif_block;
34+
s32 bond_mode;
35+
u16 bond_swid; /* swid for primary interface */
36+
u8 active_port; /* lport value for the current active port */
2637
u8 bonded:1; /* currently bonded */
2738
u8 primary:1; /* this is primary */
39+
u16 pf_recipe;
40+
u16 pf_rule_id;
41+
u16 cp_rule_idx;
2842
u8 role;
2943
};
3044

45+
/* LAG workqueue struct */
46+
struct ice_lag_work {
47+
struct work_struct lag_task;
48+
struct ice_lag_netdev_list netdev_list;
49+
struct ice_lag *lag;
50+
unsigned long event;
51+
struct net_device *event_netdev;
52+
union {
53+
struct netdev_notifier_changeupper_info changeupper_info;
54+
struct netdev_notifier_bonding_info bonding_info;
55+
struct netdev_notifier_info notifier_info;
56+
} info;
57+
};
58+
3159
int ice_init_lag(struct ice_pf *pf);
3260
void ice_deinit_lag(struct ice_pf *pf);
3361
#endif /* _ICE_LAG_H_ */

0 commit comments

Comments
 (0)