aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/myri10ge
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-10-03 19:41:36 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:47:45 -0400
commitbea3348eef27e6044b6161fd04c3152215f96411 (patch)
treef0990b263e5ce42505d290a4c346fe990bcd4c33 /drivers/net/myri10ge
parentdde4e47e8fe333a5649a3fa0e7db1fa7c08d6158 (diff)
[NET]: Make NAPI polling independent of struct net_device objects.
Several devices have multiple independant RX queues per net device, and some have a single interrupt doorbell for several queues. In either case, it's easier to support layouts like that if the structure representing the poll is independant from the net device itself. The signature of the ->poll() call back goes from: int foo_poll(struct net_device *dev, int *budget) to int foo_poll(struct napi_struct *napi, int budget) The caller is returned the number of RX packets processed (or the number of "NAPI credits" consumed if you want to get abstract). The callee no longer messes around bumping dev->quota, *budget, etc. because that is all handled in the caller upon return. The napi_struct is to be embedded in the device driver private data structures. Furthermore, it is the driver's responsibility to disable all NAPI instances in it's ->stop() device close handler. Since the napi_struct is privatized into the driver's private data structures, only the driver knows how to get at all of the napi_struct instances it may have per-device. With lots of help and suggestions from Rusty Russell, Roland Dreier, Michael Chan, Jeff Garzik, and Jamal Hadi Salim. Bug fixes from Thomas Graf, Roland Dreier, Peter Zijlstra, Joseph Fannin, Scott Wood, Hans J. Koch, and Michael Chan. [ Ported to current tree and all drivers converted. Integrated Stephen's follow-on kerneldoc additions, and restored poll_list handling to the old style to fix mutual exclusion issues. -DaveM ] Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/myri10ge')
-rw-r--r--drivers/net/myri10ge/myri10ge.c40
1 files changed, 17 insertions, 23 deletions
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 556962f9612d..a30146ea51f0 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -163,6 +163,7 @@ struct myri10ge_priv {
163 int small_bytes; 163 int small_bytes;
164 int big_bytes; 164 int big_bytes;
165 struct net_device *dev; 165 struct net_device *dev;
166 struct napi_struct napi;
166 struct net_device_stats stats; 167 struct net_device_stats stats;
167 u8 __iomem *sram; 168 u8 __iomem *sram;
168 int sram_size; 169 int sram_size;
@@ -1100,7 +1101,7 @@ static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index)
1100 } 1101 }
1101} 1102}
1102 1103
1103static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit) 1104static inline int myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int budget)
1104{ 1105{
1105 struct myri10ge_rx_done *rx_done = &mgp->rx_done; 1106 struct myri10ge_rx_done *rx_done = &mgp->rx_done;
1106 unsigned long rx_bytes = 0; 1107 unsigned long rx_bytes = 0;
@@ -1109,10 +1110,11 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit)
1109 1110
1110 int idx = rx_done->idx; 1111 int idx = rx_done->idx;
1111 int cnt = rx_done->cnt; 1112 int cnt = rx_done->cnt;
1113 int work_done = 0;
1112 u16 length; 1114 u16 length;
1113 __wsum checksum; 1115 __wsum checksum;
1114 1116
1115 while (rx_done->entry[idx].length != 0 && *limit != 0) { 1117 while (rx_done->entry[idx].length != 0 && work_done++ < budget) {
1116 length = ntohs(rx_done->entry[idx].length); 1118 length = ntohs(rx_done->entry[idx].length);
1117 rx_done->entry[idx].length = 0; 1119 rx_done->entry[idx].length = 0;
1118 checksum = csum_unfold(rx_done->entry[idx].checksum); 1120 checksum = csum_unfold(rx_done->entry[idx].checksum);
@@ -1128,10 +1130,6 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit)
1128 rx_bytes += rx_ok * (unsigned long)length; 1130 rx_bytes += rx_ok * (unsigned long)length;
1129 cnt++; 1131 cnt++;
1130 idx = cnt & (myri10ge_max_intr_slots - 1); 1132 idx = cnt & (myri10ge_max_intr_slots - 1);
1131
1132 /* limit potential for livelock by only handling a
1133 * limited number of frames. */
1134 (*limit)--;
1135 } 1133 }
1136 rx_done->idx = idx; 1134 rx_done->idx = idx;
1137 rx_done->cnt = cnt; 1135 rx_done->cnt = cnt;
@@ -1145,6 +1143,7 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit)
1145 if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt < myri10ge_fill_thresh) 1143 if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt < myri10ge_fill_thresh)
1146 myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0); 1144 myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0);
1147 1145
1146 return work_done;
1148} 1147}
1149 1148
1150static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) 1149static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
@@ -1189,26 +1188,21 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
1189 } 1188 }
1190} 1189}
1191 1190
1192static int myri10ge_poll(struct net_device *netdev, int *budget) 1191static int myri10ge_poll(struct napi_struct *napi, int budget)
1193{ 1192{
1194 struct myri10ge_priv *mgp = netdev_priv(netdev); 1193 struct myri10ge_priv *mgp = container_of(napi, struct myri10ge_priv, napi);
1194 struct net_device *netdev = mgp->dev;
1195 struct myri10ge_rx_done *rx_done = &mgp->rx_done; 1195 struct myri10ge_rx_done *rx_done = &mgp->rx_done;
1196 int limit, orig_limit, work_done; 1196 int work_done;
1197 1197
1198 /* process as many rx events as NAPI will allow */ 1198 /* process as many rx events as NAPI will allow */
1199 limit = min(*budget, netdev->quota); 1199 work_done = myri10ge_clean_rx_done(mgp, budget);
1200 orig_limit = limit;
1201 myri10ge_clean_rx_done(mgp, &limit);
1202 work_done = orig_limit - limit;
1203 *budget -= work_done;
1204 netdev->quota -= work_done;
1205 1200
1206 if (rx_done->entry[rx_done->idx].length == 0 || !netif_running(netdev)) { 1201 if (rx_done->entry[rx_done->idx].length == 0 || !netif_running(netdev)) {
1207 netif_rx_complete(netdev); 1202 netif_rx_complete(netdev, napi);
1208 put_be32(htonl(3), mgp->irq_claim); 1203 put_be32(htonl(3), mgp->irq_claim);
1209 return 0;
1210 } 1204 }
1211 return 1; 1205 return work_done;
1212} 1206}
1213 1207
1214static irqreturn_t myri10ge_intr(int irq, void *arg) 1208static irqreturn_t myri10ge_intr(int irq, void *arg)
@@ -1226,7 +1220,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
1226 /* low bit indicates receives are present, so schedule 1220 /* low bit indicates receives are present, so schedule
1227 * napi poll handler */ 1221 * napi poll handler */
1228 if (stats->valid & 1) 1222 if (stats->valid & 1)
1229 netif_rx_schedule(mgp->dev); 1223 netif_rx_schedule(mgp->dev, &mgp->napi);
1230 1224
1231 if (!mgp->msi_enabled) { 1225 if (!mgp->msi_enabled) {
1232 put_be32(0, mgp->irq_deassert); 1226 put_be32(0, mgp->irq_deassert);
@@ -1853,7 +1847,7 @@ static int myri10ge_open(struct net_device *dev)
1853 mgp->link_state = htonl(~0U); 1847 mgp->link_state = htonl(~0U);
1854 mgp->rdma_tags_available = 15; 1848 mgp->rdma_tags_available = 15;
1855 1849
1856 netif_poll_enable(mgp->dev); /* must happen prior to any irq */ 1850 napi_enable(&mgp->napi); /* must happen prior to any irq */
1857 1851
1858 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd, 0); 1852 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd, 0);
1859 if (status) { 1853 if (status) {
@@ -1897,7 +1891,7 @@ static int myri10ge_close(struct net_device *dev)
1897 1891
1898 del_timer_sync(&mgp->watchdog_timer); 1892 del_timer_sync(&mgp->watchdog_timer);
1899 mgp->running = MYRI10GE_ETH_STOPPING; 1893 mgp->running = MYRI10GE_ETH_STOPPING;
1900 netif_poll_disable(mgp->dev); 1894 napi_disable(&mgp->napi);
1901 netif_carrier_off(dev); 1895 netif_carrier_off(dev);
1902 netif_stop_queue(dev); 1896 netif_stop_queue(dev);
1903 old_down_cnt = mgp->down_cnt; 1897 old_down_cnt = mgp->down_cnt;
@@ -2857,6 +2851,8 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2857 mgp = netdev_priv(netdev); 2851 mgp = netdev_priv(netdev);
2858 memset(mgp, 0, sizeof(*mgp)); 2852 memset(mgp, 0, sizeof(*mgp));
2859 mgp->dev = netdev; 2853 mgp->dev = netdev;
2854 netif_napi_add(netdev, &mgp->napi,
2855 myri10ge_poll, myri10ge_napi_weight);
2860 mgp->pdev = pdev; 2856 mgp->pdev = pdev;
2861 mgp->csum_flag = MXGEFW_FLAGS_CKSUM; 2857 mgp->csum_flag = MXGEFW_FLAGS_CKSUM;
2862 mgp->pause = myri10ge_flow_control; 2858 mgp->pause = myri10ge_flow_control;
@@ -2981,8 +2977,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2981 netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO; 2977 netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO;
2982 if (dac_enabled) 2978 if (dac_enabled)
2983 netdev->features |= NETIF_F_HIGHDMA; 2979 netdev->features |= NETIF_F_HIGHDMA;
2984 netdev->poll = myri10ge_poll;
2985 netdev->weight = myri10ge_napi_weight;
2986 2980
2987 /* make sure we can get an irq, and that MSI can be 2981 /* make sure we can get an irq, and that MSI can be
2988 * setup (if available). Also ensure netdev->irq 2982 * setup (if available). Also ensure netdev->irq