summaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen/netxen_nic_main.c
diff options
context:
space:
mode:
authorDhananjay Phadke2009-04-08 00:50:42 +0200
committerDavid S. Miller2009-04-09 00:58:27 +0200
commit3bf26ce3f4cc3c9e0d0478b4016c6113a16faaf1 (patch)
tree8478804493b6e749a6e61870c8c3b5b9549469ad /drivers/net/netxen/netxen_nic_main.c
parentnetxen: defer firmware handshake (diff)
downloadkernel-qcow2-linux-3bf26ce3f4cc3c9e0d0478b4016c6113a16faaf1.tar.gz
kernel-qcow2-linux-3bf26ce3f4cc3c9e0d0478b4016c6113a16faaf1.tar.xz
kernel-qcow2-linux-3bf26ce3f4cc3c9e0d0478b4016c6113a16faaf1.zip
netxen: async link event handling
Add support for asynchronous events from firmware, received over one of the rx rings. Add support for event based phy interrupts, enhanced links status reporting from firmware. Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/netxen/netxen_nic_main.c')
-rw-r--r--drivers/net/netxen/netxen_nic_main.c55
1 files changed, 34 insertions, 21 deletions
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 665fce561d4a..bd93296be4dd 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -787,6 +787,9 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
if (adapter->max_sds_rings > 1)
netxen_config_rss(adapter, 1);
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ netxen_linkevent_request(adapter, 1);
+
return 0;
}
@@ -1493,26 +1496,9 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter)
return rv;
}
-static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
+void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup)
{
struct net_device *netdev = adapter->netdev;
- u32 val, port, linkup;
-
- port = adapter->physical_port;
-
- if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
- val = adapter->pci_read_normalize(adapter, CRB_XG_STATE_P3);
- val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
- linkup = (val == XG_LINK_UP_P3);
- } else {
- val = adapter->pci_read_normalize(adapter, CRB_XG_STATE);
- if (adapter->ahw.port_type == NETXEN_NIC_GBE)
- linkup = (val >> port) & 1;
- else {
- val = (val >> port*8) & 0xff;
- linkup = (val == XG_LINK_UP);
- }
- }
if (adapter->ahw.linkup && !linkup) {
printk(KERN_INFO "%s: %s NIC Link is down\n",
@@ -1523,7 +1509,9 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
netif_stop_queue(netdev);
}
- netxen_nic_set_link_parameters(adapter);
+ if (!adapter->has_link_events)
+ netxen_nic_set_link_parameters(adapter);
+
} else if (!adapter->ahw.linkup && linkup) {
printk(KERN_INFO "%s: %s NIC Link is up\n",
netxen_nic_driver_name, netdev->name);
@@ -1533,10 +1521,34 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
netif_wake_queue(netdev);
}
- netxen_nic_set_link_parameters(adapter);
+ if (!adapter->has_link_events)
+ netxen_nic_set_link_parameters(adapter);
}
}
+static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
+{
+ u32 val, port, linkup;
+
+ port = adapter->physical_port;
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ val = adapter->pci_read_normalize(adapter, CRB_XG_STATE_P3);
+ val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
+ linkup = (val == XG_LINK_UP_P3);
+ } else {
+ val = adapter->pci_read_normalize(adapter, CRB_XG_STATE);
+ if (adapter->ahw.port_type == NETXEN_NIC_GBE)
+ linkup = (val >> port) & 1;
+ else {
+ val = (val >> port*8) & 0xff;
+ linkup = (val == XG_LINK_UP);
+ }
+ }
+
+ netxen_advert_link_change(adapter, linkup);
+}
+
static void netxen_watchdog(unsigned long v)
{
struct netxen_adapter *adapter = (struct netxen_adapter *)v;
@@ -1552,7 +1564,8 @@ void netxen_watchdog_task(struct work_struct *work)
if ((adapter->portnum == 0) && netxen_nic_check_temp(adapter))
return;
- netxen_nic_handle_phy_intr(adapter);
+ if (!adapter->has_link_events)
+ netxen_nic_handle_phy_intr(adapter);
if (netif_running(adapter->netdev))
mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);