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

Merge branch 'nfp-ksettings'

Jakub Kicinski says:

====================
nfp: ethtool link settings

This series adds support for getting and setting link settings
via the (moderately) new ethtool ksettings ops.

First patch introduces minimal speed and duplex reporting using
the information directly provided in PCI BAR0 memory.

Next few changes deal with the need to refresh port state read
from the service process and patch 6 finally uses that information
to provide link speed and duplex. Patches 7 and 8 add auto
negotiation and port type reporting.

Remaining changes provide the set support for speed and auto
negotiation. An upcoming series will also add port splitting
support via devlink.

Quite a bit of churn in this series is caused by the fact that
currently port speed and split changes will usually require a
reboot to take effect. Current service process code is not capable
of performing MAC reinitialization after chip has been passing
traffic. To make sure user is aware of this limitation we refuse
the configuration unless netdev is down, print warning to the logs
and if configuration was performed but did take effect we unregister
the netdev. Service process has a "reboot needed" sticky bit, so
reloading the driver will not bring the netdev back.

Note that there is a helper in patch 13 which is marked as
__always_inline, because the FIELD_* macros require the parameters
to be known at compilation time. I hope that is OK.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+756 -130
+2 -3
drivers/net/ethernet/netronome/nfp/nfp_main.c
··· 48 48 #include "nfpcore/nfp.h" 49 49 #include "nfpcore/nfp_cpp.h" 50 50 #include "nfpcore/nfp_nffw.h" 51 - #include "nfpcore/nfp_nsp_eth.h" 51 + #include "nfpcore/nfp_nsp.h" 52 52 53 53 #include "nfpcore/nfp6000_pcie.h" 54 54 ··· 385 385 { 386 386 struct nfp_pf *pf = pci_get_drvdata(pdev); 387 387 388 - if (!list_empty(&pf->ports)) 389 - nfp_net_pci_remove(pf); 388 + nfp_net_pci_remove(pf); 390 389 391 390 nfp_pcie_sriov_disable(pdev); 392 391
+10 -1
drivers/net/ethernet/netronome/nfp/nfp_main.h
··· 42 42 #include <linux/list.h> 43 43 #include <linux/types.h> 44 44 #include <linux/msi.h> 45 + #include <linux/mutex.h> 45 46 #include <linux/pci.h> 47 + #include <linux/workqueue.h> 46 48 47 49 struct dentry; 48 50 struct pci_dev; ··· 66 64 * @fw_loaded: Is the firmware loaded? 67 65 * @eth_tbl: NSP ETH table 68 66 * @ddir: Per-device debugfs directory 69 - * @num_ports: Number of adapter ports 67 + * @num_ports: Number of adapter ports app firmware supports 68 + * @num_netdevs: Number of netdevs spawned 70 69 * @ports: Linked list of port structures (struct nfp_net) 70 + * @port_lock: Protects @ports, @num_ports, @num_netdevs 71 + * @port_refresh_work: Work entry for taking netdevs out 71 72 */ 72 73 struct nfp_pf { 73 74 struct pci_dev *pdev; ··· 93 88 struct dentry *ddir; 94 89 95 90 unsigned int num_ports; 91 + unsigned int num_netdevs; 92 + 96 93 struct list_head ports; 94 + struct work_struct port_refresh_work; 95 + struct mutex port_lock; 97 96 }; 98 97 99 98 extern struct pci_driver nfp_netvf_pci_driver;
+6 -1
drivers/net/ethernet/netronome/nfp/nfp_net.h
··· 523 523 * @reconfig_sync_present: Some thread is performing synchronous reconfig 524 524 * @reconfig_timer: Timer for async reading of reconfig results 525 525 * @link_up: Is the link up? 526 - * @link_status_lock: Protects @link_up and ensures atomicity with BAR reading 526 + * @link_changed: Has link state changes since last port refresh? 527 + * @link_status_lock: Protects @link_* and ensures atomicity with BAR reading 527 528 * @rx_coalesce_usecs: RX interrupt moderation usecs delay parameter 528 529 * @rx_coalesce_max_frames: RX interrupt moderation frame count parameter 529 530 * @tx_coalesce_usecs: TX interrupt moderation usecs delay parameter ··· 581 580 u32 me_freq_mhz; 582 581 583 582 bool link_up; 583 + bool link_changed; 584 584 spinlock_t link_status_lock; 585 585 586 586 spinlock_t reconfig_lock; ··· 811 809 812 810 struct nfp_net_dp *nfp_net_clone_dp(struct nfp_net *nn); 813 811 int nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_dp *new); 812 + 813 + bool nfp_net_link_changed_read_clear(struct nfp_net *nn); 814 + void nfp_net_refresh_port_config(struct nfp_net *nn); 814 815 815 816 #ifdef CONFIG_NFP_DEBUG 816 817 void nfp_net_debugfs_create(void);
+15 -1
drivers/net/ethernet/netronome/nfp/nfp_net_common.c
··· 67 67 #include <net/pkt_cls.h> 68 68 #include <net/vxlan.h> 69 69 70 - #include "nfpcore/nfp_nsp_eth.h" 70 + #include "nfpcore/nfp_nsp.h" 71 71 #include "nfp_net_ctrl.h" 72 72 #include "nfp_net.h" 73 73 ··· 376 376 return IRQ_HANDLED; 377 377 } 378 378 379 + bool nfp_net_link_changed_read_clear(struct nfp_net *nn) 380 + { 381 + unsigned long flags; 382 + bool ret; 383 + 384 + spin_lock_irqsave(&nn->link_status_lock, flags); 385 + ret = nn->link_changed; 386 + nn->link_changed = false; 387 + spin_unlock_irqrestore(&nn->link_status_lock, flags); 388 + 389 + return ret; 390 + } 391 + 379 392 /** 380 393 * nfp_net_read_link_status() - Reread link status from control BAR 381 394 * @nn: NFP Network structure ··· 408 395 goto out; 409 396 410 397 nn->link_up = link_up; 398 + nn->link_changed = true; 411 399 412 400 if (nn->link_up) { 413 401 netif_carrier_on(nn->dp.netdev);
+13
drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
··· 177 177 #define NFP_NET_CFG_VERSION_MINOR(x) (((x) & 0xff) << 0) 178 178 #define NFP_NET_CFG_STS 0x0034 179 179 #define NFP_NET_CFG_STS_LINK (0x1 << 0) /* Link up or down */ 180 + /* Link rate */ 181 + #define NFP_NET_CFG_STS_LINK_RATE_SHIFT 1 182 + #define NFP_NET_CFG_STS_LINK_RATE_MASK 0xF 183 + #define NFP_NET_CFG_STS_LINK_RATE \ 184 + (NFP_NET_CFG_STS_LINK_RATE_MASK << NFP_NET_CFG_STS_LINK_RATE_SHIFT) 185 + #define NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED 0 186 + #define NFP_NET_CFG_STS_LINK_RATE_UNKNOWN 1 187 + #define NFP_NET_CFG_STS_LINK_RATE_1G 2 188 + #define NFP_NET_CFG_STS_LINK_RATE_10G 3 189 + #define NFP_NET_CFG_STS_LINK_RATE_25G 4 190 + #define NFP_NET_CFG_STS_LINK_RATE_40G 5 191 + #define NFP_NET_CFG_STS_LINK_RATE_50G 6 192 + #define NFP_NET_CFG_STS_LINK_RATE_100G 7 180 193 #define NFP_NET_CFG_CAP 0x0038 181 194 #define NFP_NET_CFG_MAX_TXRINGS 0x003c 182 195 #define NFP_NET_CFG_MAX_RXRINGS 0x0040
+111
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
··· 49 49 #include <linux/ethtool.h> 50 50 51 51 #include "nfpcore/nfp.h" 52 + #include "nfpcore/nfp_nsp.h" 52 53 #include "nfp_net_ctrl.h" 53 54 #include "nfp_net.h" 54 55 ··· 172 171 173 172 drvinfo->n_stats = NN_ET_STATS_LEN; 174 173 drvinfo->regdump_len = NFP_NET_CFG_BAR_SZ; 174 + } 175 + 176 + /** 177 + * nfp_net_get_link_ksettings - Get Link Speed settings 178 + * @netdev: network interface device structure 179 + * @cmd: ethtool command 180 + * 181 + * Reports speed settings based on info in the BAR provided by the fw. 182 + */ 183 + static int 184 + nfp_net_get_link_ksettings(struct net_device *netdev, 185 + struct ethtool_link_ksettings *cmd) 186 + { 187 + static const u32 ls_to_ethtool[] = { 188 + [NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = 0, 189 + [NFP_NET_CFG_STS_LINK_RATE_UNKNOWN] = SPEED_UNKNOWN, 190 + [NFP_NET_CFG_STS_LINK_RATE_1G] = SPEED_1000, 191 + [NFP_NET_CFG_STS_LINK_RATE_10G] = SPEED_10000, 192 + [NFP_NET_CFG_STS_LINK_RATE_25G] = SPEED_25000, 193 + [NFP_NET_CFG_STS_LINK_RATE_40G] = SPEED_40000, 194 + [NFP_NET_CFG_STS_LINK_RATE_50G] = SPEED_50000, 195 + [NFP_NET_CFG_STS_LINK_RATE_100G] = SPEED_100000, 196 + }; 197 + struct nfp_net *nn = netdev_priv(netdev); 198 + u32 sts, ls; 199 + 200 + ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); 201 + cmd->base.port = PORT_OTHER; 202 + cmd->base.speed = SPEED_UNKNOWN; 203 + cmd->base.duplex = DUPLEX_UNKNOWN; 204 + 205 + if (nn->eth_port) 206 + cmd->base.autoneg = nn->eth_port->aneg != NFP_ANEG_DISABLED ? 207 + AUTONEG_ENABLE : AUTONEG_DISABLE; 208 + 209 + if (!netif_carrier_ok(netdev)) 210 + return 0; 211 + 212 + /* Use link speed from ETH table if available, otherwise try the BAR */ 213 + if (nn->eth_port && nfp_net_link_changed_read_clear(nn)) 214 + nfp_net_refresh_port_config(nn); 215 + /* Separate if - on FW error the port could've disappeared from table */ 216 + if (nn->eth_port) { 217 + cmd->base.port = nn->eth_port->port_type; 218 + cmd->base.speed = nn->eth_port->speed; 219 + cmd->base.duplex = DUPLEX_FULL; 220 + return 0; 221 + } 222 + 223 + sts = nn_readl(nn, NFP_NET_CFG_STS); 224 + 225 + ls = FIELD_GET(NFP_NET_CFG_STS_LINK_RATE, sts); 226 + if (ls == NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED) 227 + return -EOPNOTSUPP; 228 + 229 + if (ls == NFP_NET_CFG_STS_LINK_RATE_UNKNOWN || 230 + ls >= ARRAY_SIZE(ls_to_ethtool)) 231 + return 0; 232 + 233 + cmd->base.speed = ls_to_ethtool[sts]; 234 + cmd->base.duplex = DUPLEX_FULL; 235 + 236 + return 0; 237 + } 238 + 239 + static int 240 + nfp_net_set_link_ksettings(struct net_device *netdev, 241 + const struct ethtool_link_ksettings *cmd) 242 + { 243 + struct nfp_net *nn = netdev_priv(netdev); 244 + struct nfp_nsp *nsp; 245 + int err; 246 + 247 + if (!nn->eth_port) 248 + return -EOPNOTSUPP; 249 + 250 + if (netif_running(netdev)) { 251 + nn_warn(nn, "Changing settings not allowed on an active interface. It may cause the port to be disabled until reboot.\n"); 252 + return -EBUSY; 253 + } 254 + 255 + nsp = nfp_eth_config_start(nn->cpp, nn->eth_port->index); 256 + if (IS_ERR(nsp)) 257 + return PTR_ERR(nsp); 258 + 259 + err = __nfp_eth_set_aneg(nsp, cmd->base.autoneg == AUTONEG_ENABLE ? 260 + NFP_ANEG_AUTO : NFP_ANEG_DISABLED); 261 + if (err) 262 + goto err_bad_set; 263 + if (cmd->base.speed != SPEED_UNKNOWN) { 264 + u32 speed = cmd->base.speed / nn->eth_port->lanes; 265 + 266 + err = __nfp_eth_set_speed(nsp, speed); 267 + if (err) 268 + goto err_bad_set; 269 + } 270 + 271 + err = nfp_eth_config_commit_end(nsp); 272 + if (err > 0) 273 + return 0; /* no change */ 274 + 275 + nfp_net_refresh_port_config(nn); 276 + 277 + return err; 278 + 279 + err_bad_set: 280 + nfp_eth_config_cleanup_end(nsp); 281 + return err; 175 282 } 176 283 177 284 static void nfp_net_get_ringparam(struct net_device *netdev, ··· 923 814 .set_coalesce = nfp_net_set_coalesce, 924 815 .get_channels = nfp_net_get_channels, 925 816 .set_channels = nfp_net_set_channels, 817 + .get_link_ksettings = nfp_net_get_link_ksettings, 818 + .set_link_ksettings = nfp_net_set_link_ksettings, 926 819 }; 927 820 928 821 void nfp_net_set_ethtool_ops(struct net_device *netdev)
+144 -43
drivers/net/ethernet/netronome/nfp/nfp_net_main.c
··· 47 47 #include <linux/pci_regs.h> 48 48 #include <linux/msi.h> 49 49 #include <linux/random.h> 50 + #include <linux/rtnetlink.h> 50 51 51 52 #include "nfpcore/nfp.h" 52 53 #include "nfpcore/nfp_cpp.h" 53 54 #include "nfpcore/nfp_nffw.h" 54 - #include "nfpcore/nfp_nsp_eth.h" 55 + #include "nfpcore/nfp_nsp.h" 55 56 #include "nfpcore/nfp6000_pcie.h" 56 57 57 58 #include "nfp_net_ctrl.h" ··· 130 129 return (u8 __iomem *)ERR_PTR(err); 131 130 } 132 131 132 + /** 133 + * nfp_net_get_mac_addr() - Get the MAC address. 134 + * @nn: NFP Network structure 135 + * @cpp: NFP CPP handle 136 + * @id: NFP port id 137 + * 138 + * First try to get the MAC address from NSP ETH table. If that 139 + * fails try HWInfo. As a last resort generate a random address. 140 + */ 133 141 static void 134 - nfp_net_get_mac_addr_hwinfo(struct nfp_net_dp *dp, struct nfp_cpp *cpp, 135 - unsigned int id) 142 + nfp_net_get_mac_addr(struct nfp_net *nn, struct nfp_cpp *cpp, unsigned int id) 136 143 { 144 + struct nfp_net_dp *dp = &nn->dp; 137 145 u8 mac_addr[ETH_ALEN]; 138 146 const char *mac_str; 139 147 char name[32]; 148 + 149 + if (nn->eth_port) { 150 + ether_addr_copy(dp->netdev->dev_addr, nn->eth_port->mac_addr); 151 + ether_addr_copy(dp->netdev->perm_addr, nn->eth_port->mac_addr); 152 + return; 153 + } 140 154 141 155 snprintf(name, sizeof(name), "eth%d.mac", id); 142 156 ··· 175 159 ether_addr_copy(dp->netdev->perm_addr, mac_addr); 176 160 } 177 161 178 - /** 179 - * nfp_net_get_mac_addr() - Get the MAC address. 180 - * @nn: NFP Network structure 181 - * @pf: NFP PF device structure 182 - * @id: NFP port id 183 - * 184 - * First try to get the MAC address from NSP ETH table. If that 185 - * fails try HWInfo. As a last resort generate a random address. 186 - */ 187 - static void 188 - nfp_net_get_mac_addr(struct nfp_net *nn, struct nfp_pf *pf, unsigned int id) 162 + static struct nfp_eth_table_port * 163 + nfp_net_find_port(struct nfp_pf *pf, unsigned int id) 189 164 { 190 165 int i; 191 166 192 167 for (i = 0; pf->eth_tbl && i < pf->eth_tbl->count; i++) 193 - if (pf->eth_tbl->ports[i].eth_index == id) { 194 - const u8 *mac_addr = pf->eth_tbl->ports[i].mac_addr; 168 + if (pf->eth_tbl->ports[i].eth_index == id) 169 + return &pf->eth_tbl->ports[i]; 195 170 196 - nn->eth_port = &pf->eth_tbl->ports[i]; 197 - 198 - ether_addr_copy(nn->dp.netdev->dev_addr, mac_addr); 199 - ether_addr_copy(nn->dp.netdev->perm_addr, mac_addr); 200 - return; 201 - } 202 - 203 - nfp_net_get_mac_addr_hwinfo(&nn->dp, pf->cpp, id); 171 + return NULL; 204 172 } 205 173 206 174 static unsigned int nfp_net_pf_get_num_ports(struct nfp_pf *pf) ··· 283 283 while (!list_empty(&pf->ports)) { 284 284 nn = list_first_entry(&pf->ports, struct nfp_net, port_list); 285 285 list_del(&nn->port_list); 286 + pf->num_netdevs--; 286 287 287 288 nfp_net_netdev_free(nn); 288 289 } ··· 292 291 static struct nfp_net * 293 292 nfp_net_pf_alloc_port_netdev(struct nfp_pf *pf, void __iomem *ctrl_bar, 294 293 void __iomem *tx_bar, void __iomem *rx_bar, 295 - int stride, struct nfp_net_fw_version *fw_ver) 294 + int stride, struct nfp_net_fw_version *fw_ver, 295 + struct nfp_eth_table_port *eth_port) 296 296 { 297 297 u32 n_tx_rings, n_rx_rings; 298 298 struct nfp_net *nn; ··· 314 312 nn->dp.is_vf = 0; 315 313 nn->stride_rx = stride; 316 314 nn->stride_tx = stride; 315 + nn->eth_port = eth_port; 317 316 318 317 return nn; 319 318 } ··· 326 323 int err; 327 324 328 325 /* Get MAC address */ 329 - nfp_net_get_mac_addr(nn, pf, id); 326 + nfp_net_get_mac_addr(nn, pf->cpp, id); 330 327 331 328 /* Get ME clock frequency from ctrl BAR 332 329 * XXX for now frequency is hardcoded until we figure out how ··· 351 348 int stride, struct nfp_net_fw_version *fw_ver) 352 349 { 353 350 u32 prev_tx_base, prev_rx_base, tgt_tx_base, tgt_rx_base; 351 + struct nfp_eth_table_port *eth_port; 354 352 struct nfp_net *nn; 355 353 unsigned int i; 356 354 int err; ··· 367 363 prev_tx_base = tgt_tx_base; 368 364 prev_rx_base = tgt_rx_base; 369 365 370 - nn = nfp_net_pf_alloc_port_netdev(pf, ctrl_bar, tx_bar, rx_bar, 371 - stride, fw_ver); 372 - if (IS_ERR(nn)) { 373 - err = PTR_ERR(nn); 374 - goto err_free_prev; 366 + eth_port = nfp_net_find_port(pf, i); 367 + if (eth_port && eth_port->override_changed) { 368 + nfp_warn(pf->cpp, "Config changed for port #%d, reboot required before port will be operational\n", i); 369 + } else { 370 + nn = nfp_net_pf_alloc_port_netdev(pf, ctrl_bar, tx_bar, 371 + rx_bar, stride, 372 + fw_ver, eth_port); 373 + if (IS_ERR(nn)) { 374 + err = PTR_ERR(nn); 375 + goto err_free_prev; 376 + } 377 + list_add_tail(&nn->port_list, &pf->ports); 378 + pf->num_netdevs++; 375 379 } 376 - list_add_tail(&nn->port_list, &pf->ports); 377 380 378 381 ctrl_bar += NFP_PF_CSR_SLICE_SIZE; 379 382 } 383 + 384 + if (list_empty(&pf->ports)) 385 + return -ENODEV; 380 386 381 387 return 0; 382 388 ··· 423 409 } 424 410 425 411 num_irqs = nfp_net_irqs_alloc(pf->pdev, pf->irq_entries, 426 - NFP_NET_MIN_PORT_IRQS * pf->num_ports, 412 + NFP_NET_MIN_PORT_IRQS * pf->num_netdevs, 427 413 wanted_irqs); 428 414 if (!num_irqs) { 429 415 nn_warn(nn, "Unable to allocate MSI-X Vectors. Exiting\n"); ··· 433 419 434 420 /* Distribute IRQs to ports */ 435 421 irqs_left = num_irqs; 436 - ports_left = pf->num_ports; 422 + ports_left = pf->num_netdevs; 437 423 list_for_each_entry(nn, &pf->ports, port_list) { 438 424 unsigned int n; 439 425 ··· 469 455 return err; 470 456 } 471 457 458 + static void nfp_net_pci_remove_finish(struct nfp_pf *pf) 459 + { 460 + nfp_net_debugfs_dir_clean(&pf->ddir); 461 + 462 + nfp_net_irqs_disable(pf->pdev); 463 + kfree(pf->irq_entries); 464 + 465 + nfp_cpp_area_release_free(pf->rx_area); 466 + nfp_cpp_area_release_free(pf->tx_area); 467 + nfp_cpp_area_release_free(pf->ctrl_area); 468 + } 469 + 470 + static void nfp_net_refresh_netdevs(struct work_struct *work) 471 + { 472 + struct nfp_pf *pf = container_of(work, struct nfp_pf, 473 + port_refresh_work); 474 + struct nfp_net *nn, *next; 475 + 476 + mutex_lock(&pf->port_lock); 477 + 478 + /* Check for nfp_net_pci_remove() racing against us */ 479 + if (list_empty(&pf->ports)) 480 + goto out; 481 + 482 + list_for_each_entry_safe(nn, next, &pf->ports, port_list) { 483 + if (!nn->eth_port) { 484 + nfp_warn(pf->cpp, "Warning: port %d not present after reconfig\n", 485 + nn->eth_port->eth_index); 486 + continue; 487 + } 488 + if (!nn->eth_port->override_changed) 489 + continue; 490 + 491 + nn_warn(nn, "Port config changed, unregistering. Reboot required before port will be operational again.\n"); 492 + 493 + nfp_net_debugfs_dir_clean(&nn->debugfs_dir); 494 + nfp_net_netdev_clean(nn->dp.netdev); 495 + 496 + list_del(&nn->port_list); 497 + pf->num_netdevs--; 498 + nfp_net_netdev_free(nn); 499 + } 500 + 501 + if (list_empty(&pf->ports)) 502 + nfp_net_pci_remove_finish(pf); 503 + out: 504 + mutex_unlock(&pf->port_lock); 505 + } 506 + 507 + void nfp_net_refresh_port_config(struct nfp_net *nn) 508 + { 509 + struct nfp_pf *pf = pci_get_drvdata(nn->pdev); 510 + struct nfp_eth_table *old_table; 511 + 512 + ASSERT_RTNL(); 513 + 514 + old_table = pf->eth_tbl; 515 + 516 + list_for_each_entry(nn, &pf->ports, port_list) 517 + nfp_net_link_changed_read_clear(nn); 518 + 519 + pf->eth_tbl = nfp_eth_read_ports(pf->cpp); 520 + if (!pf->eth_tbl) { 521 + pf->eth_tbl = old_table; 522 + nfp_err(pf->cpp, "Error refreshing port config!\n"); 523 + return; 524 + } 525 + 526 + list_for_each_entry(nn, &pf->ports, port_list) 527 + nn->eth_port = nfp_net_find_port(pf, nn->eth_port->eth_index); 528 + 529 + kfree(old_table); 530 + 531 + schedule_work(&pf->port_refresh_work); 532 + } 533 + 472 534 /* 473 535 * PCI device functions 474 536 */ ··· 558 468 int stride; 559 469 int err; 560 470 471 + INIT_WORK(&pf->port_refresh_work, nfp_net_refresh_netdevs); 472 + mutex_init(&pf->port_lock); 473 + 561 474 /* Verify that the board has completed initialization */ 562 475 if (!nfp_is_ready(pf->cpp)) { 563 476 nfp_err(pf->cpp, "NFP is not ready for NIC operation.\n"); 564 477 return -EINVAL; 565 478 } 566 479 480 + mutex_lock(&pf->port_lock); 567 481 pf->num_ports = nfp_net_pf_get_num_ports(pf); 568 482 569 483 ctrl_bar = nfp_net_pf_map_ctrl_bar(pf); 570 - if (!ctrl_bar) 571 - return pf->fw_loaded ? -EINVAL : -EPROBE_DEFER; 484 + if (!ctrl_bar) { 485 + err = pf->fw_loaded ? -EINVAL : -EPROBE_DEFER; 486 + goto err_unlock; 487 + } 572 488 573 489 nfp_net_get_fw_version(&fw_ver, ctrl_bar); 574 490 if (fw_ver.resv || fw_ver.class != NFP_NET_CFG_VERSION_CLASS_GENERIC) { ··· 648 552 if (err) 649 553 goto err_clean_ddir; 650 554 555 + mutex_unlock(&pf->port_lock); 556 + 651 557 return 0; 652 558 653 559 err_clean_ddir: ··· 659 561 nfp_cpp_area_release_free(pf->tx_area); 660 562 err_ctrl_unmap: 661 563 nfp_cpp_area_release_free(pf->ctrl_area); 564 + err_unlock: 565 + mutex_unlock(&pf->port_lock); 662 566 return err; 663 567 } 664 568 665 569 void nfp_net_pci_remove(struct nfp_pf *pf) 666 570 { 667 571 struct nfp_net *nn; 572 + 573 + mutex_lock(&pf->port_lock); 574 + if (list_empty(&pf->ports)) 575 + goto out; 668 576 669 577 list_for_each_entry(nn, &pf->ports, port_list) { 670 578 nfp_net_debugfs_dir_clean(&nn->debugfs_dir); ··· 680 576 681 577 nfp_net_pf_free_netdevs(pf); 682 578 683 - nfp_net_debugfs_dir_clean(&pf->ddir); 579 + nfp_net_pci_remove_finish(pf); 580 + out: 581 + mutex_unlock(&pf->port_lock); 684 582 685 - nfp_net_irqs_disable(pf->pdev); 686 - kfree(pf->irq_entries); 687 - 688 - nfp_cpp_area_release_free(pf->rx_area); 689 - nfp_cpp_area_release_free(pf->tx_area); 690 - nfp_cpp_area_release_free(pf->ctrl_area); 583 + cancel_work_sync(&pf->port_refresh_work); 691 584 }
+9 -9
drivers/net/ethernet/netronome/nfp/nfpcore/nfp.h
··· 48 48 49 49 const char *nfp_hwinfo_lookup(struct nfp_cpp *cpp, const char *lookup); 50 50 51 - /* Implemented in nfp_nsp.c */ 51 + /* Implemented in nfp_nsp.c, low level functions */ 52 52 53 53 struct nfp_nsp; 54 - struct firmware; 55 54 56 - struct nfp_nsp *nfp_nsp_open(struct nfp_cpp *cpp); 57 - void nfp_nsp_close(struct nfp_nsp *state); 58 - u16 nfp_nsp_get_abi_ver_major(struct nfp_nsp *state); 59 - u16 nfp_nsp_get_abi_ver_minor(struct nfp_nsp *state); 60 - int nfp_nsp_wait(struct nfp_nsp *state); 61 - int nfp_nsp_device_soft_reset(struct nfp_nsp *state); 62 - int nfp_nsp_load_fw(struct nfp_nsp *state, const struct firmware *fw); 55 + struct nfp_cpp *nfp_nsp_cpp(struct nfp_nsp *state); 56 + bool nfp_nsp_config_modified(struct nfp_nsp *state); 57 + void nfp_nsp_config_set_modified(struct nfp_nsp *state, bool modified); 58 + void *nfp_nsp_config_entries(struct nfp_nsp *state); 59 + unsigned int nfp_nsp_config_idx(struct nfp_nsp *state); 60 + void nfp_nsp_config_set_state(struct nfp_nsp *state, void *entries, 61 + unsigned int idx); 62 + void nfp_nsp_config_clear_state(struct nfp_nsp *state); 63 63 int nfp_nsp_read_eth_table(struct nfp_nsp *state, void *buf, unsigned int size); 64 64 int nfp_nsp_write_eth_table(struct nfp_nsp *state, 65 65 const void *buf, unsigned int size);
+77 -8
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
··· 49 49 50 50 #include "nfp.h" 51 51 #include "nfp_cpp.h" 52 + #include "nfp_nsp.h" 52 53 53 54 /* Offsets relative to the CSR base */ 54 55 #define NSP_STATUS 0x00 ··· 97 96 __MAX_SPCODE, 98 97 }; 99 98 99 + static const struct { 100 + int code; 101 + const char *msg; 102 + } nsp_errors[] = { 103 + { 6010, "could not map to phy for port" }, 104 + { 6011, "not an allowed rate/lanes for port" }, 105 + { 6012, "not an allowed rate/lanes for port" }, 106 + { 6013, "high/low error, change other port first" }, 107 + { 6014, "config not found in flash" }, 108 + }; 109 + 100 110 struct nfp_nsp { 101 111 struct nfp_cpp *cpp; 102 112 struct nfp_resource *res; ··· 115 103 u16 major; 116 104 u16 minor; 117 105 } ver; 106 + 107 + /* Eth table config state */ 108 + bool modified; 109 + unsigned int idx; 110 + void *entries; 118 111 }; 112 + 113 + struct nfp_cpp *nfp_nsp_cpp(struct nfp_nsp *state) 114 + { 115 + return state->cpp; 116 + } 117 + 118 + bool nfp_nsp_config_modified(struct nfp_nsp *state) 119 + { 120 + return state->modified; 121 + } 122 + 123 + void nfp_nsp_config_set_modified(struct nfp_nsp *state, bool modified) 124 + { 125 + state->modified = modified; 126 + } 127 + 128 + void *nfp_nsp_config_entries(struct nfp_nsp *state) 129 + { 130 + return state->entries; 131 + } 132 + 133 + unsigned int nfp_nsp_config_idx(struct nfp_nsp *state) 134 + { 135 + return state->idx; 136 + } 137 + 138 + void 139 + nfp_nsp_config_set_state(struct nfp_nsp *state, void *entries, unsigned int idx) 140 + { 141 + state->entries = entries; 142 + state->idx = idx; 143 + } 144 + 145 + void nfp_nsp_config_clear_state(struct nfp_nsp *state) 146 + { 147 + state->entries = NULL; 148 + state->idx = 0; 149 + } 150 + 151 + static void nfp_nsp_print_extended_error(struct nfp_nsp *state, u32 ret_val) 152 + { 153 + int i; 154 + 155 + if (!ret_val) 156 + return; 157 + 158 + for (i = 0; i < ARRAY_SIZE(nsp_errors); i++) 159 + if (ret_val == nsp_errors[i].code) 160 + nfp_err(state->cpp, "err msg: %s\n", nsp_errors[i].msg); 161 + } 119 162 120 163 static int nfp_nsp_check(struct nfp_nsp *state) 121 164 { ··· 305 238 static int nfp_nsp_command(struct nfp_nsp *state, u16 code, u32 option, 306 239 u32 buff_cpp, u64 buff_addr) 307 240 { 308 - u64 reg, nsp_base, nsp_buffer, nsp_status, nsp_command; 241 + u64 reg, ret_val, nsp_base, nsp_buffer, nsp_status, nsp_command; 309 242 struct nfp_cpp *cpp = state->cpp; 310 243 u32 nsp_cpp; 311 244 int err; ··· 358 291 return err; 359 292 } 360 293 294 + err = nfp_cpp_readq(cpp, nsp_cpp, nsp_command, &ret_val); 295 + if (err < 0) 296 + return err; 297 + ret_val = FIELD_GET(NSP_COMMAND_OPTION, ret_val); 298 + 361 299 err = FIELD_GET(NSP_STATUS_RESULT, reg); 362 300 if (err) { 363 - nfp_warn(cpp, "Result (error) code set: %d command: %d\n", 364 - -err, code); 301 + nfp_warn(cpp, "Result (error) code set: %d (%d) command: %d\n", 302 + -err, (int)ret_val, code); 303 + nfp_nsp_print_extended_error(state, ret_val); 365 304 return -err; 366 305 } 367 306 368 - err = nfp_cpp_readq(cpp, nsp_cpp, nsp_command, &reg); 369 - if (err < 0) 370 - return err; 371 - 372 - return FIELD_GET(NSP_COMMAND_OPTION, reg); 307 + return ret_val; 373 308 } 374 309 375 310 static int nfp_nsp_command_buf(struct nfp_nsp *nsp, u16 code, u32 option,
+306 -59
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c
··· 43 43 #include <linux/module.h> 44 44 45 45 #include "nfp.h" 46 - #include "nfp_nsp_eth.h" 46 + #include "nfp_nsp.h" 47 47 #include "nfp6000/nfp6000.h" 48 48 49 49 #define NSP_ETH_NBI_PORT_COUNT 24 50 50 #define NSP_ETH_MAX_COUNT (2 * NSP_ETH_NBI_PORT_COUNT) 51 51 #define NSP_ETH_TABLE_SIZE (NSP_ETH_MAX_COUNT * \ 52 - sizeof(struct eth_table_entry)) 52 + sizeof(union eth_table_entry)) 53 53 54 54 #define NSP_ETH_PORT_LANES GENMASK_ULL(3, 0) 55 55 #define NSP_ETH_PORT_INDEX GENMASK_ULL(15, 8) ··· 58 58 59 59 #define NSP_ETH_PORT_LANES_MASK cpu_to_le64(NSP_ETH_PORT_LANES) 60 60 61 + #define NSP_ETH_STATE_CONFIGURED BIT_ULL(0) 61 62 #define NSP_ETH_STATE_ENABLED BIT_ULL(1) 62 63 #define NSP_ETH_STATE_TX_ENABLED BIT_ULL(2) 63 64 #define NSP_ETH_STATE_RX_ENABLED BIT_ULL(3) 64 65 #define NSP_ETH_STATE_RATE GENMASK_ULL(11, 8) 66 + #define NSP_ETH_STATE_INTERFACE GENMASK_ULL(19, 12) 67 + #define NSP_ETH_STATE_MEDIA GENMASK_ULL(21, 20) 68 + #define NSP_ETH_STATE_OVRD_CHNG BIT_ULL(22) 69 + #define NSP_ETH_STATE_ANEG GENMASK_ULL(25, 23) 65 70 71 + #define NSP_ETH_CTRL_CONFIGURED BIT_ULL(0) 66 72 #define NSP_ETH_CTRL_ENABLED BIT_ULL(1) 67 73 #define NSP_ETH_CTRL_TX_ENABLED BIT_ULL(2) 68 74 #define NSP_ETH_CTRL_RX_ENABLED BIT_ULL(3) 75 + #define NSP_ETH_CTRL_SET_RATE BIT_ULL(4) 76 + #define NSP_ETH_CTRL_SET_LANES BIT_ULL(5) 77 + #define NSP_ETH_CTRL_SET_ANEG BIT_ULL(6) 78 + 79 + enum nfp_eth_raw { 80 + NSP_ETH_RAW_PORT = 0, 81 + NSP_ETH_RAW_STATE, 82 + NSP_ETH_RAW_MAC, 83 + NSP_ETH_RAW_CONTROL, 84 + 85 + NSP_ETH_NUM_RAW 86 + }; 69 87 70 88 enum nfp_eth_rate { 71 89 RATE_INVALID = 0, ··· 94 76 RATE_25G, 95 77 }; 96 78 97 - struct eth_table_entry { 98 - __le64 port; 99 - __le64 state; 100 - u8 mac_addr[6]; 101 - u8 resv[2]; 102 - __le64 control; 79 + union eth_table_entry { 80 + struct { 81 + __le64 port; 82 + __le64 state; 83 + u8 mac_addr[6]; 84 + u8 resv[2]; 85 + __le64 control; 86 + }; 87 + __le64 raw[NSP_ETH_NUM_RAW]; 103 88 }; 104 89 105 - static unsigned int nfp_eth_rate(enum nfp_eth_rate rate) 90 + static const struct { 91 + enum nfp_eth_rate rate; 92 + unsigned int speed; 93 + } nsp_eth_rate_tbl[] = { 94 + { RATE_INVALID, 0, }, 95 + { RATE_10M, SPEED_10, }, 96 + { RATE_100M, SPEED_100, }, 97 + { RATE_1G, SPEED_1000, }, 98 + { RATE_10G, SPEED_10000, }, 99 + { RATE_25G, SPEED_25000, }, 100 + }; 101 + 102 + static unsigned int nfp_eth_rate2speed(enum nfp_eth_rate rate) 106 103 { 107 - unsigned int rate_xlate[] = { 108 - [RATE_INVALID] = 0, 109 - [RATE_10M] = SPEED_10, 110 - [RATE_100M] = SPEED_100, 111 - [RATE_1G] = SPEED_1000, 112 - [RATE_10G] = SPEED_10000, 113 - [RATE_25G] = SPEED_25000, 114 - }; 104 + int i; 115 105 116 - if (rate >= ARRAY_SIZE(rate_xlate)) 117 - return 0; 106 + for (i = 0; i < ARRAY_SIZE(nsp_eth_rate_tbl); i++) 107 + if (nsp_eth_rate_tbl[i].rate == rate) 108 + return nsp_eth_rate_tbl[i].speed; 118 109 119 - return rate_xlate[rate]; 110 + return 0; 111 + } 112 + 113 + static unsigned int nfp_eth_speed2rate(unsigned int speed) 114 + { 115 + int i; 116 + 117 + for (i = 0; i < ARRAY_SIZE(nsp_eth_rate_tbl); i++) 118 + if (nsp_eth_rate_tbl[i].speed == speed) 119 + return nsp_eth_rate_tbl[i].rate; 120 + 121 + return RATE_INVALID; 120 122 } 121 123 122 124 static void nfp_eth_copy_mac_reverse(u8 *dst, const u8 *src) ··· 148 110 } 149 111 150 112 static void 151 - nfp_eth_port_translate(const struct eth_table_entry *src, unsigned int index, 152 - struct nfp_eth_table_port *dst) 113 + nfp_eth_port_translate(struct nfp_nsp *nsp, const union eth_table_entry *src, 114 + unsigned int index, struct nfp_eth_table_port *dst) 153 115 { 154 116 unsigned int rate; 155 117 u64 port, state; ··· 167 129 dst->tx_enabled = FIELD_GET(NSP_ETH_STATE_TX_ENABLED, state); 168 130 dst->rx_enabled = FIELD_GET(NSP_ETH_STATE_RX_ENABLED, state); 169 131 170 - rate = nfp_eth_rate(FIELD_GET(NSP_ETH_STATE_RATE, state)); 132 + rate = nfp_eth_rate2speed(FIELD_GET(NSP_ETH_STATE_RATE, state)); 171 133 dst->speed = dst->lanes * rate; 134 + 135 + dst->interface = FIELD_GET(NSP_ETH_STATE_INTERFACE, state); 136 + dst->media = FIELD_GET(NSP_ETH_STATE_MEDIA, state); 172 137 173 138 nfp_eth_copy_mac_reverse(dst->mac_addr, src->mac_addr); 174 139 175 140 dst->label_port = FIELD_GET(NSP_ETH_PORT_PHYLABEL, port); 176 141 dst->label_subport = FIELD_GET(NSP_ETH_PORT_LABEL, port); 142 + 143 + if (nfp_nsp_get_abi_ver_minor(nsp) < 17) 144 + return; 145 + 146 + dst->override_changed = FIELD_GET(NSP_ETH_STATE_OVRD_CHNG, state); 147 + dst->aneg = FIELD_GET(NSP_ETH_STATE_ANEG, state); 177 148 } 178 149 179 150 static void ··· 207 160 table->ports[i].is_split = true; 208 161 break; 209 162 } 163 + } 164 + 165 + static void 166 + nfp_eth_calc_port_type(struct nfp_cpp *cpp, struct nfp_eth_table_port *entry) 167 + { 168 + if (entry->interface == NFP_INTERFACE_NONE) { 169 + entry->port_type = PORT_NONE; 170 + return; 171 + } 172 + 173 + if (entry->media == NFP_MEDIA_FIBRE) 174 + entry->port_type = PORT_FIBRE; 175 + else 176 + entry->port_type = PORT_DA; 210 177 } 211 178 212 179 /** ··· 250 189 struct nfp_eth_table * 251 190 __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp) 252 191 { 253 - struct eth_table_entry *entries; 192 + union eth_table_entry *entries; 254 193 struct nfp_eth_table *table; 255 194 int i, j, ret, cnt = 0; 256 195 ··· 286 225 table->count = cnt; 287 226 for (i = 0, j = 0; i < NSP_ETH_MAX_COUNT; i++) 288 227 if (entries[i].port & NSP_ETH_PORT_LANES_MASK) 289 - nfp_eth_port_translate(&entries[i], i, 228 + nfp_eth_port_translate(nsp, &entries[i], i, 290 229 &table->ports[j++]); 291 230 292 231 nfp_eth_mark_split_ports(cpp, table); 232 + for (i = 0; i < table->count; i++) 233 + nfp_eth_calc_port_type(cpp, &table->ports[i]); 293 234 294 235 kfree(entries); 295 236 ··· 300 237 err: 301 238 kfree(entries); 302 239 return NULL; 240 + } 241 + 242 + struct nfp_nsp *nfp_eth_config_start(struct nfp_cpp *cpp, unsigned int idx) 243 + { 244 + union eth_table_entry *entries; 245 + struct nfp_nsp *nsp; 246 + int ret; 247 + 248 + entries = kzalloc(NSP_ETH_TABLE_SIZE, GFP_KERNEL); 249 + if (!entries) 250 + return ERR_PTR(-ENOMEM); 251 + 252 + nsp = nfp_nsp_open(cpp); 253 + if (IS_ERR(nsp)) { 254 + kfree(entries); 255 + return nsp; 256 + } 257 + 258 + ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE); 259 + if (ret < 0) { 260 + nfp_err(cpp, "reading port table failed %d\n", ret); 261 + goto err; 262 + } 263 + 264 + if (!(entries[idx].port & NSP_ETH_PORT_LANES_MASK)) { 265 + nfp_warn(cpp, "trying to set port state on disabled port %d\n", 266 + idx); 267 + goto err; 268 + } 269 + 270 + nfp_nsp_config_set_state(nsp, entries, idx); 271 + return nsp; 272 + 273 + err: 274 + nfp_nsp_close(nsp); 275 + kfree(entries); 276 + return ERR_PTR(-EIO); 277 + } 278 + 279 + void nfp_eth_config_cleanup_end(struct nfp_nsp *nsp) 280 + { 281 + union eth_table_entry *entries = nfp_nsp_config_entries(nsp); 282 + 283 + nfp_nsp_config_set_modified(nsp, false); 284 + nfp_nsp_config_clear_state(nsp); 285 + nfp_nsp_close(nsp); 286 + kfree(entries); 287 + } 288 + 289 + /** 290 + * nfp_eth_config_commit_end() - perform recorded configuration changes 291 + * @nsp: NFP NSP handle returned from nfp_eth_config_start() 292 + * 293 + * Perform the configuration which was requested with __nfp_eth_set_*() 294 + * helpers and recorded in @nsp state. If device was already configured 295 + * as requested or no __nfp_eth_set_*() operations were made no NSP command 296 + * will be performed. 297 + * 298 + * Return: 299 + * 0 - configuration successful; 300 + * 1 - no changes were needed; 301 + * -ERRNO - configuration failed. 302 + */ 303 + int nfp_eth_config_commit_end(struct nfp_nsp *nsp) 304 + { 305 + union eth_table_entry *entries = nfp_nsp_config_entries(nsp); 306 + int ret = 1; 307 + 308 + if (nfp_nsp_config_modified(nsp)) { 309 + ret = nfp_nsp_write_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE); 310 + ret = ret < 0 ? ret : 0; 311 + } 312 + 313 + nfp_eth_config_cleanup_end(nsp); 314 + 315 + return ret; 303 316 } 304 317 305 318 /** ··· 391 252 */ 392 253 int nfp_eth_set_mod_enable(struct nfp_cpp *cpp, unsigned int idx, bool enable) 393 254 { 394 - struct eth_table_entry *entries; 255 + union eth_table_entry *entries; 395 256 struct nfp_nsp *nsp; 396 257 u64 reg; 397 - int ret; 398 258 399 - entries = kzalloc(NSP_ETH_TABLE_SIZE, GFP_KERNEL); 400 - if (!entries) 401 - return -ENOMEM; 402 - 403 - nsp = nfp_nsp_open(cpp); 404 - if (IS_ERR(nsp)) { 405 - kfree(entries); 259 + nsp = nfp_eth_config_start(cpp, idx); 260 + if (IS_ERR(nsp)) 406 261 return PTR_ERR(nsp); 407 - } 408 262 409 - ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE); 410 - if (ret < 0) { 411 - nfp_err(cpp, "reading port table failed %d\n", ret); 412 - goto exit_close_nsp; 413 - } 414 - 415 - if (!(entries[idx].port & NSP_ETH_PORT_LANES_MASK)) { 416 - nfp_warn(cpp, "trying to set port state on disabled port %d\n", 417 - idx); 418 - ret = -EINVAL; 419 - goto exit_close_nsp; 420 - } 263 + entries = nfp_nsp_config_entries(nsp); 421 264 422 265 /* Check if we are already in requested state */ 423 266 reg = le64_to_cpu(entries[idx].state); 424 - if (enable == FIELD_GET(NSP_ETH_CTRL_ENABLED, reg)) { 425 - ret = 0; 426 - goto exit_close_nsp; 267 + if (enable != FIELD_GET(NSP_ETH_CTRL_ENABLED, reg)) { 268 + reg = le64_to_cpu(entries[idx].control); 269 + reg &= ~NSP_ETH_CTRL_ENABLED; 270 + reg |= FIELD_PREP(NSP_ETH_CTRL_ENABLED, enable); 271 + entries[idx].control = cpu_to_le64(reg); 272 + 273 + nfp_nsp_config_set_modified(nsp, true); 427 274 } 428 275 429 - reg = le64_to_cpu(entries[idx].control); 430 - reg &= ~NSP_ETH_CTRL_ENABLED; 431 - reg |= FIELD_PREP(NSP_ETH_CTRL_ENABLED, enable); 432 - entries[idx].control = cpu_to_le64(reg); 276 + return nfp_eth_config_commit_end(nsp); 277 + } 433 278 434 - ret = nfp_nsp_write_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE); 435 - exit_close_nsp: 436 - nfp_nsp_close(nsp); 437 - kfree(entries); 279 + /** 280 + * nfp_eth_set_configured() - set PHY module configured control bit 281 + * @cpp: NFP CPP handle 282 + * @idx: NFP chip-wide port index 283 + * @configed: Desired state 284 + * 285 + * Set the ifup/ifdown state on the PHY. 286 + * 287 + * Return: 0 or -ERRNO. 288 + */ 289 + int nfp_eth_set_configured(struct nfp_cpp *cpp, unsigned int idx, bool configed) 290 + { 291 + union eth_table_entry *entries; 292 + struct nfp_nsp *nsp; 293 + u64 reg; 438 294 439 - return ret < 0 ? ret : 0; 295 + nsp = nfp_eth_config_start(cpp, idx); 296 + if (IS_ERR(nsp)) 297 + return PTR_ERR(nsp); 298 + 299 + entries = nfp_nsp_config_entries(nsp); 300 + 301 + /* Check if we are already in requested state */ 302 + reg = le64_to_cpu(entries[idx].state); 303 + if (configed != FIELD_GET(NSP_ETH_STATE_CONFIGURED, reg)) { 304 + reg = le64_to_cpu(entries[idx].control); 305 + reg &= ~NSP_ETH_CTRL_CONFIGURED; 306 + reg |= FIELD_PREP(NSP_ETH_CTRL_CONFIGURED, configed); 307 + entries[idx].control = cpu_to_le64(reg); 308 + 309 + nfp_nsp_config_set_modified(nsp, true); 310 + } 311 + 312 + return nfp_eth_config_commit_end(nsp); 313 + } 314 + 315 + /* Force inline, FIELD_* macroes require masks to be compilation-time known */ 316 + static __always_inline int 317 + nfp_eth_set_bit_config(struct nfp_nsp *nsp, unsigned int raw_idx, 318 + const u64 mask, unsigned int val, const u64 ctrl_bit) 319 + { 320 + union eth_table_entry *entries = nfp_nsp_config_entries(nsp); 321 + unsigned int idx = nfp_nsp_config_idx(nsp); 322 + u64 reg; 323 + 324 + /* Note: set features were added in ABI 0.14 but the error 325 + * codes were initially not populated correctly. 326 + */ 327 + if (nfp_nsp_get_abi_ver_minor(nsp) < 17) { 328 + nfp_err(nfp_nsp_cpp(nsp), 329 + "set operations not supported, please update flash\n"); 330 + return -EOPNOTSUPP; 331 + } 332 + 333 + /* Check if we are already in requested state */ 334 + reg = le64_to_cpu(entries[idx].raw[raw_idx]); 335 + if (val == FIELD_GET(mask, reg)) 336 + return 0; 337 + 338 + reg &= ~mask; 339 + reg |= FIELD_PREP(mask, val); 340 + entries[idx].raw[raw_idx] = cpu_to_le64(reg); 341 + 342 + entries[idx].control |= cpu_to_le64(ctrl_bit); 343 + 344 + nfp_nsp_config_set_modified(nsp, true); 345 + 346 + return 0; 347 + } 348 + 349 + /** 350 + * __nfp_eth_set_aneg() - set PHY autonegotiation control bit 351 + * @nsp: NFP NSP handle returned from nfp_eth_config_start() 352 + * @mode: Desired autonegotiation mode 353 + * 354 + * Allow/disallow PHY module to advertise/perform autonegotiation. 355 + * Will write to hwinfo overrides in the flash (persistent config). 356 + * 357 + * Return: 0 or -ERRNO. 358 + */ 359 + int __nfp_eth_set_aneg(struct nfp_nsp *nsp, enum nfp_eth_aneg mode) 360 + { 361 + return nfp_eth_set_bit_config(nsp, NSP_ETH_RAW_STATE, 362 + NSP_ETH_STATE_ANEG, mode, 363 + NSP_ETH_CTRL_SET_ANEG); 364 + } 365 + 366 + /** 367 + * __nfp_eth_set_speed() - set interface speed/rate 368 + * @nsp: NFP NSP handle returned from nfp_eth_config_start() 369 + * @speed: Desired speed (per lane) 370 + * 371 + * Set lane speed. Provided @speed value should be subport speed divided 372 + * by number of lanes this subport is spanning (i.e. 10000 for 40G, 25000 for 373 + * 50G, etc.) 374 + * Will write to hwinfo overrides in the flash (persistent config). 375 + * 376 + * Return: 0 or -ERRNO. 377 + */ 378 + int __nfp_eth_set_speed(struct nfp_nsp *nsp, unsigned int speed) 379 + { 380 + enum nfp_eth_rate rate; 381 + 382 + rate = nfp_eth_speed2rate(speed); 383 + if (rate == RATE_INVALID) { 384 + nfp_warn(nfp_nsp_cpp(nsp), 385 + "could not find matching lane rate for speed %u\n", 386 + speed); 387 + return -EINVAL; 388 + } 389 + 390 + return nfp_eth_set_bit_config(nsp, NSP_ETH_RAW_STATE, 391 + NSP_ETH_STATE_RATE, rate, 392 + NSP_ETH_CTRL_SET_RATE); 393 + } 394 + 395 + /** 396 + * __nfp_eth_set_split() - set interface lane split 397 + * @nsp: NFP NSP handle returned from nfp_eth_config_start() 398 + * @lanes: Desired lanes per port 399 + * 400 + * Set number of lanes in the port. 401 + * Will write to hwinfo overrides in the flash (persistent config). 402 + * 403 + * Return: 0 or -ERRNO. 404 + */ 405 + int __nfp_eth_set_split(struct nfp_nsp *nsp, unsigned int lanes) 406 + { 407 + return nfp_eth_set_bit_config(nsp, NSP_ETH_RAW_PORT, NSP_ETH_PORT_LANES, 408 + lanes, NSP_ETH_CTRL_SET_LANES); 440 409 }
+63 -5
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.h drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h
··· 31 31 * SOFTWARE. 32 32 */ 33 33 34 - #ifndef NSP_NSP_ETH_H 35 - #define NSP_NSP_ETH_H 1 34 + #ifndef NSP_NSP_H 35 + #define NSP_NSP_H 1 36 36 37 37 #include <linux/types.h> 38 38 #include <linux/if_ether.h> 39 + 40 + struct firmware; 41 + struct nfp_cpp; 42 + struct nfp_nsp; 43 + 44 + struct nfp_nsp *nfp_nsp_open(struct nfp_cpp *cpp); 45 + void nfp_nsp_close(struct nfp_nsp *state); 46 + u16 nfp_nsp_get_abi_ver_major(struct nfp_nsp *state); 47 + u16 nfp_nsp_get_abi_ver_minor(struct nfp_nsp *state); 48 + int nfp_nsp_wait(struct nfp_nsp *state); 49 + int nfp_nsp_device_soft_reset(struct nfp_nsp *state); 50 + int nfp_nsp_load_fw(struct nfp_nsp *state, const struct firmware *fw); 51 + 52 + enum nfp_eth_interface { 53 + NFP_INTERFACE_NONE = 0, 54 + NFP_INTERFACE_SFP = 1, 55 + NFP_INTERFACE_SFPP = 10, 56 + NFP_INTERFACE_SFP28 = 28, 57 + NFP_INTERFACE_QSFP = 40, 58 + NFP_INTERFACE_CXP = 100, 59 + NFP_INTERFACE_QSFP28 = 112, 60 + }; 61 + 62 + enum nfp_eth_media { 63 + NFP_MEDIA_DAC_PASSIVE = 0, 64 + NFP_MEDIA_DAC_ACTIVE, 65 + NFP_MEDIA_FIBRE, 66 + }; 67 + 68 + enum nfp_eth_aneg { 69 + NFP_ANEG_AUTO = 0, 70 + NFP_ANEG_SEARCH, 71 + NFP_ANEG_25G_CONSORTIUM, 72 + NFP_ANEG_25G_IEEE, 73 + NFP_ANEG_DISABLED, 74 + }; 39 75 40 76 /** 41 77 * struct nfp_eth_table - ETH table information ··· 84 48 * @base: first channel index (within NBI) 85 49 * @lanes: number of channels 86 50 * @speed: interface speed (in Mbps) 51 + * @interface: interface (module) plugged in 52 + * @media: media type of the @interface 53 + * @aneg: auto negotiation mode 87 54 * @mac_addr: interface MAC address 88 55 * @label_port: port id 89 56 * @label_subport: id of interface within port (for split ports) 90 57 * @enabled: is enabled? 91 58 * @tx_enabled: is TX enabled? 92 59 * @rx_enabled: is RX enabled? 60 + * @override_changed: is media reconfig pending? 93 61 * 62 + * @port_type: one of %PORT_* defines for ethtool 94 63 * @is_split: is interface part of a split port 95 64 */ 96 65 struct nfp_eth_table { ··· 108 67 unsigned int lanes; 109 68 unsigned int speed; 110 69 70 + unsigned int interface; 71 + enum nfp_eth_media media; 72 + 73 + enum nfp_eth_aneg aneg; 74 + 111 75 u8 mac_addr[ETH_ALEN]; 112 76 113 77 u8 label_port; ··· 122 76 bool tx_enabled; 123 77 bool rx_enabled; 124 78 79 + bool override_changed; 80 + 125 81 /* Computed fields */ 82 + u8 port_type; 83 + 126 84 bool is_split; 127 85 } ports[0]; 128 86 }; 129 87 130 - struct nfp_cpp; 131 - struct nfp_nsp; 132 - 133 88 struct nfp_eth_table *nfp_eth_read_ports(struct nfp_cpp *cpp); 134 89 struct nfp_eth_table * 135 90 __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp); 91 + 136 92 int nfp_eth_set_mod_enable(struct nfp_cpp *cpp, unsigned int idx, bool enable); 93 + int nfp_eth_set_configured(struct nfp_cpp *cpp, unsigned int idx, 94 + bool configed); 95 + 96 + struct nfp_nsp *nfp_eth_config_start(struct nfp_cpp *cpp, unsigned int idx); 97 + int nfp_eth_config_commit_end(struct nfp_nsp *nsp); 98 + void nfp_eth_config_cleanup_end(struct nfp_nsp *nsp); 99 + 100 + int __nfp_eth_set_aneg(struct nfp_nsp *nsp, enum nfp_eth_aneg mode); 101 + int __nfp_eth_set_speed(struct nfp_nsp *nsp, unsigned int speed); 102 + int __nfp_eth_set_split(struct nfp_nsp *nsp, unsigned int lanes); 137 103 138 104 #endif