enic: do tx cleanup in napi poll
[cascardo/linux.git] / drivers / net / ethernet / cisco / enic / enic_main.c
index d4918ee..9348feb 100644 (file)
@@ -316,40 +316,15 @@ static irqreturn_t enic_isr_msi(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static irqreturn_t enic_isr_msix_rq(int irq, void *data)
+static irqreturn_t enic_isr_msix(int irq, void *data)
 {
        struct napi_struct *napi = data;
 
-       /* schedule NAPI polling for RQ cleanup */
        napi_schedule(napi);
 
        return IRQ_HANDLED;
 }
 
-static irqreturn_t enic_isr_msix_wq(int irq, void *data)
-{
-       struct enic *enic = data;
-       unsigned int cq;
-       unsigned int intr;
-       unsigned int wq_work_to_do = -1; /* no limit */
-       unsigned int wq_work_done;
-       unsigned int wq_irq;
-
-       wq_irq = (u32)irq - enic->msix_entry[enic_msix_wq_intr(enic, 0)].vector;
-       cq = enic_cq_wq(enic, wq_irq);
-       intr = enic_msix_wq_intr(enic, wq_irq);
-
-       wq_work_done = vnic_cq_service(&enic->cq[cq],
-               wq_work_to_do, enic_wq_service, NULL);
-
-       vnic_intr_return_credits(&enic->intr[intr],
-               wq_work_done,
-               1 /* unmask intr */,
-               1 /* reset intr timer */);
-
-       return IRQ_HANDLED;
-}
-
 static irqreturn_t enic_isr_msix_err(int irq, void *data)
 {
        struct enic *enic = data;
@@ -1274,7 +1249,36 @@ int enic_busy_poll(struct napi_struct *napi)
 }
 #endif /* CONFIG_NET_RX_BUSY_POLL */
 
-static int enic_poll_msix(struct napi_struct *napi, int budget)
+static int enic_poll_msix_wq(struct napi_struct *napi, int budget)
+{
+       struct net_device *netdev = napi->dev;
+       struct enic *enic = netdev_priv(netdev);
+       unsigned int wq_index = (napi - &enic->napi[0]) - enic->rq_count;
+       struct vnic_wq *wq = &enic->wq[wq_index];
+       unsigned int cq;
+       unsigned int intr;
+       unsigned int wq_work_to_do = -1; /* clean all desc possible */
+       unsigned int wq_work_done;
+       unsigned int wq_irq;
+
+       wq_irq = wq->index;
+       cq = enic_cq_wq(enic, wq_irq);
+       intr = enic_msix_wq_intr(enic, wq_irq);
+       wq_work_done = vnic_cq_service(&enic->cq[cq], wq_work_to_do,
+                                      enic_wq_service, NULL);
+
+       vnic_intr_return_credits(&enic->intr[intr], wq_work_done,
+                                0 /* don't unmask intr */,
+                                1 /* reset intr timer */);
+       if (!wq_work_done) {
+               napi_complete(napi);
+               vnic_intr_unmask(&enic->intr[intr]);
+       }
+
+       return 0;
+}
+
+static int enic_poll_msix_rq(struct napi_struct *napi, int budget)
 {
        struct net_device *netdev = napi->dev;
        struct enic *enic = netdev_priv(netdev);
@@ -1399,17 +1403,19 @@ static int enic_request_intr(struct enic *enic)
                        snprintf(enic->msix[intr].devname,
                                sizeof(enic->msix[intr].devname),
                                "%.11s-rx-%d", netdev->name, i);
-                       enic->msix[intr].isr = enic_isr_msix_rq;
+                       enic->msix[intr].isr = enic_isr_msix;
                        enic->msix[intr].devid = &enic->napi[i];
                }
 
                for (i = 0; i < enic->wq_count; i++) {
+                       int wq = enic_cq_wq(enic, i);
+
                        intr = enic_msix_wq_intr(enic, i);
                        snprintf(enic->msix[intr].devname,
                                sizeof(enic->msix[intr].devname),
                                "%.11s-tx-%d", netdev->name, i);
-                       enic->msix[intr].isr = enic_isr_msix_wq;
-                       enic->msix[intr].devid = enic;
+                       enic->msix[intr].isr = enic_isr_msix;
+                       enic->msix[intr].devid = &enic->napi[wq];
                }
 
                intr = enic_msix_err_intr(enic);
@@ -1585,7 +1591,9 @@ static int enic_open(struct net_device *netdev)
                enic_busy_poll_init_lock(&enic->rq[i]);
                napi_enable(&enic->napi[i]);
        }
-
+       if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
+               for (i = 0; i < enic->wq_count; i++)
+                       napi_enable(&enic->napi[enic_cq_wq(enic, i)]);
        enic_dev_enable(enic);
 
        for (i = 0; i < enic->intr_count; i++)
@@ -1633,6 +1641,9 @@ static int enic_stop(struct net_device *netdev)
 
        netif_carrier_off(netdev);
        netif_tx_disable(netdev);
+       if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
+               for (i = 0; i < enic->wq_count; i++)
+                       napi_disable(&enic->napi[enic_cq_wq(enic, i)]);
 
        if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic))
                enic_dev_del_station_addr(enic);
@@ -1752,13 +1763,14 @@ static void enic_poll_controller(struct net_device *netdev)
        case VNIC_DEV_INTR_MODE_MSIX:
                for (i = 0; i < enic->rq_count; i++) {
                        intr = enic_msix_rq_intr(enic, i);
-                       enic_isr_msix_rq(enic->msix_entry[intr].vector,
-                               &enic->napi[i]);
+                       enic_isr_msix(enic->msix_entry[intr].vector,
+                                     &enic->napi[i]);
                }
 
                for (i = 0; i < enic->wq_count; i++) {
                        intr = enic_msix_wq_intr(enic, i);
-                       enic_isr_msix_wq(enic->msix_entry[intr].vector, enic);
+                       enic_isr_msix(enic->msix_entry[intr].vector,
+                                     &enic->napi[enic_cq_wq(enic, i)]);
                }
 
                break;
@@ -2159,6 +2171,9 @@ static void enic_dev_deinit(struct enic *enic)
                napi_hash_del(&enic->napi[i]);
                netif_napi_del(&enic->napi[i]);
        }
+       if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
+               for (i = 0; i < enic->wq_count; i++)
+                       netif_napi_del(&enic->napi[enic_cq_wq(enic, i)]);
 
        enic_free_vnic_resources(enic);
        enic_clear_intr_mode(enic);
@@ -2229,9 +2244,12 @@ static int enic_dev_init(struct enic *enic)
        case VNIC_DEV_INTR_MODE_MSIX:
                for (i = 0; i < enic->rq_count; i++) {
                        netif_napi_add(netdev, &enic->napi[i],
-                               enic_poll_msix, 64);
+                               enic_poll_msix_rq, NAPI_POLL_WEIGHT);
                        napi_hash_add(&enic->napi[i]);
                }
+               for (i = 0; i < enic->wq_count; i++)
+                       netif_napi_add(netdev, &enic->napi[enic_cq_wq(enic, i)],
+                                      enic_poll_msix_wq, NAPI_POLL_WEIGHT);
                break;
        }