Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'fbnic-synchronize-address-handling-with-bmc'

Alexander Duyck says:

====================
fbnic: Synchronize address handling with BMC

The fbnic driver needs to communicate with the BMC if it is operating on
the RMII-based transport (RBT) of the same port the host is on. To enable
this we need to add rules that will route BMC traffic to the RBT/BMC and
the BMC and firmware need to configure rules on the RBT side of the
interface to route traffic from the BMC to the host instead of the MAC.

To enable that this patch set addresses two issues. First it will cause the
TCAM to be reconfigured in the event that the BMC was not previously
present when the driver was loaded, but the FW sends a notification that
the FW capabilities have changed and a BMC w/ various MAC addresses is now
present. Second it adds support for sending a message to the firmware so
that if the host adds additional MAC addresses the FW can be made aware and
route traffic for those addresses from the RBT to the host instead of the
MAC.
====================

Link: https://patch.msgid.link/175623715978.2246365.7798520806218461199.stgit@ahduyck-xeon-server.home.arpa
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+225 -64
+106
drivers/net/ethernet/meta/fbnic/fbnic_fw.c
··· 653 653 fbd->fw_cap.anti_rollback_version = 654 654 fta_get_uint(results, FBNIC_FW_CAP_RESP_ANTI_ROLLBACK_VERSION); 655 655 656 + /* Always assume we need a BMC reinit */ 657 + fbd->fw_cap.need_bmc_tcam_reinit = true; 658 + 656 659 return 0; 657 660 } 658 661 ··· 1411 1408 msleep(20); 1412 1409 fbnic_mbx_process_tx_msgs(fbd); 1413 1410 } while (time_is_after_jiffies(timeout)); 1411 + } 1412 + 1413 + int fbnic_fw_xmit_rpc_macda_sync(struct fbnic_dev *fbd) 1414 + { 1415 + struct fbnic_tlv_msg *mac_array; 1416 + int i, addr_count = 0, err; 1417 + struct fbnic_tlv_msg *msg; 1418 + u32 rx_flags = 0; 1419 + 1420 + /* Nothing to do if there is no FW to sync with */ 1421 + if (!fbd->mbx[FBNIC_IPC_MBX_TX_IDX].ready) 1422 + return 0; 1423 + 1424 + msg = fbnic_tlv_msg_alloc(FBNIC_TLV_MSG_ID_RPC_MAC_SYNC_REQ); 1425 + if (!msg) 1426 + return -ENOMEM; 1427 + 1428 + mac_array = fbnic_tlv_attr_nest_start(msg, 1429 + FBNIC_FW_RPC_MAC_SYNC_UC_ARRAY); 1430 + if (!mac_array) 1431 + goto free_message_nospc; 1432 + 1433 + /* Populate the unicast MAC addrs and capture PROMISC/ALLMULTI flags */ 1434 + for (addr_count = 0, i = FBNIC_RPC_TCAM_MACDA_PROMISC_IDX; 1435 + i >= fbd->mac_addr_boundary; i--) { 1436 + struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[i]; 1437 + 1438 + if (mac_addr->state != FBNIC_TCAM_S_VALID) 1439 + continue; 1440 + if (test_bit(FBNIC_MAC_ADDR_T_ALLMULTI, mac_addr->act_tcam)) 1441 + rx_flags |= FW_RPC_MAC_SYNC_RX_FLAGS_ALLMULTI; 1442 + if (test_bit(FBNIC_MAC_ADDR_T_PROMISC, mac_addr->act_tcam)) 1443 + rx_flags |= FW_RPC_MAC_SYNC_RX_FLAGS_PROMISC; 1444 + if (!test_bit(FBNIC_MAC_ADDR_T_UNICAST, mac_addr->act_tcam)) 1445 + continue; 1446 + if (addr_count == FW_RPC_MAC_SYNC_UC_ARRAY_SIZE) { 1447 + rx_flags |= FW_RPC_MAC_SYNC_RX_FLAGS_PROMISC; 1448 + continue; 1449 + } 1450 + 1451 + err = fbnic_tlv_attr_put_value(mac_array, 1452 + FBNIC_FW_RPC_MAC_SYNC_MAC_ADDR, 1453 + mac_addr->value.addr8, 1454 + ETH_ALEN); 1455 + if (err) 1456 + goto free_message; 1457 + addr_count++; 1458 + } 1459 + 1460 + /* Close array */ 1461 + fbnic_tlv_attr_nest_stop(msg); 1462 + 1463 + mac_array = fbnic_tlv_attr_nest_start(msg, 1464 + FBNIC_FW_RPC_MAC_SYNC_MC_ARRAY); 1465 + if (!mac_array) 1466 + goto free_message_nospc; 1467 + 1468 + /* Repeat for multicast addrs, record BROADCAST/ALLMULTI flags */ 1469 + for (addr_count = 0, i = FBNIC_RPC_TCAM_MACDA_BROADCAST_IDX; 1470 + i < fbd->mac_addr_boundary; i++) { 1471 + struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[i]; 1472 + 1473 + if (mac_addr->state != FBNIC_TCAM_S_VALID) 1474 + continue; 1475 + if (test_bit(FBNIC_MAC_ADDR_T_BROADCAST, mac_addr->act_tcam)) 1476 + rx_flags |= FW_RPC_MAC_SYNC_RX_FLAGS_BROADCAST; 1477 + if (test_bit(FBNIC_MAC_ADDR_T_ALLMULTI, mac_addr->act_tcam)) 1478 + rx_flags |= FW_RPC_MAC_SYNC_RX_FLAGS_ALLMULTI; 1479 + if (!test_bit(FBNIC_MAC_ADDR_T_MULTICAST, mac_addr->act_tcam)) 1480 + continue; 1481 + if (addr_count == FW_RPC_MAC_SYNC_MC_ARRAY_SIZE) { 1482 + rx_flags |= FW_RPC_MAC_SYNC_RX_FLAGS_ALLMULTI; 1483 + continue; 1484 + } 1485 + 1486 + err = fbnic_tlv_attr_put_value(mac_array, 1487 + FBNIC_FW_RPC_MAC_SYNC_MAC_ADDR, 1488 + mac_addr->value.addr8, 1489 + ETH_ALEN); 1490 + if (err) 1491 + goto free_message; 1492 + addr_count++; 1493 + } 1494 + 1495 + /* Close array */ 1496 + fbnic_tlv_attr_nest_stop(msg); 1497 + 1498 + /* Report flags at end of list */ 1499 + err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_RPC_MAC_SYNC_RX_FLAGS, 1500 + rx_flags); 1501 + if (err) 1502 + goto free_message; 1503 + 1504 + /* Send message of to FW notifying it of current RPC config */ 1505 + err = fbnic_mbx_map_tlv_msg(fbd, msg); 1506 + if (err) 1507 + goto free_message; 1508 + return 0; 1509 + free_message_nospc: 1510 + err = -ENOSPC; 1511 + free_message: 1512 + free_page((unsigned long)msg); 1513 + return err; 1414 1514 } 1415 1515 1416 1516 void fbnic_get_fw_ver_commit_str(struct fbnic_dev *fbd, char *fw_version,
+21 -2
drivers/net/ethernet/meta/fbnic/fbnic_fw.h
··· 51 51 } stored; 52 52 u8 active_slot; 53 53 u8 bmc_mac_addr[4][ETH_ALEN]; 54 - u8 bmc_present : 1; 55 - u8 all_multi : 1; 54 + u8 bmc_present : 1; 55 + u8 need_bmc_tcam_reinit : 1; 56 + u8 need_bmc_macda_sync : 1; 57 + u8 all_multi : 1; 56 58 u8 link_speed; 57 59 u8 link_fec; 58 60 u32 anti_rollback_version; ··· 99 97 struct fbnic_fw_completion *cmpl_data); 100 98 int fbnic_fw_xmit_send_logs(struct fbnic_dev *fbd, bool enable, 101 99 bool send_log_history); 100 + int fbnic_fw_xmit_rpc_macda_sync(struct fbnic_dev *fbd); 102 101 struct fbnic_fw_completion *fbnic_fw_alloc_cmpl(u32 msg_type); 103 102 void fbnic_fw_put_cmpl(struct fbnic_fw_completion *cmpl_data); 104 103 ··· 146 143 FBNIC_TLV_MSG_ID_LOG_SEND_LOGS_REQ = 0x43, 147 144 FBNIC_TLV_MSG_ID_LOG_MSG_REQ = 0x44, 148 145 FBNIC_TLV_MSG_ID_LOG_MSG_RESP = 0x45, 146 + FBNIC_TLV_MSG_ID_RPC_MAC_SYNC_REQ = 0x46, 149 147 }; 150 148 151 149 #define FBNIC_FW_CAP_RESP_VERSION_MAJOR CSR_GENMASK(31, 24) ··· 238 234 FBNIC_FW_LOG_MSG_ARRAY = 0x6, 239 235 FBNIC_FW_LOG_MSG_MAX 240 236 }; 237 + 238 + enum { 239 + FBNIC_FW_RPC_MAC_SYNC_RX_FLAGS = 0x0, 240 + FBNIC_FW_RPC_MAC_SYNC_UC_ARRAY = 0x1, 241 + FBNIC_FW_RPC_MAC_SYNC_MC_ARRAY = 0x2, 242 + FBNIC_FW_RPC_MAC_SYNC_MAC_ADDR = 0x3, 243 + FBNIC_FW_RPC_MAC_SYNC_MSG_MAX 244 + }; 245 + 246 + #define FW_RPC_MAC_SYNC_RX_FLAGS_PROMISC 1 247 + #define FW_RPC_MAC_SYNC_RX_FLAGS_ALLMULTI 2 248 + #define FW_RPC_MAC_SYNC_RX_FLAGS_BROADCAST 4 249 + 250 + #define FW_RPC_MAC_SYNC_UC_ARRAY_SIZE 8 251 + #define FW_RPC_MAC_SYNC_MC_ARRAY_SIZE 8 241 252 242 253 #endif /* _FBNIC_FW_H_ */
+10 -50
drivers/net/ethernet/meta/fbnic/fbnic_netdev.c
··· 179 179 return ret; 180 180 } 181 181 182 - void __fbnic_set_rx_mode(struct net_device *netdev) 182 + void __fbnic_set_rx_mode(struct fbnic_dev *fbd) 183 183 { 184 - struct fbnic_net *fbn = netdev_priv(netdev); 185 184 bool uc_promisc = false, mc_promisc = false; 186 - struct fbnic_dev *fbd = fbn->fbd; 185 + struct net_device *netdev = fbd->netdev; 187 186 struct fbnic_mac_addr *mac_addr; 188 187 int err; 189 188 ··· 219 220 uc_promisc |= !!(netdev->flags & IFF_PROMISC); 220 221 mc_promisc |= !!(netdev->flags & IFF_ALLMULTI) || uc_promisc; 221 222 222 - /* Populate last TCAM entry with promiscuous entry and 0/1 bit mask */ 223 - mac_addr = &fbd->mac_addr[FBNIC_RPC_TCAM_MACDA_PROMISC_IDX]; 224 - if (uc_promisc) { 225 - if (!is_zero_ether_addr(mac_addr->value.addr8) || 226 - mac_addr->state != FBNIC_TCAM_S_VALID) { 227 - eth_zero_addr(mac_addr->value.addr8); 228 - eth_broadcast_addr(mac_addr->mask.addr8); 229 - clear_bit(FBNIC_MAC_ADDR_T_ALLMULTI, 230 - mac_addr->act_tcam); 231 - set_bit(FBNIC_MAC_ADDR_T_PROMISC, 232 - mac_addr->act_tcam); 233 - mac_addr->state = FBNIC_TCAM_S_ADD; 234 - } 235 - } else if (mc_promisc && 236 - (!fbnic_bmc_present(fbd) || !fbd->fw_cap.all_multi)) { 237 - /* We have to add a special handler for multicast as the 238 - * BMC may have an all-multi rule already in place. As such 239 - * adding a rule ourselves won't do any good so we will have 240 - * to modify the rules for the ALL MULTI below if the BMC 241 - * already has the rule in place. 242 - */ 243 - if (!is_multicast_ether_addr(mac_addr->value.addr8) || 244 - mac_addr->state != FBNIC_TCAM_S_VALID) { 245 - eth_zero_addr(mac_addr->value.addr8); 246 - eth_broadcast_addr(mac_addr->mask.addr8); 247 - mac_addr->value.addr8[0] ^= 1; 248 - mac_addr->mask.addr8[0] ^= 1; 249 - set_bit(FBNIC_MAC_ADDR_T_ALLMULTI, 250 - mac_addr->act_tcam); 251 - clear_bit(FBNIC_MAC_ADDR_T_PROMISC, 252 - mac_addr->act_tcam); 253 - mac_addr->state = FBNIC_TCAM_S_ADD; 254 - } 255 - } else if (mac_addr->state == FBNIC_TCAM_S_VALID) { 256 - if (test_bit(FBNIC_MAC_ADDR_T_BMC, mac_addr->act_tcam)) { 257 - clear_bit(FBNIC_MAC_ADDR_T_ALLMULTI, 258 - mac_addr->act_tcam); 259 - clear_bit(FBNIC_MAC_ADDR_T_PROMISC, 260 - mac_addr->act_tcam); 261 - } else { 262 - mac_addr->state = FBNIC_TCAM_S_DELETE; 263 - } 264 - } 223 + /* Update the promiscuous rules */ 224 + fbnic_promisc_sync(fbd, uc_promisc, mc_promisc); 265 225 266 226 /* Add rules for BMC all multicast if it is enabled */ 267 227 fbnic_bmc_rpc_all_multi_config(fbd, mc_promisc); ··· 236 278 237 279 static void fbnic_set_rx_mode(struct net_device *netdev) 238 280 { 281 + struct fbnic_net *fbn = netdev_priv(netdev); 282 + struct fbnic_dev *fbd = fbn->fbd; 283 + 239 284 /* No need to update the hardware if we are not running */ 240 285 if (netif_running(netdev)) 241 - __fbnic_set_rx_mode(netdev); 286 + __fbnic_set_rx_mode(fbd); 242 287 } 243 288 244 289 static int fbnic_set_mac(struct net_device *netdev, void *p) ··· 258 297 return 0; 259 298 } 260 299 261 - void fbnic_clear_rx_mode(struct net_device *netdev) 300 + void fbnic_clear_rx_mode(struct fbnic_dev *fbd) 262 301 { 263 - struct fbnic_net *fbn = netdev_priv(netdev); 264 - struct fbnic_dev *fbd = fbn->fbd; 302 + struct net_device *netdev = fbd->netdev; 265 303 int idx; 266 304 267 305 for (idx = ARRAY_SIZE(fbd->mac_addr); idx--;) {
+2 -2
drivers/net/ethernet/meta/fbnic/fbnic_netdev.h
··· 94 94 int fbnic_time_start(struct fbnic_net *fbn); 95 95 void fbnic_time_stop(struct fbnic_net *fbn); 96 96 97 - void __fbnic_set_rx_mode(struct net_device *netdev); 98 - void fbnic_clear_rx_mode(struct net_device *netdev); 97 + void __fbnic_set_rx_mode(struct fbnic_dev *fbd); 98 + void fbnic_clear_rx_mode(struct fbnic_dev *fbd); 99 99 100 100 void fbnic_phylink_get_pauseparam(struct net_device *netdev, 101 101 struct ethtool_pauseparam *pause);
+4 -2
drivers/net/ethernet/meta/fbnic/fbnic_pci.c
··· 137 137 138 138 fbnic_rss_reinit_hw(fbn->fbd, fbn); 139 139 140 - __fbnic_set_rx_mode(fbn->netdev); 140 + __fbnic_set_rx_mode(fbn->fbd); 141 141 142 142 /* Enable Tx/Rx processing */ 143 143 fbnic_napi_enable(fbn); ··· 154 154 fbnic_napi_disable(fbn); 155 155 netif_tx_disable(fbn->netdev); 156 156 157 - fbnic_clear_rx_mode(fbn->netdev); 157 + fbnic_clear_rx_mode(fbn->fbd); 158 158 fbnic_clear_rules(fbn->fbd); 159 159 fbnic_rss_disable_hw(fbn->fbd); 160 160 fbnic_disable(fbn); ··· 205 205 fbnic_fw_check_heartbeat(fbd); 206 206 207 207 fbnic_health_check(fbd); 208 + 209 + fbnic_bmc_rpc_check(fbd); 208 210 209 211 if (netif_carrier_ok(fbd->netdev)) 210 212 fbnic_napi_depletion_check(fbd->netdev);
+78 -8
drivers/net/ethernet/meta/fbnic/fbnic_rpc.c
··· 6 6 #include <net/ipv6.h> 7 7 8 8 #include "fbnic.h" 9 + #include "fbnic_fw.h" 9 10 #include "fbnic_netdev.h" 10 11 #include "fbnic_rpc.h" 11 12 ··· 132 131 else 133 132 clear_bit(FBNIC_MAC_ADDR_T_ALLMULTI, 134 133 mac_addr->act_tcam); 135 - } else if (!test_bit(FBNIC_MAC_ADDR_T_BMC, mac_addr->act_tcam) && 136 - !is_zero_ether_addr(mac_addr->mask.addr8) && 137 - mac_addr->state == FBNIC_TCAM_S_VALID) { 138 - clear_bit(FBNIC_MAC_ADDR_T_ALLMULTI, mac_addr->act_tcam); 139 - clear_bit(FBNIC_MAC_ADDR_T_BMC, mac_addr->act_tcam); 140 - mac_addr->state = FBNIC_TCAM_S_DELETE; 134 + } else { 135 + __fbnic_xc_unsync(mac_addr, FBNIC_MAC_ADDR_T_BMC); 136 + __fbnic_xc_unsync(mac_addr, FBNIC_MAC_ADDR_T_ALLMULTI); 141 137 } 142 138 143 139 /* We have to add a special handler for multicast as the ··· 236 238 act_tcam->mask.tcam[j] = 0xffff; 237 239 238 240 act_tcam->state = FBNIC_TCAM_S_UPDATE; 241 + } 239 242 240 - fbnic_bmc_rpc_all_multi_config(fbd, false); 243 + void fbnic_bmc_rpc_check(struct fbnic_dev *fbd) 244 + { 245 + int err; 246 + 247 + if (fbd->fw_cap.need_bmc_tcam_reinit) { 248 + fbnic_bmc_rpc_init(fbd); 249 + __fbnic_set_rx_mode(fbd); 250 + fbd->fw_cap.need_bmc_tcam_reinit = false; 251 + } 252 + 253 + if (fbd->fw_cap.need_bmc_macda_sync) { 254 + err = fbnic_fw_xmit_rpc_macda_sync(fbd); 255 + if (err) 256 + dev_warn(fbd->dev, 257 + "Writing MACDA table to FW failed, err: %d\n", err); 258 + fbd->fw_cap.need_bmc_macda_sync = false; 259 + } 241 260 } 242 261 243 262 #define FBNIC_ACT1_INIT(_l4, _udp, _ip, _v6) \ ··· 469 454 return 0; 470 455 } 471 456 457 + void fbnic_promisc_sync(struct fbnic_dev *fbd, 458 + bool uc_promisc, bool mc_promisc) 459 + { 460 + struct fbnic_mac_addr *mac_addr; 461 + 462 + /* Populate last TCAM entry with promiscuous entry and 0/1 bit mask */ 463 + mac_addr = &fbd->mac_addr[FBNIC_RPC_TCAM_MACDA_PROMISC_IDX]; 464 + if (uc_promisc) { 465 + if (!is_zero_ether_addr(mac_addr->value.addr8) || 466 + mac_addr->state != FBNIC_TCAM_S_VALID) { 467 + eth_zero_addr(mac_addr->value.addr8); 468 + eth_broadcast_addr(mac_addr->mask.addr8); 469 + clear_bit(FBNIC_MAC_ADDR_T_ALLMULTI, 470 + mac_addr->act_tcam); 471 + set_bit(FBNIC_MAC_ADDR_T_PROMISC, 472 + mac_addr->act_tcam); 473 + mac_addr->state = FBNIC_TCAM_S_ADD; 474 + } 475 + } else if (mc_promisc && 476 + (!fbnic_bmc_present(fbd) || !fbd->fw_cap.all_multi)) { 477 + /* We have to add a special handler for multicast as the 478 + * BMC may have an all-multi rule already in place. As such 479 + * adding a rule ourselves won't do any good so we will have 480 + * to modify the rules for the ALL MULTI below if the BMC 481 + * already has the rule in place. 482 + */ 483 + if (!is_multicast_ether_addr(mac_addr->value.addr8) || 484 + mac_addr->state != FBNIC_TCAM_S_VALID) { 485 + eth_zero_addr(mac_addr->value.addr8); 486 + eth_broadcast_addr(mac_addr->mask.addr8); 487 + mac_addr->value.addr8[0] ^= 1; 488 + mac_addr->mask.addr8[0] ^= 1; 489 + set_bit(FBNIC_MAC_ADDR_T_ALLMULTI, 490 + mac_addr->act_tcam); 491 + clear_bit(FBNIC_MAC_ADDR_T_PROMISC, 492 + mac_addr->act_tcam); 493 + mac_addr->state = FBNIC_TCAM_S_ADD; 494 + } 495 + } else if (mac_addr->state == FBNIC_TCAM_S_VALID) { 496 + __fbnic_xc_unsync(mac_addr, FBNIC_MAC_ADDR_T_ALLMULTI); 497 + __fbnic_xc_unsync(mac_addr, FBNIC_MAC_ADDR_T_PROMISC); 498 + } 499 + } 500 + 472 501 void fbnic_sift_macda(struct fbnic_dev *fbd) 473 502 { 474 503 int dest, src; ··· 617 558 618 559 void fbnic_write_macda(struct fbnic_dev *fbd) 619 560 { 620 - int idx; 561 + int idx, updates = 0; 621 562 622 563 for (idx = ARRAY_SIZE(fbd->mac_addr); idx--;) { 623 564 struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[idx]; ··· 625 566 /* Check if update flag is set else exit. */ 626 567 if (!(mac_addr->state & FBNIC_TCAM_S_UPDATE)) 627 568 continue; 569 + 570 + /* Record update count */ 571 + updates++; 628 572 629 573 /* Clear by writing 0s. */ 630 574 if (mac_addr->state == FBNIC_TCAM_S_DELETE) { ··· 642 580 643 581 mac_addr->state = FBNIC_TCAM_S_VALID; 644 582 } 583 + 584 + /* If reinitializing the BMC TCAM we are doing an initial update */ 585 + if (fbd->fw_cap.need_bmc_tcam_reinit) 586 + updates++; 587 + 588 + /* If needed notify firmware of changes to MACDA TCAM */ 589 + if (updates != 0 && fbnic_bmc_present(fbd)) 590 + fbd->fw_cap.need_bmc_macda_sync = true; 645 591 } 646 592 647 593 static void fbnic_clear_act_tcam(struct fbnic_dev *fbd, unsigned int idx)
+4
drivers/net/ethernet/meta/fbnic/fbnic_rpc.h
··· 184 184 185 185 void fbnic_bmc_rpc_init(struct fbnic_dev *fbd); 186 186 void fbnic_bmc_rpc_all_multi_config(struct fbnic_dev *fbd, bool enable_host); 187 + void fbnic_bmc_rpc_check(struct fbnic_dev *fbd); 187 188 188 189 void fbnic_reset_indir_tbl(struct fbnic_net *fbn); 189 190 void fbnic_rss_key_fill(u32 *buffer); ··· 201 200 const unsigned char *addr); 202 201 void fbnic_sift_macda(struct fbnic_dev *fbd); 203 202 void fbnic_write_macda(struct fbnic_dev *fbd); 203 + 204 + void fbnic_promisc_sync(struct fbnic_dev *fbd, 205 + bool uc_promisc, bool mc_promisc); 204 206 205 207 struct fbnic_ip_addr *__fbnic_ip4_sync(struct fbnic_dev *fbd, 206 208 struct fbnic_ip_addr *ip_addr,