aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGovindarajulu Varadarajan <_govind@gmx.com>2014-06-23 06:38:05 -0400
committerDavid S. Miller <davem@davemloft.net>2014-06-23 17:32:20 -0400
commit4cfe878537cec0e9c0f84b93cc6aa9526f6942b5 (patch)
treec3f002369ac3d8c478efb797561e9069f7c35f98
parent14747cd977195a8aae13d0b1ad021e33c8786afe (diff)
enic: do tx cleanup in napi poll
Till now enic had been doing tx clean in isr. Using napi infrastructure to move the tx clean up out of isr to softirq. Now, wq isr schedules napi poll. In enic_poll_msix_wq we clean up the tx queus. This is applicable only on MSIX. In INTx and MSI we use single napi to clean both rx & tx queues. Signed-off-by: Govindarajulu Varadarajan <_govind@gmx.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/cisco/enic/enic.h2
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c88
2 files changed, 54 insertions, 36 deletions
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index b9b9178e174e..c8aa9fb81d3c 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -178,7 +178,7 @@ struct enic {
178 unsigned int rq_count; 178 unsigned int rq_count;
179 u64 rq_truncated_pkts; 179 u64 rq_truncated_pkts;
180 u64 rq_bad_fcs; 180 u64 rq_bad_fcs;
181 struct napi_struct napi[ENIC_RQ_MAX]; 181 struct napi_struct napi[ENIC_RQ_MAX + ENIC_WQ_MAX];
182 182
183 /* interrupt resource cache line section */ 183 /* interrupt resource cache line section */
184 ____cacheline_aligned struct vnic_intr intr[ENIC_INTR_MAX]; 184 ____cacheline_aligned struct vnic_intr intr[ENIC_INTR_MAX];
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index d4918eef5050..9348febc0743 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -316,40 +316,15 @@ static irqreturn_t enic_isr_msi(int irq, void *data)
316 return IRQ_HANDLED; 316 return IRQ_HANDLED;
317} 317}
318 318
319static irqreturn_t enic_isr_msix_rq(int irq, void *data) 319static irqreturn_t enic_isr_msix(int irq, void *data)
320{ 320{
321 struct napi_struct *napi = data; 321 struct napi_struct *napi = data;
322 322
323 /* schedule NAPI polling for RQ cleanup */
324 napi_schedule(napi); 323 napi_schedule(napi);
325 324
326 return IRQ_HANDLED; 325 return IRQ_HANDLED;
327} 326}
328 327
329static irqreturn_t enic_isr_msix_wq(int irq, void *data)
330{
331 struct enic *enic = data;
332 unsigned int cq;
333 unsigned int intr;
334 unsigned int wq_work_to_do = -1; /* no limit */
335 unsigned int wq_work_done;
336 unsigned int wq_irq;
337
338 wq_irq = (u32)irq - enic->msix_entry[enic_msix_wq_intr(enic, 0)].vector;
339 cq = enic_cq_wq(enic, wq_irq);
340 intr = enic_msix_wq_intr(enic, wq_irq);
341
342 wq_work_done = vnic_cq_service(&enic->cq[cq],
343 wq_work_to_do, enic_wq_service, NULL);
344
345 vnic_intr_return_credits(&enic->intr[intr],
346 wq_work_done,
347 1 /* unmask intr */,
348 1 /* reset intr timer */);
349
350 return IRQ_HANDLED;
351}
352
353static irqreturn_t enic_isr_msix_err(int irq, void *data) 328static irqreturn_t enic_isr_msix_err(int irq, void *data)
354{ 329{
355 struct enic *enic = data; 330 struct enic *enic = data;
@@ -1274,7 +1249,36 @@ int enic_busy_poll(struct napi_struct *napi)
1274} 1249}
1275#endif /* CONFIG_NET_RX_BUSY_POLL */ 1250#endif /* CONFIG_NET_RX_BUSY_POLL */
1276 1251
1277static int enic_poll_msix(struct napi_struct *napi, int budget) 1252static int enic_poll_msix_wq(struct napi_struct *napi, int budget)
1253{
1254 struct net_device *netdev = napi->dev;
1255 struct enic *enic = netdev_priv(netdev);
1256 unsigned int wq_index = (napi - &enic->napi[0]) - enic->rq_count;
1257 struct vnic_wq *wq = &enic->wq[wq_index];
1258 unsigned int cq;
1259 unsigned int intr;
1260 unsigned int wq_work_to_do = -1; /* clean all desc possible */
1261 unsigned int wq_work_done;
1262 unsigned int wq_irq;
1263
1264 wq_irq = wq->index;
1265 cq = enic_cq_wq(enic, wq_irq);
1266 intr = enic_msix_wq_intr(enic, wq_irq);
1267 wq_work_done = vnic_cq_service(&enic->cq[cq], wq_work_to_do,
1268 enic_wq_service, NULL);
1269
1270 vnic_intr_return_credits(&enic->intr[intr], wq_work_done,
1271 0 /* don't unmask intr */,
1272 1 /* reset intr timer */);
1273 if (!wq_work_done) {
1274 napi_complete(napi);
1275 vnic_intr_unmask(&enic->intr[intr]);
1276 }
1277
1278 return 0;
1279}
1280
1281static int enic_poll_msix_rq(struct napi_struct *napi, int budget)
1278{ 1282{
1279 struct net_device *netdev = napi->dev; 1283 struct net_device *netdev = napi->dev;
1280 struct enic *enic = netdev_priv(netdev); 1284 struct enic *enic = netdev_priv(netdev);
@@ -1399,17 +1403,19 @@ static int enic_request_intr(struct enic *enic)
1399 snprintf(enic->msix[intr].devname, 1403 snprintf(enic->msix[intr].devname,
1400 sizeof(enic->msix[intr].devname), 1404 sizeof(enic->msix[intr].devname),
1401 "%.11s-rx-%d", netdev->name, i); 1405 "%.11s-rx-%d", netdev->name, i);
1402 enic->msix[intr].isr = enic_isr_msix_rq; 1406 enic->msix[intr].isr = enic_isr_msix;
1403 enic->msix[intr].devid = &enic->napi[i]; 1407 enic->msix[intr].devid = &enic->napi[i];
1404 } 1408 }
1405 1409
1406 for (i = 0; i < enic->wq_count; i++) { 1410 for (i = 0; i < enic->wq_count; i++) {
1411 int wq = enic_cq_wq(enic, i);
1412
1407 intr = enic_msix_wq_intr(enic, i); 1413 intr = enic_msix_wq_intr(enic, i);
1408 snprintf(enic->msix[intr].devname, 1414 snprintf(enic->msix[intr].devname,
1409 sizeof(enic->msix[intr].devname), 1415 sizeof(enic->msix[intr].devname),
1410 "%.11s-tx-%d", netdev->name, i); 1416 "%.11s-tx-%d", netdev->name, i);
1411 enic->msix[intr].isr = enic_isr_msix_wq; 1417 enic->msix[intr].isr = enic_isr_msix;
1412 enic->msix[intr].devid = enic; 1418 enic->msix[intr].devid = &enic->napi[wq];
1413 } 1419 }
1414 1420
1415 intr = enic_msix_err_intr(enic); 1421 intr = enic_msix_err_intr(enic);
@@ -1585,7 +1591,9 @@ static int enic_open(struct net_device *netdev)
1585 enic_busy_poll_init_lock(&enic->rq[i]); 1591 enic_busy_poll_init_lock(&enic->rq[i]);
1586 napi_enable(&enic->napi[i]); 1592 napi_enable(&enic->napi[i]);
1587 } 1593 }
1588 1594 if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
1595 for (i = 0; i < enic->wq_count; i++)
1596 napi_enable(&enic->napi[enic_cq_wq(enic, i)]);
1589 enic_dev_enable(enic); 1597 enic_dev_enable(enic);
1590 1598
1591 for (i = 0; i < enic->intr_count; i++) 1599 for (i = 0; i < enic->intr_count; i++)
@@ -1633,6 +1641,9 @@ static int enic_stop(struct net_device *netdev)
1633 1641
1634 netif_carrier_off(netdev); 1642 netif_carrier_off(netdev);
1635 netif_tx_disable(netdev); 1643 netif_tx_disable(netdev);
1644 if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
1645 for (i = 0; i < enic->wq_count; i++)
1646 napi_disable(&enic->napi[enic_cq_wq(enic, i)]);
1636 1647
1637 if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic)) 1648 if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic))
1638 enic_dev_del_station_addr(enic); 1649 enic_dev_del_station_addr(enic);
@@ -1752,13 +1763,14 @@ static void enic_poll_controller(struct net_device *netdev)
1752 case VNIC_DEV_INTR_MODE_MSIX: 1763 case VNIC_DEV_INTR_MODE_MSIX:
1753 for (i = 0; i < enic->rq_count; i++) { 1764 for (i = 0; i < enic->rq_count; i++) {
1754 intr = enic_msix_rq_intr(enic, i); 1765 intr = enic_msix_rq_intr(enic, i);
1755 enic_isr_msix_rq(enic->msix_entry[intr].vector, 1766 enic_isr_msix(enic->msix_entry[intr].vector,
1756 &enic->napi[i]); 1767 &enic->napi[i]);
1757 } 1768 }
1758 1769
1759 for (i = 0; i < enic->wq_count; i++) { 1770 for (i = 0; i < enic->wq_count; i++) {
1760 intr = enic_msix_wq_intr(enic, i); 1771 intr = enic_msix_wq_intr(enic, i);
1761 enic_isr_msix_wq(enic->msix_entry[intr].vector, enic); 1772 enic_isr_msix(enic->msix_entry[intr].vector,
1773 &enic->napi[enic_cq_wq(enic, i)]);
1762 } 1774 }
1763 1775
1764 break; 1776 break;
@@ -2159,6 +2171,9 @@ static void enic_dev_deinit(struct enic *enic)
2159 napi_hash_del(&enic->napi[i]); 2171 napi_hash_del(&enic->napi[i]);
2160 netif_napi_del(&enic->napi[i]); 2172 netif_napi_del(&enic->napi[i]);
2161 } 2173 }
2174 if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
2175 for (i = 0; i < enic->wq_count; i++)
2176 netif_napi_del(&enic->napi[enic_cq_wq(enic, i)]);
2162 2177
2163 enic_free_vnic_resources(enic); 2178 enic_free_vnic_resources(enic);
2164 enic_clear_intr_mode(enic); 2179 enic_clear_intr_mode(enic);
@@ -2229,9 +2244,12 @@ static int enic_dev_init(struct enic *enic)
2229 case VNIC_DEV_INTR_MODE_MSIX: 2244 case VNIC_DEV_INTR_MODE_MSIX:
2230 for (i = 0; i < enic->rq_count; i++) { 2245 for (i = 0; i < enic->rq_count; i++) {
2231 netif_napi_add(netdev, &enic->napi[i], 2246 netif_napi_add(netdev, &enic->napi[i],
2232 enic_poll_msix, 64); 2247 enic_poll_msix_rq, NAPI_POLL_WEIGHT);
2233 napi_hash_add(&enic->napi[i]); 2248 napi_hash_add(&enic->napi[i]);
2234 } 2249 }
2250 for (i = 0; i < enic->wq_count; i++)
2251 netif_napi_add(netdev, &enic->napi[enic_cq_wq(enic, i)],
2252 enic_poll_msix_wq, NAPI_POLL_WEIGHT);
2235 break; 2253 break;
2236 } 2254 }
2237 2255