1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00

modules/mqnic: Add link status monitoring

This solution is based on the assumption that, if there are multiple
(mqnic-)ports per (mqnic-)interface, the single netdev, which is currently
associated with one (mqnic-)interface, is assumed to be up, when all ports' TX
and RX status bits are asserted. As soon as one of these bits is deasserted for
any of the involved ports the netdev is assumed to be down.

Module parameter "link_status_poll" specifies the polling interval in
milliseconds. Setting it to 0, disables any form of monitoring. By default we
check once per second, which is a totally arbitrary choice - no special
reasoning.

Signed-off-by: Joachim Foerster <joachim.foerster@missinglinkelectronics.com>
This commit is contained in:
Joachim Foerster 2022-05-13 19:13:41 +02:00 committed by Alex Forencich
parent db1bb30745
commit 0d2e794b74
3 changed files with 62 additions and 2 deletions

View File

@ -49,6 +49,7 @@
#include <linux/etherdevice.h>
#include <linux/net_tstamp.h>
#include <linux/ptp_clock_kernel.h>
#include <linux/timer.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
@ -66,10 +67,15 @@
#define MQNIC_PROP_MODULE_EEPROM "module-eeproms"
#endif
// default interval to poll port TX/RX status, in ms
#define MQNIC_LINK_STATUS_POLL_MS 1000
extern unsigned int mqnic_num_ev_queue_entries;
extern unsigned int mqnic_num_tx_queue_entries;
extern unsigned int mqnic_num_rx_queue_entries;
extern unsigned int mqnic_link_status_poll;
struct mqnic_dev;
struct mqnic_if;
@ -456,6 +462,9 @@ struct mqnic_priv {
u32 if_features;
unsigned int link_status;
struct timer_list link_status_timer;
u32 event_queue_count;
struct mqnic_eq_ring *event_ring[MQNIC_MAX_EVENT_RINGS];

View File

@ -59,6 +59,13 @@ MODULE_PARM_DESC(num_tx_queue_entries, "number of entries to allocate per transm
module_param_named(num_rx_queue_entries, mqnic_num_rx_queue_entries, uint, 0444);
MODULE_PARM_DESC(num_rx_queue_entries, "number of entries to allocate per receive queue (default: 1024)");
unsigned int mqnic_link_status_poll = MQNIC_LINK_STATUS_POLL_MS;
module_param_named(link_status_poll, mqnic_link_status_poll, uint, 0444);
MODULE_PARM_DESC(link_status_poll,
"link status polling interval, in ms (default: 1000; 0 to turn off)");
#ifdef CONFIG_PCI
static const struct pci_device_id mqnic_pci_id_table[] = {
{PCI_DEVICE(0x1234, 0x1001)},

View File

@ -99,8 +99,11 @@ static int mqnic_start_port(struct net_device *ndev)
netif_tx_start_all_queues(ndev);
netif_device_attach(ndev);
//netif_carrier_off(ndev);
netif_carrier_on(ndev); // TODO link status monitoring
if (mqnic_link_status_poll)
mod_timer(&priv->link_status_timer,
jiffies + msecs_to_jiffies(mqnic_link_status_poll));
else
netif_carrier_on(ndev);
return 0;
}
@ -114,6 +117,9 @@ static int mqnic_stop_port(struct net_device *ndev)
dev_info(mdev->dev, "%s on interface %d netdev %d", __func__,
priv->interface->index, priv->index);
if (mqnic_link_status_poll)
del_timer_sync(&priv->link_status_timer);
netif_tx_lock_bh(ndev);
// if (detach)
// netif_device_detach(ndev);
@ -359,6 +365,40 @@ static const struct net_device_ops mqnic_netdev_ops = {
#endif
};
static void mqnic_link_status_timeout(struct timer_list *timer)
{
struct mqnic_priv *priv = from_timer(priv, timer, link_status_timer);
struct mqnic_if *interface = priv->interface;
int k;
unsigned int up;
// "combine" all TX/RX status signals of all ports of this interface
for (k = 0, up = 0; k < interface->port_count; k++) {
if (!(mqnic_port_get_tx_status(interface->port[k]) & 0x1))
continue;
if (!(mqnic_port_get_rx_status(interface->port[k]) & 0x1))
continue;
up++;
}
if (up < interface->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);
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);
priv->link_status = !priv->link_status;
}
}
mod_timer(&priv->link_status_timer, jiffies + msecs_to_jiffies(mqnic_link_status_poll));
}
int mqnic_create_netdev(struct mqnic_if *interface, struct net_device **ndev_ptr,
int index, int dev_port)
{
@ -502,6 +542,10 @@ int mqnic_create_netdev(struct mqnic_if *interface, struct net_device **ndev_ptr
ndev->max_mtu = min(interface->max_tx_mtu, interface->max_rx_mtu) - ETH_HLEN;
netif_carrier_off(ndev);
if (mqnic_link_status_poll) {
priv->link_status = false;
timer_setup(&priv->link_status_timer, mqnic_link_status_timeout, 0);
}
ret = register_netdev(ndev);
if (ret) {