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