From 54d0165f68b8505d3419aa0a1d6492598eef9f97 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Wed, 13 Sep 2023 16:40:27 -0700 Subject: [PATCH] modules/mqnic: Register ports with devlink Signed-off-by: Alex Forencich --- modules/mqnic/mqnic.h | 24 +++++---- modules/mqnic/mqnic_devlink.c | 1 - modules/mqnic/mqnic_ethtool.c | 6 +-- modules/mqnic/mqnic_if.c | 8 ++- modules/mqnic/mqnic_main.c | 5 +- modules/mqnic/mqnic_netdev.c | 91 +++++++++++++++++++---------------- modules/mqnic/mqnic_port.c | 16 +++++- 7 files changed, 82 insertions(+), 69 deletions(-) diff --git a/modules/mqnic/mqnic.h b/modules/mqnic/mqnic.h index 58a4d4d8f..5e78a4b2e 100644 --- a/modules/mqnic/mqnic.h +++ b/modules/mqnic/mqnic.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -151,8 +152,7 @@ struct mqnic_dev { struct mqnic_reg_block *clk_info_rb; struct mqnic_reg_block *phc_rb; - int dev_port_max; - int dev_port_limit; + int phys_port_max; u32 fpga_id; u32 fw_id; @@ -349,8 +349,11 @@ struct mqnic_port { struct mqnic_reg_block *port_ctrl_rb; int index; + int phys_index; u32 port_features; + + struct devlink_port dl_port; }; struct mqnic_sched_block { @@ -380,10 +383,6 @@ struct mqnic_if { int index; - int dev_port_base; - int dev_port_max; - int dev_port_limit; - u32 if_features; u32 max_tx_mtu; @@ -423,6 +422,7 @@ struct mqnic_if { struct mqnic_priv { struct device *dev; struct net_device *ndev; + struct devlink_port *dl_port; struct mqnic_dev *mdev; struct mqnic_if *interface; @@ -449,11 +449,8 @@ struct mqnic_priv { struct rw_semaphore rxq_table_sem; struct radix_tree_root rxq_table; - u32 sched_block_count; - struct mqnic_sched_block *sched_block[MQNIC_MAX_PORTS]; - - u32 port_count; - struct mqnic_port *port[MQNIC_MAX_PORTS]; + struct mqnic_sched_block *sched_block; + struct mqnic_port *port; u32 max_desc_block_size; @@ -508,7 +505,7 @@ void mqnic_interface_set_rx_queue_map_indir_table(struct mqnic_if *interface, in // mqnic_port.c struct mqnic_port *mqnic_create_port(struct mqnic_if *interface, int index, - struct mqnic_reg_block *port_rb); + int phys_index, struct mqnic_reg_block *port_rb); void mqnic_destroy_port(struct mqnic_port *port); u32 mqnic_port_get_tx_ctrl(struct mqnic_port *port); void mqnic_port_set_tx_ctrl(struct mqnic_port *port, u32 val); @@ -526,7 +523,8 @@ int mqnic_start_port(struct net_device *ndev); void mqnic_stop_port(struct net_device *ndev); int mqnic_update_indir_table(struct net_device *ndev); void mqnic_update_stats(struct net_device *ndev); -struct net_device *mqnic_create_netdev(struct mqnic_if *interface, int index, int dev_port); +struct net_device *mqnic_create_netdev(struct mqnic_if *interface, int index, + struct mqnic_port *port, struct mqnic_sched_block *sched_block); void mqnic_destroy_netdev(struct net_device *ndev); // mqnic_sched_block.c diff --git a/modules/mqnic/mqnic_devlink.c b/modules/mqnic/mqnic_devlink.c index a433e66ea..a39fcd36f 100644 --- a/modules/mqnic/mqnic_devlink.c +++ b/modules/mqnic/mqnic_devlink.c @@ -6,7 +6,6 @@ #include "mqnic.h" #include -#include static int mqnic_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, struct netlink_ext_ack *extack) diff --git a/modules/mqnic/mqnic_ethtool.c b/modules/mqnic/mqnic_ethtool.c index 613e1af64..d5b7c2653 100644 --- a/modules/mqnic/mqnic_ethtool.c +++ b/modules/mqnic/mqnic_ethtool.c @@ -143,7 +143,7 @@ static void mqnic_get_pauseparam(struct net_device *ndev, if (!(priv->if_features & MQNIC_IF_FEATURE_LFC)) return; - val = mqnic_port_get_lfc_ctrl(priv->port[0]); + val = mqnic_port_get_lfc_ctrl(priv->port); param->rx_pause = !!(val & MQNIC_PORT_LFC_CTRL_RX_LFC_EN); param->tx_pause = !!(val & MQNIC_PORT_LFC_CTRL_TX_LFC_EN); @@ -161,7 +161,7 @@ static int mqnic_set_pauseparam(struct net_device *ndev, if (param->autoneg) return -EINVAL; - val = mqnic_port_get_lfc_ctrl(priv->port[0]); + val = mqnic_port_get_lfc_ctrl(priv->port); if (param->rx_pause) val |= MQNIC_PORT_LFC_CTRL_RX_LFC_EN; @@ -173,7 +173,7 @@ static int mqnic_set_pauseparam(struct net_device *ndev, else val &= ~MQNIC_PORT_LFC_CTRL_TX_LFC_EN; - mqnic_port_set_lfc_ctrl(priv->port[0], val); + mqnic_port_set_lfc_ctrl(priv->port, val); return 0; } diff --git a/modules/mqnic/mqnic_if.c b/modules/mqnic/mqnic_if.c index 4ca99fec8..3445f13e3 100644 --- a/modules/mqnic/mqnic_if.c +++ b/modules/mqnic/mqnic_if.c @@ -221,7 +221,7 @@ struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __ goto fail; } - port = mqnic_create_port(interface, k, port_rb); + port = mqnic_create_port(interface, k, mdev->phys_port_max++, port_rb); if (IS_ERR_OR_NULL(port)) { ret = PTR_ERR(port); goto fail; @@ -267,12 +267,10 @@ struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __ } // create net_devices - interface->dev_port_base = mdev->dev_port_max; - interface->dev_port_max = mdev->dev_port_max; - interface->ndev_count = 1; for (k = 0; k < interface->ndev_count; k++) { - struct net_device *ndev = mqnic_create_netdev(interface, k, interface->dev_port_max++); + struct net_device *ndev = mqnic_create_netdev(interface, k, + interface->port[k], interface->sched_block[k]); if (IS_ERR_OR_NULL(ndev)) { ret = PTR_ERR(ndev); goto fail; diff --git a/modules/mqnic/mqnic_main.c b/modules/mqnic/mqnic_main.c index b8fad741d..aaa8f9d69 100644 --- a/modules/mqnic/mqnic_main.c +++ b/modules/mqnic/mqnic_main.c @@ -9,7 +9,6 @@ #include #include #include -#include #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0) #include @@ -364,8 +363,7 @@ static int mqnic_common_probe(struct mqnic_dev *mqnic) mutex_init(&mqnic->state_lock); // Set up interfaces - mqnic->dev_port_max = 0; - mqnic->dev_port_limit = MQNIC_MAX_IF; + mqnic->phys_port_max = 0; mqnic->if_count = min_t(u32, mqnic->if_count, MQNIC_MAX_IF); @@ -378,7 +376,6 @@ static int mqnic_common_probe(struct mqnic_dev *mqnic) goto fail_create_if; } mqnic->interface[k] = interface; - mqnic->dev_port_max = mqnic->interface[k]->dev_port_max; } // pass module I2C clients to interface instances diff --git a/modules/mqnic/mqnic_netdev.c b/modules/mqnic/mqnic_netdev.c index 06972c4c4..853b0f8d8 100644 --- a/modules/mqnic/mqnic_netdev.c +++ b/modules/mqnic/mqnic_netdev.c @@ -159,11 +159,10 @@ int mqnic_start_port(struct net_device *ndev) } up_read(&priv->rxq_table_sem); - // enable first scheduler - mqnic_activate_sched_block(priv->sched_block[0]); + mqnic_port_set_tx_ctrl(priv->port, MQNIC_PORT_TX_CTRL_EN); - // enable first port - mqnic_port_set_tx_ctrl(priv->port[0], MQNIC_PORT_TX_CTRL_EN); + // enable scheduler + mqnic_activate_sched_block(priv->sched_block); netif_tx_start_all_queues(ndev); netif_device_attach(ndev); @@ -176,7 +175,7 @@ int mqnic_start_port(struct net_device *ndev) netif_carrier_on(ndev); } - mqnic_port_set_rx_ctrl(priv->port[0], MQNIC_PORT_RX_CTRL_EN); + mqnic_port_set_rx_ctrl(priv->port, MQNIC_PORT_RX_CTRL_EN); return 0; @@ -191,7 +190,6 @@ void mqnic_stop_port(struct net_device *ndev) struct mqnic_cq *cq; struct radix_tree_iter iter; void **slot; - int k; netdev_info(ndev, "%s on interface %d netdev %d", __func__, priv->interface->index, priv->index); @@ -199,7 +197,7 @@ void mqnic_stop_port(struct net_device *ndev) if (mqnic_link_status_poll) del_timer_sync(&priv->link_status_timer); - mqnic_port_set_rx_ctrl(priv->port[0], 0); + mqnic_port_set_rx_ctrl(priv->port, 0); netif_tx_lock_bh(ndev); // if (detach) @@ -214,9 +212,8 @@ void mqnic_stop_port(struct net_device *ndev) mqnic_update_stats(ndev); spin_unlock_bh(&priv->stats_lock); - // disable schedulers - for (k = 0; k < priv->sched_block_count; k++) - mqnic_deactivate_sched_block(priv->sched_block[k]); + // disable scheduler + mqnic_deactivate_sched_block(priv->sched_block); // disable TX and RX queues down_read(&priv->txq_table_sem); @@ -237,7 +234,7 @@ void mqnic_stop_port(struct net_device *ndev) msleep(20); - mqnic_port_set_tx_ctrl(priv->port[0], 0); + mqnic_port_set_tx_ctrl(priv->port, 0); priv->port_up = false; @@ -481,6 +478,14 @@ static int mqnic_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) } } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0) +static struct devlink_port *mqnic_get_devlink_port(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + return priv->dl_port; +} +#endif + static const struct net_device_ops mqnic_netdev_ops = { .ndo_open = mqnic_open, .ndo_stop = mqnic_close, @@ -493,34 +498,29 @@ static const struct net_device_ops mqnic_netdev_ops = { #else .ndo_do_ioctl = mqnic_ioctl, #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0) + .ndo_get_devlink_port = mqnic_get_devlink_port, +#endif }; static void mqnic_link_status_timeout(struct timer_list *timer) { struct mqnic_priv *priv = from_timer(priv, timer, link_status_timer); - int k; - unsigned int up; + unsigned int up = 1; - // "combine" all TX/RX status signals of all ports of this netdev - for (k = 0, up = 0; k < priv->port_count; k++) { - if (!(mqnic_port_get_tx_ctrl(priv->port[k]) & MQNIC_PORT_TX_CTRL_STATUS)) - continue; - if (!(mqnic_port_get_rx_ctrl(priv->port[k]) & MQNIC_PORT_RX_CTRL_STATUS)) - continue; + if (!(mqnic_port_get_tx_ctrl(priv->port) & MQNIC_PORT_TX_CTRL_STATUS)) + up = 0; + if (!(mqnic_port_get_rx_ctrl(priv->port) & MQNIC_PORT_RX_CTRL_STATUS)) + up = 0; - up++; - } - - if (up < priv->port_count) { - // report carrier off, as soon as a one port's TX/RX status is deasserted - if (priv->link_status) { - netif_carrier_off(priv->ndev); + if (up) { + if (!priv->link_status) { + netif_carrier_on(priv->ndev); priv->link_status = !priv->link_status; } } else { - // report carrier on, as soon as all ports' TX/RX status is asserted - if (!priv->link_status) { - netif_carrier_on(priv->ndev); + if (priv->link_status) { + netif_carrier_off(priv->ndev); priv->link_status = !priv->link_status; } } @@ -528,7 +528,8 @@ static void mqnic_link_status_timeout(struct timer_list *timer) mod_timer(&priv->link_status_timer, jiffies + msecs_to_jiffies(mqnic_link_status_poll)); } -struct net_device *mqnic_create_netdev(struct mqnic_if *interface, int index, int dev_port) +struct net_device *mqnic_create_netdev(struct mqnic_if *interface, int index, + struct mqnic_port *port, struct mqnic_sched_block *sched_block) { struct mqnic_dev *mdev = interface->mdev; struct device *dev = interface->dev; @@ -546,7 +547,10 @@ struct net_device *mqnic_create_netdev(struct mqnic_if *interface, int index, in } SET_NETDEV_DEV(ndev, dev); - ndev->dev_port = dev_port; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 2, 0) + SET_NETDEV_DEVLINK_PORT(ndev, &port->dl_port); +#endif + ndev->dev_port = port->phys_index; // init private data priv = netdev_priv(ndev); @@ -556,10 +560,13 @@ struct net_device *mqnic_create_netdev(struct mqnic_if *interface, int index, in priv->ndev = ndev; priv->mdev = interface->mdev; + priv->dl_port = &port->dl_port; priv->interface = interface; priv->dev = dev; priv->index = index; + priv->port = port; priv->port_up = false; + priv->sched_block = sched_block; // associate interface resources priv->if_features = interface->if_features; @@ -578,28 +585,20 @@ struct net_device *mqnic_create_netdev(struct mqnic_if *interface, int index, in init_rwsem(&priv->rxq_table_sem); INIT_RADIX_TREE(&priv->rxq_table, GFP_KERNEL); - priv->sched_block_count = interface->sched_block_count; - for (k = 0; k < interface->sched_block_count; k++) - priv->sched_block[k] = interface->sched_block[k]; - - priv->port_count = interface->port_count; - for (k = 0; k < interface->port_count; k++) - priv->port[k] = interface->port[k]; - netif_set_real_num_tx_queues(ndev, priv->txq_count); netif_set_real_num_rx_queues(ndev, priv->rxq_count); // set MAC ndev->addr_len = ETH_ALEN; - if (dev_port >= mdev->mac_count) { + if (ndev->dev_port >= mdev->mac_count) { dev_warn(dev, "Exhausted permanent MAC addresses; using random MAC"); eth_hw_addr_random(ndev); } else { #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) - eth_hw_addr_set(ndev, mdev->mac_list[dev_port]); + eth_hw_addr_set(ndev, mdev->mac_list[ndev->dev_port]); #else - memcpy(ndev->dev_addr, mdev->mac_list[dev_port], ETH_ALEN); + memcpy(ndev->dev_addr, mdev->mac_list[ndev->dev_port], ETH_ALEN); #endif if (!is_valid_ether_addr(ndev->dev_addr)) { @@ -657,6 +656,10 @@ struct net_device *mqnic_create_netdev(struct mqnic_if *interface, int index, in goto fail; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0) + devlink_port_type_eth_set(&port->dl_port, ndev); +#endif + priv->registered = 1; return ndev; @@ -675,5 +678,9 @@ void mqnic_destroy_netdev(struct net_device *ndev) kfree(priv->rx_queue_map_indir_table); + #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0) + devlink_port_type_clear(priv->dl_port); + #endif + free_netdev(ndev); } diff --git a/modules/mqnic/mqnic_port.c b/modules/mqnic/mqnic_port.c index 1242b9a8e..721191995 100644 --- a/modules/mqnic/mqnic_port.c +++ b/modules/mqnic/mqnic_port.c @@ -6,9 +6,11 @@ #include "mqnic.h" struct mqnic_port *mqnic_create_port(struct mqnic_if *interface, int index, - struct mqnic_reg_block *port_rb) + int phys_index, struct mqnic_reg_block *port_rb) { struct device *dev = interface->dev; + struct devlink *devlink = priv_to_devlink(interface->mdev); + struct devlink_port_attrs attrs = {}; struct mqnic_port *port; struct mqnic_reg_block *rb; u32 offset; @@ -19,6 +21,16 @@ struct mqnic_port *mqnic_create_port(struct mqnic_if *interface, int index, if (!port) return ERR_PTR(-ENOMEM); + attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; + attrs.phys.port_number = phys_index; + devlink_port_attrs_set(&port->dl_port, &attrs); + + ret = devlink_port_register(devlink, &port->dl_port, phys_index); + if (ret) { + kfree(port); + return ERR_PTR(ret); + } + port->dev = dev; port->interface = interface; @@ -75,6 +87,8 @@ void mqnic_destroy_port(struct mqnic_port *port) if (port->rb_list) mqnic_free_reg_block_list(port->rb_list); + devlink_port_unregister(&port->dl_port); + kfree(port); }