mirror of
https://github.com/corundum/corundum.git
synced 2025-01-16 08:12:53 +08:00
modules/mqnic: Register ports with devlink
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
parent
a9800099e3
commit
54d0165f68
@ -20,6 +20,7 @@
|
||||
#include <linux/net_tstamp.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/timer.h>
|
||||
#include <net/devlink.h>
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
@ -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
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "mqnic.h"
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <net/devlink.h>
|
||||
|
||||
static int mqnic_devlink_info_get(struct devlink *devlink,
|
||||
struct devlink_info_req *req, struct netlink_ext_ack *extack)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <net/devlink.h>
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)
|
||||
#include <linux/pci-aspm.h>
|
||||
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user