xref: /linux/drivers/net/ethernet/netronome/nfp/flower/lag_conf.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2018 Netronome Systems, Inc. */
3 
4 #include "main.h"
5 
6 /* LAG group config flags. */
7 #define NFP_FL_LAG_LAST			BIT(1)
8 #define NFP_FL_LAG_FIRST		BIT(2)
9 #define NFP_FL_LAG_DATA			BIT(3)
10 #define NFP_FL_LAG_XON			BIT(4)
11 #define NFP_FL_LAG_SYNC			BIT(5)
12 #define NFP_FL_LAG_SWITCH		BIT(6)
13 #define NFP_FL_LAG_RESET		BIT(7)
14 
15 /* LAG port state flags. */
16 #define NFP_PORT_LAG_LINK_UP		BIT(0)
17 #define NFP_PORT_LAG_TX_ENABLED		BIT(1)
18 #define NFP_PORT_LAG_CHANGED		BIT(2)
19 
20 enum nfp_fl_lag_batch {
21 	NFP_FL_LAG_BATCH_FIRST,
22 	NFP_FL_LAG_BATCH_MEMBER,
23 	NFP_FL_LAG_BATCH_FINISHED
24 };
25 
26 /**
27  * struct nfp_flower_cmsg_lag_config - control message payload for LAG config
28  * @ctrl_flags:	Configuration flags
29  * @reserved:	Reserved for future use
30  * @ttl:	Time to live of packet - host always sets to 0xff
31  * @pkt_number:	Config message packet number - increment for each message
32  * @batch_ver:	Batch version of messages - increment for each batch of messages
33  * @group_id:	Group ID applicable
34  * @group_inst:	Group instance number - increment when group is reused
35  * @members:	Array of 32-bit words listing all active group members
36  */
37 struct nfp_flower_cmsg_lag_config {
38 	u8 ctrl_flags;
39 	u8 reserved[2];
40 	u8 ttl;
41 	__be32 pkt_number;
42 	__be32 batch_ver;
43 	__be32 group_id;
44 	__be32 group_inst;
45 	__be32 members[];
46 };
47 
48 /**
49  * struct nfp_fl_lag_group - list entry for each LAG group
50  * @group_id:		Assigned group ID for host/kernel sync
51  * @group_inst:		Group instance in case of ID reuse
52  * @list:		List entry
53  * @master_ndev:	Group master Netdev
54  * @dirty:		Marked if the group needs synced to HW
55  * @offloaded:		Marked if the group is currently offloaded to NIC
56  * @to_remove:		Marked if the group should be removed from NIC
57  * @to_destroy:		Marked if the group should be removed from driver
58  * @slave_cnt:		Number of slaves in group
59  */
60 struct nfp_fl_lag_group {
61 	unsigned int group_id;
62 	u8 group_inst;
63 	struct list_head list;
64 	struct net_device *master_ndev;
65 	bool dirty;
66 	bool offloaded;
67 	bool to_remove;
68 	bool to_destroy;
69 	unsigned int slave_cnt;
70 };
71 
72 #define NFP_FL_LAG_PKT_NUMBER_MASK	GENMASK(30, 0)
73 #define NFP_FL_LAG_VERSION_MASK		GENMASK(22, 0)
74 #define NFP_FL_LAG_HOST_TTL		0xff
75 
76 /* Use this ID with zero members to ack a batch config */
77 #define NFP_FL_LAG_SYNC_ID		0
78 #define NFP_FL_LAG_GROUP_MIN		1 /* ID 0 reserved */
79 #define NFP_FL_LAG_GROUP_MAX		31 /* IDs 1 to 31 are valid */
80 
81 /* wait for more config */
82 #define NFP_FL_LAG_DELAY		(msecs_to_jiffies(2))
83 
84 #define NFP_FL_LAG_RETRANS_LIMIT	100 /* max retrans cmsgs to store */
85 
86 static unsigned int nfp_fl_get_next_pkt_number(struct nfp_fl_lag *lag)
87 {
88 	lag->pkt_num++;
89 	lag->pkt_num &= NFP_FL_LAG_PKT_NUMBER_MASK;
90 
91 	return lag->pkt_num;
92 }
93 
94 static void nfp_fl_increment_version(struct nfp_fl_lag *lag)
95 {
96 	/* LSB is not considered by firmware so add 2 for each increment. */
97 	lag->batch_ver += 2;
98 	lag->batch_ver &= NFP_FL_LAG_VERSION_MASK;
99 
100 	/* Zero is reserved by firmware. */
101 	if (!lag->batch_ver)
102 		lag->batch_ver += 2;
103 }
104 
105 static struct nfp_fl_lag_group *
106 nfp_fl_lag_group_create(struct nfp_fl_lag *lag, struct net_device *master)
107 {
108 	struct nfp_fl_lag_group *group;
109 	struct nfp_flower_priv *priv;
110 	int id;
111 
112 	priv = container_of(lag, struct nfp_flower_priv, nfp_lag);
113 
114 	id = ida_alloc_range(&lag->ida_handle, NFP_FL_LAG_GROUP_MIN,
115 			     NFP_FL_LAG_GROUP_MAX, GFP_KERNEL);
116 	if (id < 0) {
117 		nfp_flower_cmsg_warn(priv->app,
118 				     "No more bonding groups available\n");
119 		return ERR_PTR(id);
120 	}
121 
122 	group = kmalloc(sizeof(*group), GFP_KERNEL);
123 	if (!group) {
124 		ida_free(&lag->ida_handle, id);
125 		return ERR_PTR(-ENOMEM);
126 	}
127 
128 	group->group_id = id;
129 	group->master_ndev = master;
130 	group->dirty = true;
131 	group->offloaded = false;
132 	group->to_remove = false;
133 	group->to_destroy = false;
134 	group->slave_cnt = 0;
135 	group->group_inst = ++lag->global_inst;
136 	list_add_tail(&group->list, &lag->group_list);
137 
138 	return group;
139 }
140 
141 static struct nfp_fl_lag_group *
142 nfp_fl_lag_find_group_for_master_with_lag(struct nfp_fl_lag *lag,
143 					  struct net_device *master)
144 {
145 	struct nfp_fl_lag_group *entry;
146 
147 	if (!master)
148 		return NULL;
149 
150 	list_for_each_entry(entry, &lag->group_list, list)
151 		if (entry->master_ndev == master)
152 			return entry;
153 
154 	return NULL;
155 }
156 
157 static int nfp_fl_lag_get_group_info(struct nfp_app *app,
158 				     struct net_device *netdev,
159 				     __be16 *group_id,
160 				     u8 *batch_ver,
161 				     u8 *group_inst)
162 {
163 	struct nfp_flower_priv *priv = app->priv;
164 	struct nfp_fl_lag_group *group = NULL;
165 	__be32 temp_vers;
166 
167 	mutex_lock(&priv->nfp_lag.lock);
168 	group = nfp_fl_lag_find_group_for_master_with_lag(&priv->nfp_lag,
169 							  netdev);
170 	if (!group) {
171 		mutex_unlock(&priv->nfp_lag.lock);
172 		return -ENOENT;
173 	}
174 
175 	if (group_id)
176 		*group_id = cpu_to_be16(group->group_id);
177 
178 	if (batch_ver) {
179 		temp_vers = cpu_to_be32(priv->nfp_lag.batch_ver <<
180 					NFP_FL_PRE_LAG_VER_OFF);
181 		memcpy(batch_ver, &temp_vers, 3);
182 	}
183 
184 	if (group_inst)
185 		*group_inst = group->group_inst;
186 
187 	mutex_unlock(&priv->nfp_lag.lock);
188 
189 	return 0;
190 }
191 
192 int nfp_flower_lag_populate_pre_action(struct nfp_app *app,
193 				       struct net_device *master,
194 				       struct nfp_fl_pre_lag *pre_act,
195 				       struct netlink_ext_ack *extack)
196 {
197 	if (nfp_fl_lag_get_group_info(app, master, &pre_act->group_id,
198 				      pre_act->lag_version,
199 				      &pre_act->instance)) {
200 		NL_SET_ERR_MSG_MOD(extack, "invalid entry: group does not exist for LAG action");
201 		return -ENOENT;
202 	}
203 
204 	return 0;
205 }
206 
207 void nfp_flower_lag_get_info_from_netdev(struct nfp_app *app,
208 					 struct net_device *netdev,
209 					 struct nfp_tun_neigh_lag *lag)
210 {
211 	nfp_fl_lag_get_group_info(app, netdev, NULL,
212 				  lag->lag_version, &lag->lag_instance);
213 }
214 
215 int nfp_flower_lag_get_output_id(struct nfp_app *app, struct net_device *master)
216 {
217 	struct nfp_flower_priv *priv = app->priv;
218 	struct nfp_fl_lag_group *group = NULL;
219 	int group_id = -ENOENT;
220 
221 	mutex_lock(&priv->nfp_lag.lock);
222 	group = nfp_fl_lag_find_group_for_master_with_lag(&priv->nfp_lag,
223 							  master);
224 	if (group)
225 		group_id = group->group_id;
226 	mutex_unlock(&priv->nfp_lag.lock);
227 
228 	return group_id;
229 }
230 
231 static int
232 nfp_fl_lag_config_group(struct nfp_fl_lag *lag, struct nfp_fl_lag_group *group,
233 			struct net_device **active_members,
234 			unsigned int member_cnt, enum nfp_fl_lag_batch *batch)
235 {
236 	struct nfp_flower_cmsg_lag_config *cmsg_payload;
237 	struct nfp_flower_priv *priv;
238 	unsigned long int flags;
239 	unsigned int size, i;
240 	struct sk_buff *skb;
241 
242 	priv = container_of(lag, struct nfp_flower_priv, nfp_lag);
243 	size = sizeof(*cmsg_payload) + sizeof(__be32) * member_cnt;
244 	skb = nfp_flower_cmsg_alloc(priv->app, size,
245 				    NFP_FLOWER_CMSG_TYPE_LAG_CONFIG,
246 				    GFP_KERNEL);
247 	if (!skb)
248 		return -ENOMEM;
249 
250 	cmsg_payload = nfp_flower_cmsg_get_data(skb);
251 	flags = 0;
252 
253 	/* Increment batch version for each new batch of config messages. */
254 	if (*batch == NFP_FL_LAG_BATCH_FIRST) {
255 		flags |= NFP_FL_LAG_FIRST;
256 		nfp_fl_increment_version(lag);
257 		*batch = NFP_FL_LAG_BATCH_MEMBER;
258 	}
259 
260 	/* If it is a reset msg then it is also the end of the batch. */
261 	if (lag->rst_cfg) {
262 		flags |= NFP_FL_LAG_RESET;
263 		*batch = NFP_FL_LAG_BATCH_FINISHED;
264 	}
265 
266 	/* To signal the end of a batch, both the switch and last flags are set
267 	 * and the reserved SYNC group ID is used.
268 	 */
269 	if (*batch == NFP_FL_LAG_BATCH_FINISHED) {
270 		flags |= NFP_FL_LAG_SWITCH | NFP_FL_LAG_LAST;
271 		lag->rst_cfg = false;
272 		cmsg_payload->group_id = cpu_to_be32(NFP_FL_LAG_SYNC_ID);
273 		cmsg_payload->group_inst = 0;
274 	} else {
275 		cmsg_payload->group_id = cpu_to_be32(group->group_id);
276 		cmsg_payload->group_inst = cpu_to_be32(group->group_inst);
277 	}
278 
279 	cmsg_payload->reserved[0] = 0;
280 	cmsg_payload->reserved[1] = 0;
281 	cmsg_payload->ttl = NFP_FL_LAG_HOST_TTL;
282 	cmsg_payload->ctrl_flags = flags;
283 	cmsg_payload->batch_ver = cpu_to_be32(lag->batch_ver);
284 	cmsg_payload->pkt_number = cpu_to_be32(nfp_fl_get_next_pkt_number(lag));
285 
286 	for (i = 0; i < member_cnt; i++)
287 		cmsg_payload->members[i] =
288 			cpu_to_be32(nfp_repr_get_port_id(active_members[i]));
289 
290 	nfp_ctrl_tx(priv->app->ctrl, skb);
291 	return 0;
292 }
293 
294 static void nfp_fl_lag_do_work(struct work_struct *work)
295 {
296 	enum nfp_fl_lag_batch batch = NFP_FL_LAG_BATCH_FIRST;
297 	struct nfp_fl_lag_group *entry, *storage;
298 	struct delayed_work *delayed_work;
299 	struct nfp_flower_priv *priv;
300 	struct nfp_fl_lag *lag;
301 	int err;
302 
303 	delayed_work = to_delayed_work(work);
304 	lag = container_of(delayed_work, struct nfp_fl_lag, work);
305 	priv = container_of(lag, struct nfp_flower_priv, nfp_lag);
306 
307 	mutex_lock(&lag->lock);
308 	list_for_each_entry_safe(entry, storage, &lag->group_list, list) {
309 		struct net_device *iter_netdev, **acti_netdevs;
310 		struct nfp_flower_repr_priv *repr_priv;
311 		int active_count = 0, slaves = 0;
312 		struct nfp_repr *repr;
313 		unsigned long *flags;
314 
315 		if (entry->to_remove) {
316 			/* Active count of 0 deletes group on hw. */
317 			err = nfp_fl_lag_config_group(lag, entry, NULL, 0,
318 						      &batch);
319 			if (!err) {
320 				entry->to_remove = false;
321 				entry->offloaded = false;
322 			} else {
323 				nfp_flower_cmsg_warn(priv->app,
324 						     "group delete failed\n");
325 				schedule_delayed_work(&lag->work,
326 						      NFP_FL_LAG_DELAY);
327 				continue;
328 			}
329 
330 			if (entry->to_destroy) {
331 				ida_free(&lag->ida_handle, entry->group_id);
332 				list_del(&entry->list);
333 				kfree(entry);
334 			}
335 			continue;
336 		}
337 
338 		acti_netdevs = kmalloc_array(entry->slave_cnt,
339 					     sizeof(*acti_netdevs), GFP_KERNEL);
340 		if (!acti_netdevs) {
341 			schedule_delayed_work(&lag->work,
342 					      NFP_FL_LAG_DELAY);
343 			continue;
344 		}
345 
346 		/* Include sanity check in the loop. It may be that a bond has
347 		 * changed between processing the last notification and the
348 		 * work queue triggering. If the number of slaves has changed
349 		 * or it now contains netdevs that cannot be offloaded, ignore
350 		 * the group until pending notifications are processed.
351 		 */
352 		rcu_read_lock();
353 		for_each_netdev_in_bond_rcu(entry->master_ndev, iter_netdev) {
354 			if (!nfp_netdev_is_nfp_repr(iter_netdev)) {
355 				slaves = 0;
356 				break;
357 			}
358 
359 			repr = netdev_priv(iter_netdev);
360 
361 			if (repr->app != priv->app) {
362 				slaves = 0;
363 				break;
364 			}
365 
366 			slaves++;
367 			if (slaves > entry->slave_cnt)
368 				break;
369 
370 			/* Check the ports for state changes. */
371 			repr_priv = repr->app_priv;
372 			flags = &repr_priv->lag_port_flags;
373 
374 			if (*flags & NFP_PORT_LAG_CHANGED) {
375 				*flags &= ~NFP_PORT_LAG_CHANGED;
376 				entry->dirty = true;
377 			}
378 
379 			if ((*flags & NFP_PORT_LAG_TX_ENABLED) &&
380 			    (*flags & NFP_PORT_LAG_LINK_UP))
381 				acti_netdevs[active_count++] = iter_netdev;
382 		}
383 		rcu_read_unlock();
384 
385 		if (slaves != entry->slave_cnt || !entry->dirty) {
386 			kfree(acti_netdevs);
387 			continue;
388 		}
389 
390 		err = nfp_fl_lag_config_group(lag, entry, acti_netdevs,
391 					      active_count, &batch);
392 		if (!err) {
393 			entry->offloaded = true;
394 			entry->dirty = false;
395 		} else {
396 			nfp_flower_cmsg_warn(priv->app,
397 					     "group offload failed\n");
398 			schedule_delayed_work(&lag->work, NFP_FL_LAG_DELAY);
399 		}
400 
401 		kfree(acti_netdevs);
402 	}
403 
404 	/* End the config batch if at least one packet has been batched. */
405 	if (batch == NFP_FL_LAG_BATCH_MEMBER) {
406 		batch = NFP_FL_LAG_BATCH_FINISHED;
407 		err = nfp_fl_lag_config_group(lag, NULL, NULL, 0, &batch);
408 		if (err)
409 			nfp_flower_cmsg_warn(priv->app,
410 					     "group batch end cmsg failed\n");
411 	}
412 
413 	mutex_unlock(&lag->lock);
414 }
415 
416 static int
417 nfp_fl_lag_put_unprocessed(struct nfp_fl_lag *lag, struct sk_buff *skb)
418 {
419 	struct nfp_flower_cmsg_lag_config *cmsg_payload;
420 
421 	cmsg_payload = nfp_flower_cmsg_get_data(skb);
422 	if (be32_to_cpu(cmsg_payload->group_id) > NFP_FL_LAG_GROUP_MAX)
423 		return -EINVAL;
424 
425 	/* Drop cmsg retrans if storage limit is exceeded to prevent
426 	 * overloading. If the fw notices that expected messages have not been
427 	 * received in a given time block, it will request a full resync.
428 	 */
429 	if (skb_queue_len(&lag->retrans_skbs) >= NFP_FL_LAG_RETRANS_LIMIT)
430 		return -ENOSPC;
431 
432 	__skb_queue_tail(&lag->retrans_skbs, skb);
433 
434 	return 0;
435 }
436 
437 static void nfp_fl_send_unprocessed(struct nfp_fl_lag *lag)
438 {
439 	struct nfp_flower_priv *priv;
440 	struct sk_buff *skb;
441 
442 	priv = container_of(lag, struct nfp_flower_priv, nfp_lag);
443 
444 	while ((skb = __skb_dequeue(&lag->retrans_skbs)))
445 		nfp_ctrl_tx(priv->app->ctrl, skb);
446 }
447 
448 bool nfp_flower_lag_unprocessed_msg(struct nfp_app *app, struct sk_buff *skb)
449 {
450 	struct nfp_flower_cmsg_lag_config *cmsg_payload;
451 	struct nfp_flower_priv *priv = app->priv;
452 	struct nfp_fl_lag_group *group_entry;
453 	unsigned long int flags;
454 	bool store_skb = false;
455 	int err;
456 
457 	cmsg_payload = nfp_flower_cmsg_get_data(skb);
458 	flags = cmsg_payload->ctrl_flags;
459 
460 	/* Note the intentional fall through below. If DATA and XON are both
461 	 * set, the message will stored and sent again with the rest of the
462 	 * unprocessed messages list.
463 	 */
464 
465 	/* Store */
466 	if (flags & NFP_FL_LAG_DATA)
467 		if (!nfp_fl_lag_put_unprocessed(&priv->nfp_lag, skb))
468 			store_skb = true;
469 
470 	/* Send stored */
471 	if (flags & NFP_FL_LAG_XON)
472 		nfp_fl_send_unprocessed(&priv->nfp_lag);
473 
474 	/* Resend all */
475 	if (flags & NFP_FL_LAG_SYNC) {
476 		/* To resend all config:
477 		 * 1) Clear all unprocessed messages
478 		 * 2) Mark all groups dirty
479 		 * 3) Reset NFP group config
480 		 * 4) Schedule a LAG config update
481 		 */
482 
483 		__skb_queue_purge(&priv->nfp_lag.retrans_skbs);
484 
485 		mutex_lock(&priv->nfp_lag.lock);
486 		list_for_each_entry(group_entry, &priv->nfp_lag.group_list,
487 				    list)
488 			group_entry->dirty = true;
489 
490 		err = nfp_flower_lag_reset(&priv->nfp_lag);
491 		if (err)
492 			nfp_flower_cmsg_warn(priv->app,
493 					     "mem err in group reset msg\n");
494 		mutex_unlock(&priv->nfp_lag.lock);
495 
496 		schedule_delayed_work(&priv->nfp_lag.work, 0);
497 	}
498 
499 	return store_skb;
500 }
501 
502 static void
503 nfp_fl_lag_schedule_group_remove(struct nfp_fl_lag *lag,
504 				 struct nfp_fl_lag_group *group)
505 {
506 	group->to_remove = true;
507 
508 	schedule_delayed_work(&lag->work, NFP_FL_LAG_DELAY);
509 }
510 
511 static void
512 nfp_fl_lag_schedule_group_delete(struct nfp_fl_lag *lag,
513 				 struct net_device *master)
514 {
515 	struct nfp_fl_lag_group *group;
516 	struct nfp_flower_priv *priv;
517 
518 	priv = container_of(lag, struct nfp_flower_priv, nfp_lag);
519 
520 	if (!netif_is_bond_master(master))
521 		return;
522 
523 	mutex_lock(&lag->lock);
524 	group = nfp_fl_lag_find_group_for_master_with_lag(lag, master);
525 	if (!group) {
526 		mutex_unlock(&lag->lock);
527 		nfp_warn(priv->app->cpp, "untracked bond got unregistered %s\n",
528 			 netdev_name(master));
529 		return;
530 	}
531 
532 	group->to_remove = true;
533 	group->to_destroy = true;
534 	mutex_unlock(&lag->lock);
535 
536 	schedule_delayed_work(&lag->work, NFP_FL_LAG_DELAY);
537 }
538 
539 static int
540 nfp_fl_lag_changeupper_event(struct nfp_fl_lag *lag,
541 			     struct netdev_notifier_changeupper_info *info)
542 {
543 	struct net_device *upper = info->upper_dev, *iter_netdev;
544 	struct netdev_lag_upper_info *lag_upper_info;
545 	struct nfp_fl_lag_group *group;
546 	struct nfp_flower_priv *priv;
547 	unsigned int slave_count = 0;
548 	bool can_offload = true;
549 	struct nfp_repr *repr;
550 
551 	if (!netif_is_lag_master(upper))
552 		return 0;
553 
554 	priv = container_of(lag, struct nfp_flower_priv, nfp_lag);
555 
556 	rcu_read_lock();
557 	for_each_netdev_in_bond_rcu(upper, iter_netdev) {
558 		if (!nfp_netdev_is_nfp_repr(iter_netdev)) {
559 			can_offload = false;
560 			break;
561 		}
562 		repr = netdev_priv(iter_netdev);
563 
564 		/* Ensure all ports are created by the same app/on same card. */
565 		if (repr->app != priv->app) {
566 			can_offload = false;
567 			break;
568 		}
569 
570 		slave_count++;
571 	}
572 	rcu_read_unlock();
573 
574 	lag_upper_info = info->upper_info;
575 
576 	/* Firmware supports active/backup and L3/L4 hash bonds. */
577 	if (lag_upper_info &&
578 	    lag_upper_info->tx_type != NETDEV_LAG_TX_TYPE_ACTIVEBACKUP &&
579 	    (lag_upper_info->tx_type != NETDEV_LAG_TX_TYPE_HASH ||
580 	     (lag_upper_info->hash_type != NETDEV_LAG_HASH_L34 &&
581 	      lag_upper_info->hash_type != NETDEV_LAG_HASH_E34 &&
582 	      lag_upper_info->hash_type != NETDEV_LAG_HASH_UNKNOWN))) {
583 		can_offload = false;
584 		nfp_flower_cmsg_warn(priv->app,
585 				     "Unable to offload tx_type %u hash %u\n",
586 				     lag_upper_info->tx_type,
587 				     lag_upper_info->hash_type);
588 	}
589 
590 	mutex_lock(&lag->lock);
591 	group = nfp_fl_lag_find_group_for_master_with_lag(lag, upper);
592 
593 	if (slave_count == 0 || !can_offload) {
594 		/* Cannot offload the group - remove if previously offloaded. */
595 		if (group && group->offloaded)
596 			nfp_fl_lag_schedule_group_remove(lag, group);
597 
598 		mutex_unlock(&lag->lock);
599 		return 0;
600 	}
601 
602 	if (!group) {
603 		group = nfp_fl_lag_group_create(lag, upper);
604 		if (IS_ERR(group)) {
605 			mutex_unlock(&lag->lock);
606 			return PTR_ERR(group);
607 		}
608 	}
609 
610 	group->dirty = true;
611 	group->slave_cnt = slave_count;
612 
613 	/* Group may have been on queue for removal but is now offloadable. */
614 	group->to_remove = false;
615 	mutex_unlock(&lag->lock);
616 
617 	schedule_delayed_work(&lag->work, NFP_FL_LAG_DELAY);
618 	return 0;
619 }
620 
621 static void
622 nfp_fl_lag_changels_event(struct nfp_fl_lag *lag, struct net_device *netdev,
623 			  struct netdev_notifier_changelowerstate_info *info)
624 {
625 	struct netdev_lag_lower_state_info *lag_lower_info;
626 	struct nfp_flower_repr_priv *repr_priv;
627 	struct nfp_flower_priv *priv;
628 	struct nfp_repr *repr;
629 	unsigned long *flags;
630 
631 	if (!netif_is_lag_port(netdev) || !nfp_netdev_is_nfp_repr(netdev))
632 		return;
633 
634 	lag_lower_info = info->lower_state_info;
635 	if (!lag_lower_info)
636 		return;
637 
638 	priv = container_of(lag, struct nfp_flower_priv, nfp_lag);
639 	repr = netdev_priv(netdev);
640 
641 	/* Verify that the repr is associated with this app. */
642 	if (repr->app != priv->app)
643 		return;
644 
645 	repr_priv = repr->app_priv;
646 	flags = &repr_priv->lag_port_flags;
647 
648 	mutex_lock(&lag->lock);
649 	if (lag_lower_info->link_up)
650 		*flags |= NFP_PORT_LAG_LINK_UP;
651 	else
652 		*flags &= ~NFP_PORT_LAG_LINK_UP;
653 
654 	if (lag_lower_info->tx_enabled)
655 		*flags |= NFP_PORT_LAG_TX_ENABLED;
656 	else
657 		*flags &= ~NFP_PORT_LAG_TX_ENABLED;
658 
659 	*flags |= NFP_PORT_LAG_CHANGED;
660 	mutex_unlock(&lag->lock);
661 
662 	schedule_delayed_work(&lag->work, NFP_FL_LAG_DELAY);
663 }
664 
665 int nfp_flower_lag_netdev_event(struct nfp_flower_priv *priv,
666 				struct net_device *netdev,
667 				unsigned long event, void *ptr)
668 {
669 	struct nfp_fl_lag *lag = &priv->nfp_lag;
670 	int err;
671 
672 	switch (event) {
673 	case NETDEV_CHANGEUPPER:
674 		err = nfp_fl_lag_changeupper_event(lag, ptr);
675 		if (err)
676 			return NOTIFY_BAD;
677 		return NOTIFY_OK;
678 	case NETDEV_CHANGELOWERSTATE:
679 		nfp_fl_lag_changels_event(lag, netdev, ptr);
680 		return NOTIFY_OK;
681 	case NETDEV_UNREGISTER:
682 		nfp_fl_lag_schedule_group_delete(lag, netdev);
683 		return NOTIFY_OK;
684 	}
685 
686 	return NOTIFY_DONE;
687 }
688 
689 int nfp_flower_lag_reset(struct nfp_fl_lag *lag)
690 {
691 	enum nfp_fl_lag_batch batch = NFP_FL_LAG_BATCH_FIRST;
692 
693 	lag->rst_cfg = true;
694 	return nfp_fl_lag_config_group(lag, NULL, NULL, 0, &batch);
695 }
696 
697 void nfp_flower_lag_init(struct nfp_fl_lag *lag)
698 {
699 	INIT_DELAYED_WORK(&lag->work, nfp_fl_lag_do_work);
700 	INIT_LIST_HEAD(&lag->group_list);
701 	mutex_init(&lag->lock);
702 	ida_init(&lag->ida_handle);
703 
704 	__skb_queue_head_init(&lag->retrans_skbs);
705 
706 	/* 0 is a reserved batch version so increment to first valid value. */
707 	nfp_fl_increment_version(lag);
708 }
709 
710 void nfp_flower_lag_cleanup(struct nfp_fl_lag *lag)
711 {
712 	struct nfp_fl_lag_group *entry, *storage;
713 
714 	cancel_delayed_work_sync(&lag->work);
715 
716 	__skb_queue_purge(&lag->retrans_skbs);
717 
718 	/* Remove all groups. */
719 	mutex_lock(&lag->lock);
720 	list_for_each_entry_safe(entry, storage, &lag->group_list, list) {
721 		list_del(&entry->list);
722 		kfree(entry);
723 	}
724 	mutex_unlock(&lag->lock);
725 	mutex_destroy(&lag->lock);
726 	ida_destroy(&lag->ida_handle);
727 }
728