aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen/netxen_nic_main.c
diff options
context:
space:
mode:
authorDhananjay Phadke <dhananjay@netxen.com>2008-03-17 22:59:49 -0400
committerJeff Garzik <jeff@garzik.org>2008-03-25 23:16:16 -0400
commit05aaa02d799e8e9548d57ac92fcb05e783027341 (patch)
treebecfc839727f798364c13549e332de0830d7676f /drivers/net/netxen/netxen_nic_main.c
parent443be7960be77f3345b44491c700ae4471b0fe57 (diff)
netxen: napi and irq cleanup
o separate and simpler irq handler for msi interrupts, avoids few checks than legacy mode. o avoid redudant tx_has_work() and rx_has_work() checks in interrupt and napi, which can uncork irq based on racy (lockless) access to tx and rx ring indices. If we get interrupt, there's sufficient reason to schedule napi. o replenish rx ring more often, remove self-imposed threshold rcv_free that prevents posting rx desc to card. This improves performance in low memory. Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> Tested-by: Vernon Mauery <mauery@us.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/netxen/netxen_nic_main.c')
-rw-r--r--drivers/net/netxen/netxen_nic_main.c113
1 files changed, 39 insertions, 74 deletions
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index cd665da85c7..95955204ef5 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -63,12 +63,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *);
63static void netxen_tx_timeout(struct net_device *netdev); 63static void netxen_tx_timeout(struct net_device *netdev);
64static void netxen_tx_timeout_task(struct work_struct *work); 64static void netxen_tx_timeout_task(struct work_struct *work);
65static void netxen_watchdog(unsigned long); 65static void netxen_watchdog(unsigned long);
66static int netxen_handle_int(struct netxen_adapter *, struct net_device *);
67static int netxen_nic_poll(struct napi_struct *napi, int budget); 66static int netxen_nic_poll(struct napi_struct *napi, int budget);
68#ifdef CONFIG_NET_POLL_CONTROLLER 67#ifdef CONFIG_NET_POLL_CONTROLLER
69static void netxen_nic_poll_controller(struct net_device *netdev); 68static void netxen_nic_poll_controller(struct net_device *netdev);
70#endif 69#endif
71static irqreturn_t netxen_intr(int irq, void *data); 70static irqreturn_t netxen_intr(int irq, void *data);
71static irqreturn_t netxen_msi_intr(int irq, void *data);
72 72
73int physical_port[] = {0, 1, 2, 3}; 73int physical_port[] = {0, 1, 2, 3};
74 74
@@ -405,7 +405,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
405 netdev->set_mac_address = netxen_nic_set_mac; 405 netdev->set_mac_address = netxen_nic_set_mac;
406 netdev->change_mtu = netxen_nic_change_mtu; 406 netdev->change_mtu = netxen_nic_change_mtu;
407 netdev->tx_timeout = netxen_tx_timeout; 407 netdev->tx_timeout = netxen_tx_timeout;
408 netdev->watchdog_timeo = HZ; 408 netdev->watchdog_timeo = 2*HZ;
409 409
410 netxen_nic_change_mtu(netdev, netdev->mtu); 410 netxen_nic_change_mtu(netdev, netdev->mtu);
411 411
@@ -823,6 +823,8 @@ static int netxen_nic_open(struct net_device *netdev)
823 struct netxen_adapter *adapter = (struct netxen_adapter *)netdev->priv; 823 struct netxen_adapter *adapter = (struct netxen_adapter *)netdev->priv;
824 int err = 0; 824 int err = 0;
825 int ctx, ring; 825 int ctx, ring;
826 irq_handler_t handler;
827 unsigned long flags = IRQF_SAMPLE_RANDOM;
826 828
827 if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) { 829 if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) {
828 err = netxen_init_firmware(adapter); 830 err = netxen_init_firmware(adapter);
@@ -846,9 +848,14 @@ static int netxen_nic_open(struct net_device *netdev)
846 netxen_post_rx_buffers(adapter, ctx, ring); 848 netxen_post_rx_buffers(adapter, ctx, ring);
847 } 849 }
848 adapter->irq = adapter->ahw.pdev->irq; 850 adapter->irq = adapter->ahw.pdev->irq;
849 err = request_irq(adapter->ahw.pdev->irq, netxen_intr, 851 if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
850 IRQF_SHARED|IRQF_SAMPLE_RANDOM, netdev->name, 852 handler = netxen_msi_intr;
851 adapter); 853 else {
854 flags |= IRQF_SHARED;
855 handler = netxen_intr;
856 }
857 err = request_irq(adapter->irq, handler,
858 flags, netdev->name, adapter);
852 if (err) { 859 if (err) {
853 printk(KERN_ERR "request_irq failed with: %d\n", err); 860 printk(KERN_ERR "request_irq failed with: %d\n", err);
854 netxen_free_hw_resources(adapter); 861 netxen_free_hw_resources(adapter);
@@ -857,21 +864,12 @@ static int netxen_nic_open(struct net_device *netdev)
857 864
858 adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; 865 adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
859 } 866 }
860 if (!adapter->driver_mismatch)
861 mod_timer(&adapter->watchdog_timer, jiffies);
862
863 napi_enable(&adapter->napi);
864
865 netxen_nic_enable_int(adapter);
866
867 /* Done here again so that even if phantom sw overwrote it, 867 /* Done here again so that even if phantom sw overwrote it,
868 * we set it */ 868 * we set it */
869 if (adapter->init_port 869 if (adapter->init_port
870 && adapter->init_port(adapter, adapter->portnum) != 0) { 870 && adapter->init_port(adapter, adapter->portnum) != 0) {
871 del_timer_sync(&adapter->watchdog_timer);
872 printk(KERN_ERR "%s: Failed to initialize port %d\n", 871 printk(KERN_ERR "%s: Failed to initialize port %d\n",
873 netxen_nic_driver_name, adapter->portnum); 872 netxen_nic_driver_name, adapter->portnum);
874 napi_disable(&adapter->napi);
875 return -EIO; 873 return -EIO;
876 } 874 }
877 if (adapter->macaddr_set) 875 if (adapter->macaddr_set)
@@ -884,6 +882,12 @@ static int netxen_nic_open(struct net_device *netdev)
884 adapter->set_mtu(adapter, netdev->mtu); 882 adapter->set_mtu(adapter, netdev->mtu);
885 883
886 if (!adapter->driver_mismatch) 884 if (!adapter->driver_mismatch)
885 mod_timer(&adapter->watchdog_timer, jiffies);
886
887 napi_enable(&adapter->napi);
888 netxen_nic_enable_int(adapter);
889
890 if (!adapter->driver_mismatch)
887 netif_start_queue(netdev); 891 netif_start_queue(netdev);
888 892
889 return 0; 893 return 0;
@@ -1196,81 +1200,50 @@ static void netxen_tx_timeout_task(struct work_struct *work)
1196 netif_wake_queue(adapter->netdev); 1200 netif_wake_queue(adapter->netdev);
1197} 1201}
1198 1202
1199static int 1203static inline void
1200netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) 1204netxen_handle_int(struct netxen_adapter *adapter)
1201{ 1205{
1202 u32 ret = 0;
1203
1204 DPRINTK(INFO, "Entered handle ISR\n");
1205 adapter->stats.ints++;
1206
1207 netxen_nic_disable_int(adapter); 1206 netxen_nic_disable_int(adapter);
1208 1207 napi_schedule(&adapter->napi);
1209 if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) {
1210 if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
1211 /*
1212 * Interrupts are already disabled.
1213 */
1214 __netif_rx_schedule(netdev, &adapter->napi);
1215 } else {
1216 static unsigned int intcount = 0;
1217 if ((++intcount & 0xfff) == 0xfff)
1218 DPRINTK(KERN_ERR
1219 "%s: %s interrupt %d while in poll\n",
1220 netxen_nic_driver_name, netdev->name,
1221 intcount);
1222 }
1223 ret = 1;
1224 }
1225
1226 if (ret == 0) {
1227 netxen_nic_enable_int(adapter);
1228 }
1229
1230 return ret;
1231} 1208}
1232 1209
1233/*
1234 * netxen_intr - Interrupt Handler
1235 * @irq: interrupt number
1236 * data points to adapter stucture (which may be handling more than 1 port
1237 */
1238irqreturn_t netxen_intr(int irq, void *data) 1210irqreturn_t netxen_intr(int irq, void *data)
1239{ 1211{
1240 struct netxen_adapter *adapter = data; 1212 struct netxen_adapter *adapter = data;
1241 struct net_device *netdev = adapter->netdev;
1242 u32 our_int = 0; 1213 u32 our_int = 0;
1243 1214
1244 if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { 1215 our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
1245 our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); 1216 /* not our interrupt */
1246 /* not our interrupt */ 1217 if ((our_int & (0x80 << adapter->portnum)) == 0)
1247 if ((our_int & (0x80 << adapter->portnum)) == 0) 1218 return IRQ_NONE;
1248 return IRQ_NONE;
1249 }
1250 1219
1251 if (adapter->intr_scheme == INTR_SCHEME_PERPORT) { 1220 if (adapter->intr_scheme == INTR_SCHEME_PERPORT) {
1252 /* claim interrupt */ 1221 /* claim interrupt */
1253 if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { 1222 writel(our_int & ~((u32)(0x80 << adapter->portnum)),
1254 writel(our_int & ~((u32)(0x80 << adapter->portnum)),
1255 NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); 1223 NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
1256 }
1257 } 1224 }
1258 1225
1259 if (netif_running(netdev)) 1226 netxen_handle_int(adapter);
1260 netxen_handle_int(adapter, netdev);
1261 1227
1262 return IRQ_HANDLED; 1228 return IRQ_HANDLED;
1263} 1229}
1264 1230
1231irqreturn_t netxen_msi_intr(int irq, void *data)
1232{
1233 struct netxen_adapter *adapter = data;
1234
1235 netxen_handle_int(adapter);
1236 return IRQ_HANDLED;
1237}
1238
1265static int netxen_nic_poll(struct napi_struct *napi, int budget) 1239static int netxen_nic_poll(struct napi_struct *napi, int budget)
1266{ 1240{
1267 struct netxen_adapter *adapter = container_of(napi, struct netxen_adapter, napi); 1241 struct netxen_adapter *adapter = container_of(napi, struct netxen_adapter, napi);
1268 struct net_device *netdev = adapter->netdev; 1242 int tx_complete;
1269 int done = 1;
1270 int ctx; 1243 int ctx;
1271 int work_done; 1244 int work_done;
1272 1245
1273 DPRINTK(INFO, "polling for %d descriptors\n", *budget); 1246 tx_complete = netxen_process_cmd_ring(adapter);
1274 1247
1275 work_done = 0; 1248 work_done = 0;
1276 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { 1249 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
@@ -1290,16 +1263,8 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget)
1290 budget / MAX_RCV_CTX); 1263 budget / MAX_RCV_CTX);
1291 } 1264 }
1292 1265
1293 if (work_done >= budget) 1266 if ((work_done < budget) && tx_complete) {
1294 done = 0; 1267 netif_rx_complete(adapter->netdev, &adapter->napi);
1295
1296 if (netxen_process_cmd_ring((unsigned long)adapter) == 0)
1297 done = 0;
1298
1299 DPRINTK(INFO, "new work_done: %d work_to_do: %d\n",
1300 work_done, work_to_do);
1301 if (done) {
1302 netif_rx_complete(netdev, napi);
1303 netxen_nic_enable_int(adapter); 1268 netxen_nic_enable_int(adapter);
1304 } 1269 }
1305 1270