diff options
-rw-r--r-- | drivers/net/ethernet/cisco/enic/enic.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/enic_main.c | 88 |
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 | ||
319 | static irqreturn_t enic_isr_msix_rq(int irq, void *data) | 319 | static 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 | ||
329 | static 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 | |||
353 | static irqreturn_t enic_isr_msix_err(int irq, void *data) | 328 | static 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 | ||
1277 | static int enic_poll_msix(struct napi_struct *napi, int budget) | 1252 | static 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 | |||
1281 | static 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 | ||