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