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:
parent
db1bb30745
commit
0d2e794b74
@ -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];
|
||||
|
||||
|
@ -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)},
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user