diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/enic/enic.h | 28 | ||||
-rw-r--r-- | drivers/net/enic/enic_main.c | 373 | ||||
-rw-r--r-- | drivers/net/enic/enic_res.c | 49 | ||||
-rw-r--r-- | drivers/net/enic/enic_res.h | 2 | ||||
-rw-r--r-- | drivers/net/enic/vnic_rss.h | 40 |
5 files changed, 368 insertions, 124 deletions
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index ae623206f180..c91d364c5527 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h | |||
@@ -28,10 +28,11 @@ | |||
28 | #include "vnic_intr.h" | 28 | #include "vnic_intr.h" |
29 | #include "vnic_stats.h" | 29 | #include "vnic_stats.h" |
30 | #include "vnic_nic.h" | 30 | #include "vnic_nic.h" |
31 | #include "vnic_rss.h" | ||
31 | 32 | ||
32 | #define DRV_NAME "enic" | 33 | #define DRV_NAME "enic" |
33 | #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver" | 34 | #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver" |
34 | #define DRV_VERSION "1.4.1.2a" | 35 | #define DRV_VERSION "1.4.1.6" |
35 | #define DRV_COPYRIGHT "Copyright 2008-2010 Cisco Systems, Inc" | 36 | #define DRV_COPYRIGHT "Copyright 2008-2010 Cisco Systems, Inc" |
36 | 37 | ||
37 | #define ENIC_BARS_MAX 6 | 38 | #define ENIC_BARS_MAX 6 |
@@ -41,25 +42,6 @@ | |||
41 | #define ENIC_CQ_MAX (ENIC_WQ_MAX + ENIC_RQ_MAX) | 42 | #define ENIC_CQ_MAX (ENIC_WQ_MAX + ENIC_RQ_MAX) |
42 | #define ENIC_INTR_MAX (ENIC_CQ_MAX + 2) | 43 | #define ENIC_INTR_MAX (ENIC_CQ_MAX + 2) |
43 | 44 | ||
44 | enum enic_cq_index { | ||
45 | ENIC_CQ_RQ, | ||
46 | ENIC_CQ_WQ, | ||
47 | }; | ||
48 | |||
49 | enum enic_intx_intr_index { | ||
50 | ENIC_INTX_WQ_RQ, | ||
51 | ENIC_INTX_ERR, | ||
52 | ENIC_INTX_NOTIFY, | ||
53 | }; | ||
54 | |||
55 | enum enic_msix_intr_index { | ||
56 | ENIC_MSIX_RQ, | ||
57 | ENIC_MSIX_WQ, | ||
58 | ENIC_MSIX_ERR, | ||
59 | ENIC_MSIX_NOTIFY, | ||
60 | ENIC_MSIX_MAX, | ||
61 | }; | ||
62 | |||
63 | struct enic_msix_entry { | 45 | struct enic_msix_entry { |
64 | int requested; | 46 | int requested; |
65 | char devname[IFNAMSIZ]; | 47 | char devname[IFNAMSIZ]; |
@@ -90,8 +72,8 @@ struct enic { | |||
90 | struct vnic_dev *vdev; | 72 | struct vnic_dev *vdev; |
91 | struct timer_list notify_timer; | 73 | struct timer_list notify_timer; |
92 | struct work_struct reset; | 74 | struct work_struct reset; |
93 | struct msix_entry msix_entry[ENIC_MSIX_MAX]; | 75 | struct msix_entry msix_entry[ENIC_INTR_MAX]; |
94 | struct enic_msix_entry msix[ENIC_MSIX_MAX]; | 76 | struct enic_msix_entry msix[ENIC_INTR_MAX]; |
95 | u32 msg_enable; | 77 | u32 msg_enable; |
96 | spinlock_t devcmd_lock; | 78 | spinlock_t devcmd_lock; |
97 | u8 mac_addr[ETH_ALEN]; | 79 | u8 mac_addr[ETH_ALEN]; |
@@ -118,7 +100,7 @@ struct enic { | |||
118 | int (*rq_alloc_buf)(struct vnic_rq *rq); | 100 | int (*rq_alloc_buf)(struct vnic_rq *rq); |
119 | u64 rq_truncated_pkts; | 101 | u64 rq_truncated_pkts; |
120 | u64 rq_bad_fcs; | 102 | u64 rq_bad_fcs; |
121 | struct napi_struct napi; | 103 | struct napi_struct napi[ENIC_RQ_MAX]; |
122 | 104 | ||
123 | /* interrupt resource cache line section */ | 105 | /* interrupt resource cache line section */ |
124 | ____cacheline_aligned struct vnic_intr intr[ENIC_INTR_MAX]; | 106 | ____cacheline_aligned struct vnic_intr intr[ENIC_INTR_MAX]; |
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index a1f92f193976..dcfc541291ef 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c | |||
@@ -122,6 +122,51 @@ static int enic_is_dynamic(struct enic *enic) | |||
122 | return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN; | 122 | return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN; |
123 | } | 123 | } |
124 | 124 | ||
125 | static inline unsigned int enic_cq_rq(struct enic *enic, unsigned int rq) | ||
126 | { | ||
127 | return rq; | ||
128 | } | ||
129 | |||
130 | static inline unsigned int enic_cq_wq(struct enic *enic, unsigned int wq) | ||
131 | { | ||
132 | return enic->rq_count + wq; | ||
133 | } | ||
134 | |||
135 | static inline unsigned int enic_legacy_io_intr(void) | ||
136 | { | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static inline unsigned int enic_legacy_err_intr(void) | ||
141 | { | ||
142 | return 1; | ||
143 | } | ||
144 | |||
145 | static inline unsigned int enic_legacy_notify_intr(void) | ||
146 | { | ||
147 | return 2; | ||
148 | } | ||
149 | |||
150 | static inline unsigned int enic_msix_rq_intr(struct enic *enic, unsigned int rq) | ||
151 | { | ||
152 | return rq; | ||
153 | } | ||
154 | |||
155 | static inline unsigned int enic_msix_wq_intr(struct enic *enic, unsigned int wq) | ||
156 | { | ||
157 | return enic->rq_count + wq; | ||
158 | } | ||
159 | |||
160 | static inline unsigned int enic_msix_err_intr(struct enic *enic) | ||
161 | { | ||
162 | return enic->rq_count + enic->wq_count; | ||
163 | } | ||
164 | |||
165 | static inline unsigned int enic_msix_notify_intr(struct enic *enic) | ||
166 | { | ||
167 | return enic->rq_count + enic->wq_count + 1; | ||
168 | } | ||
169 | |||
125 | static int enic_get_settings(struct net_device *netdev, | 170 | static int enic_get_settings(struct net_device *netdev, |
126 | struct ethtool_cmd *ecmd) | 171 | struct ethtool_cmd *ecmd) |
127 | { | 172 | { |
@@ -306,6 +351,7 @@ static int enic_set_coalesce(struct net_device *netdev, | |||
306 | struct enic *enic = netdev_priv(netdev); | 351 | struct enic *enic = netdev_priv(netdev); |
307 | u32 tx_coalesce_usecs; | 352 | u32 tx_coalesce_usecs; |
308 | u32 rx_coalesce_usecs; | 353 | u32 rx_coalesce_usecs; |
354 | unsigned int i, intr; | ||
309 | 355 | ||
310 | tx_coalesce_usecs = min_t(u32, | 356 | tx_coalesce_usecs = min_t(u32, |
311 | INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX), | 357 | INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX), |
@@ -319,7 +365,8 @@ static int enic_set_coalesce(struct net_device *netdev, | |||
319 | if (tx_coalesce_usecs != rx_coalesce_usecs) | 365 | if (tx_coalesce_usecs != rx_coalesce_usecs) |
320 | return -EINVAL; | 366 | return -EINVAL; |
321 | 367 | ||
322 | vnic_intr_coalescing_timer_set(&enic->intr[ENIC_INTX_WQ_RQ], | 368 | intr = enic_legacy_io_intr(); |
369 | vnic_intr_coalescing_timer_set(&enic->intr[intr], | ||
323 | INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs)); | 370 | INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs)); |
324 | break; | 371 | break; |
325 | case VNIC_DEV_INTR_MODE_MSI: | 372 | case VNIC_DEV_INTR_MODE_MSI: |
@@ -330,10 +377,18 @@ static int enic_set_coalesce(struct net_device *netdev, | |||
330 | INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs)); | 377 | INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs)); |
331 | break; | 378 | break; |
332 | case VNIC_DEV_INTR_MODE_MSIX: | 379 | case VNIC_DEV_INTR_MODE_MSIX: |
333 | vnic_intr_coalescing_timer_set(&enic->intr[ENIC_MSIX_WQ], | 380 | for (i = 0; i < enic->wq_count; i++) { |
334 | INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs)); | 381 | intr = enic_msix_wq_intr(enic, i); |
335 | vnic_intr_coalescing_timer_set(&enic->intr[ENIC_MSIX_RQ], | 382 | vnic_intr_coalescing_timer_set(&enic->intr[intr], |
336 | INTR_COALESCE_USEC_TO_HW(rx_coalesce_usecs)); | 383 | INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs)); |
384 | } | ||
385 | |||
386 | for (i = 0; i < enic->rq_count; i++) { | ||
387 | intr = enic_msix_rq_intr(enic, i); | ||
388 | vnic_intr_coalescing_timer_set(&enic->intr[intr], | ||
389 | INTR_COALESCE_USEC_TO_HW(rx_coalesce_usecs)); | ||
390 | } | ||
391 | |||
337 | break; | 392 | break; |
338 | default: | 393 | default: |
339 | break; | 394 | break; |
@@ -482,34 +537,37 @@ static irqreturn_t enic_isr_legacy(int irq, void *data) | |||
482 | { | 537 | { |
483 | struct net_device *netdev = data; | 538 | struct net_device *netdev = data; |
484 | struct enic *enic = netdev_priv(netdev); | 539 | struct enic *enic = netdev_priv(netdev); |
540 | unsigned int io_intr = enic_legacy_io_intr(); | ||
541 | unsigned int err_intr = enic_legacy_err_intr(); | ||
542 | unsigned int notify_intr = enic_legacy_notify_intr(); | ||
485 | u32 pba; | 543 | u32 pba; |
486 | 544 | ||
487 | vnic_intr_mask(&enic->intr[ENIC_INTX_WQ_RQ]); | 545 | vnic_intr_mask(&enic->intr[io_intr]); |
488 | 546 | ||
489 | pba = vnic_intr_legacy_pba(enic->legacy_pba); | 547 | pba = vnic_intr_legacy_pba(enic->legacy_pba); |
490 | if (!pba) { | 548 | if (!pba) { |
491 | vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]); | 549 | vnic_intr_unmask(&enic->intr[io_intr]); |
492 | return IRQ_NONE; /* not our interrupt */ | 550 | return IRQ_NONE; /* not our interrupt */ |
493 | } | 551 | } |
494 | 552 | ||
495 | if (ENIC_TEST_INTR(pba, ENIC_INTX_NOTIFY)) { | 553 | if (ENIC_TEST_INTR(pba, notify_intr)) { |
496 | vnic_intr_return_all_credits(&enic->intr[ENIC_INTX_NOTIFY]); | 554 | vnic_intr_return_all_credits(&enic->intr[notify_intr]); |
497 | enic_notify_check(enic); | 555 | enic_notify_check(enic); |
498 | } | 556 | } |
499 | 557 | ||
500 | if (ENIC_TEST_INTR(pba, ENIC_INTX_ERR)) { | 558 | if (ENIC_TEST_INTR(pba, err_intr)) { |
501 | vnic_intr_return_all_credits(&enic->intr[ENIC_INTX_ERR]); | 559 | vnic_intr_return_all_credits(&enic->intr[err_intr]); |
502 | enic_log_q_error(enic); | 560 | enic_log_q_error(enic); |
503 | /* schedule recovery from WQ/RQ error */ | 561 | /* schedule recovery from WQ/RQ error */ |
504 | schedule_work(&enic->reset); | 562 | schedule_work(&enic->reset); |
505 | return IRQ_HANDLED; | 563 | return IRQ_HANDLED; |
506 | } | 564 | } |
507 | 565 | ||
508 | if (ENIC_TEST_INTR(pba, ENIC_INTX_WQ_RQ)) { | 566 | if (ENIC_TEST_INTR(pba, io_intr)) { |
509 | if (napi_schedule_prep(&enic->napi)) | 567 | if (napi_schedule_prep(&enic->napi[0])) |
510 | __napi_schedule(&enic->napi); | 568 | __napi_schedule(&enic->napi[0]); |
511 | } else { | 569 | } else { |
512 | vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]); | 570 | vnic_intr_unmask(&enic->intr[io_intr]); |
513 | } | 571 | } |
514 | 572 | ||
515 | return IRQ_HANDLED; | 573 | return IRQ_HANDLED; |
@@ -535,17 +593,17 @@ static irqreturn_t enic_isr_msi(int irq, void *data) | |||
535 | * writes). | 593 | * writes). |
536 | */ | 594 | */ |
537 | 595 | ||
538 | napi_schedule(&enic->napi); | 596 | napi_schedule(&enic->napi[0]); |
539 | 597 | ||
540 | return IRQ_HANDLED; | 598 | return IRQ_HANDLED; |
541 | } | 599 | } |
542 | 600 | ||
543 | static irqreturn_t enic_isr_msix_rq(int irq, void *data) | 601 | static irqreturn_t enic_isr_msix_rq(int irq, void *data) |
544 | { | 602 | { |
545 | struct enic *enic = data; | 603 | struct napi_struct *napi = data; |
546 | 604 | ||
547 | /* schedule NAPI polling for RQ cleanup */ | 605 | /* schedule NAPI polling for RQ cleanup */ |
548 | napi_schedule(&enic->napi); | 606 | napi_schedule(napi); |
549 | 607 | ||
550 | return IRQ_HANDLED; | 608 | return IRQ_HANDLED; |
551 | } | 609 | } |
@@ -553,13 +611,15 @@ static irqreturn_t enic_isr_msix_rq(int irq, void *data) | |||
553 | static irqreturn_t enic_isr_msix_wq(int irq, void *data) | 611 | static irqreturn_t enic_isr_msix_wq(int irq, void *data) |
554 | { | 612 | { |
555 | struct enic *enic = data; | 613 | struct enic *enic = data; |
614 | unsigned int cq = enic_cq_wq(enic, 0); | ||
615 | unsigned int intr = enic_msix_wq_intr(enic, 0); | ||
556 | unsigned int wq_work_to_do = -1; /* no limit */ | 616 | unsigned int wq_work_to_do = -1; /* no limit */ |
557 | unsigned int wq_work_done; | 617 | unsigned int wq_work_done; |
558 | 618 | ||
559 | wq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_WQ], | 619 | wq_work_done = vnic_cq_service(&enic->cq[cq], |
560 | wq_work_to_do, enic_wq_service, NULL); | 620 | wq_work_to_do, enic_wq_service, NULL); |
561 | 621 | ||
562 | vnic_intr_return_credits(&enic->intr[ENIC_MSIX_WQ], | 622 | vnic_intr_return_credits(&enic->intr[intr], |
563 | wq_work_done, | 623 | wq_work_done, |
564 | 1 /* unmask intr */, | 624 | 1 /* unmask intr */, |
565 | 1 /* reset intr timer */); | 625 | 1 /* reset intr timer */); |
@@ -570,8 +630,9 @@ static irqreturn_t enic_isr_msix_wq(int irq, void *data) | |||
570 | static irqreturn_t enic_isr_msix_err(int irq, void *data) | 630 | static irqreturn_t enic_isr_msix_err(int irq, void *data) |
571 | { | 631 | { |
572 | struct enic *enic = data; | 632 | struct enic *enic = data; |
633 | unsigned int intr = enic_msix_err_intr(enic); | ||
573 | 634 | ||
574 | vnic_intr_return_all_credits(&enic->intr[ENIC_MSIX_ERR]); | 635 | vnic_intr_return_all_credits(&enic->intr[intr]); |
575 | 636 | ||
576 | enic_log_q_error(enic); | 637 | enic_log_q_error(enic); |
577 | 638 | ||
@@ -584,8 +645,9 @@ static irqreturn_t enic_isr_msix_err(int irq, void *data) | |||
584 | static irqreturn_t enic_isr_msix_notify(int irq, void *data) | 645 | static irqreturn_t enic_isr_msix_notify(int irq, void *data) |
585 | { | 646 | { |
586 | struct enic *enic = data; | 647 | struct enic *enic = data; |
648 | unsigned int intr = enic_msix_notify_intr(enic); | ||
587 | 649 | ||
588 | vnic_intr_return_all_credits(&enic->intr[ENIC_MSIX_NOTIFY]); | 650 | vnic_intr_return_all_credits(&enic->intr[intr]); |
589 | enic_notify_check(enic); | 651 | enic_notify_check(enic); |
590 | 652 | ||
591 | return IRQ_HANDLED; | 653 | return IRQ_HANDLED; |
@@ -1409,8 +1471,8 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, | |||
1409 | (vlan_tci & CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_MASK)) { | 1471 | (vlan_tci & CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_MASK)) { |
1410 | 1472 | ||
1411 | if (netdev->features & NETIF_F_GRO) | 1473 | if (netdev->features & NETIF_F_GRO) |
1412 | vlan_gro_receive(&enic->napi, enic->vlan_group, | 1474 | vlan_gro_receive(&enic->napi[q_number], |
1413 | vlan_tci, skb); | 1475 | enic->vlan_group, vlan_tci, skb); |
1414 | else | 1476 | else |
1415 | vlan_hwaccel_receive_skb(skb, | 1477 | vlan_hwaccel_receive_skb(skb, |
1416 | enic->vlan_group, vlan_tci); | 1478 | enic->vlan_group, vlan_tci); |
@@ -1418,12 +1480,11 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, | |||
1418 | } else { | 1480 | } else { |
1419 | 1481 | ||
1420 | if (netdev->features & NETIF_F_GRO) | 1482 | if (netdev->features & NETIF_F_GRO) |
1421 | napi_gro_receive(&enic->napi, skb); | 1483 | napi_gro_receive(&enic->napi[q_number], skb); |
1422 | else | 1484 | else |
1423 | netif_receive_skb(skb); | 1485 | netif_receive_skb(skb); |
1424 | 1486 | ||
1425 | } | 1487 | } |
1426 | |||
1427 | } else { | 1488 | } else { |
1428 | 1489 | ||
1429 | /* Buffer overflow | 1490 | /* Buffer overflow |
@@ -1447,7 +1508,11 @@ static int enic_rq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc, | |||
1447 | 1508 | ||
1448 | static int enic_poll(struct napi_struct *napi, int budget) | 1509 | static int enic_poll(struct napi_struct *napi, int budget) |
1449 | { | 1510 | { |
1450 | struct enic *enic = container_of(napi, struct enic, napi); | 1511 | struct net_device *netdev = napi->dev; |
1512 | struct enic *enic = netdev_priv(netdev); | ||
1513 | unsigned int cq_rq = enic_cq_rq(enic, 0); | ||
1514 | unsigned int cq_wq = enic_cq_wq(enic, 0); | ||
1515 | unsigned int intr = enic_legacy_io_intr(); | ||
1451 | unsigned int rq_work_to_do = budget; | 1516 | unsigned int rq_work_to_do = budget; |
1452 | unsigned int wq_work_to_do = -1; /* no limit */ | 1517 | unsigned int wq_work_to_do = -1; /* no limit */ |
1453 | unsigned int work_done, rq_work_done, wq_work_done; | 1518 | unsigned int work_done, rq_work_done, wq_work_done; |
@@ -1456,10 +1521,10 @@ static int enic_poll(struct napi_struct *napi, int budget) | |||
1456 | /* Service RQ (first) and WQ | 1521 | /* Service RQ (first) and WQ |
1457 | */ | 1522 | */ |
1458 | 1523 | ||
1459 | rq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ], | 1524 | rq_work_done = vnic_cq_service(&enic->cq[cq_rq], |
1460 | rq_work_to_do, enic_rq_service, NULL); | 1525 | rq_work_to_do, enic_rq_service, NULL); |
1461 | 1526 | ||
1462 | wq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_WQ], | 1527 | wq_work_done = vnic_cq_service(&enic->cq[cq_wq], |
1463 | wq_work_to_do, enic_wq_service, NULL); | 1528 | wq_work_to_do, enic_wq_service, NULL); |
1464 | 1529 | ||
1465 | /* Accumulate intr event credits for this polling | 1530 | /* Accumulate intr event credits for this polling |
@@ -1470,7 +1535,7 @@ static int enic_poll(struct napi_struct *napi, int budget) | |||
1470 | work_done = rq_work_done + wq_work_done; | 1535 | work_done = rq_work_done + wq_work_done; |
1471 | 1536 | ||
1472 | if (work_done > 0) | 1537 | if (work_done > 0) |
1473 | vnic_intr_return_credits(&enic->intr[ENIC_INTX_WQ_RQ], | 1538 | vnic_intr_return_credits(&enic->intr[intr], |
1474 | work_done, | 1539 | work_done, |
1475 | 0 /* don't unmask intr */, | 1540 | 0 /* don't unmask intr */, |
1476 | 0 /* don't reset intr timer */); | 1541 | 0 /* don't reset intr timer */); |
@@ -1491,7 +1556,7 @@ static int enic_poll(struct napi_struct *napi, int budget) | |||
1491 | */ | 1556 | */ |
1492 | 1557 | ||
1493 | napi_complete(napi); | 1558 | napi_complete(napi); |
1494 | vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]); | 1559 | vnic_intr_unmask(&enic->intr[intr]); |
1495 | } | 1560 | } |
1496 | 1561 | ||
1497 | return rq_work_done; | 1562 | return rq_work_done; |
@@ -1499,7 +1564,11 @@ static int enic_poll(struct napi_struct *napi, int budget) | |||
1499 | 1564 | ||
1500 | static int enic_poll_msix(struct napi_struct *napi, int budget) | 1565 | static int enic_poll_msix(struct napi_struct *napi, int budget) |
1501 | { | 1566 | { |
1502 | struct enic *enic = container_of(napi, struct enic, napi); | 1567 | struct net_device *netdev = napi->dev; |
1568 | struct enic *enic = netdev_priv(netdev); | ||
1569 | unsigned int rq = (napi - &enic->napi[0]); | ||
1570 | unsigned int cq = enic_cq_rq(enic, rq); | ||
1571 | unsigned int intr = enic_msix_rq_intr(enic, rq); | ||
1503 | unsigned int work_to_do = budget; | 1572 | unsigned int work_to_do = budget; |
1504 | unsigned int work_done; | 1573 | unsigned int work_done; |
1505 | int err; | 1574 | int err; |
@@ -1507,7 +1576,7 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) | |||
1507 | /* Service RQ | 1576 | /* Service RQ |
1508 | */ | 1577 | */ |
1509 | 1578 | ||
1510 | work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ], | 1579 | work_done = vnic_cq_service(&enic->cq[cq], |
1511 | work_to_do, enic_rq_service, NULL); | 1580 | work_to_do, enic_rq_service, NULL); |
1512 | 1581 | ||
1513 | /* Return intr event credits for this polling | 1582 | /* Return intr event credits for this polling |
@@ -1516,12 +1585,12 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) | |||
1516 | */ | 1585 | */ |
1517 | 1586 | ||
1518 | if (work_done > 0) | 1587 | if (work_done > 0) |
1519 | vnic_intr_return_credits(&enic->intr[ENIC_MSIX_RQ], | 1588 | vnic_intr_return_credits(&enic->intr[intr], |
1520 | work_done, | 1589 | work_done, |
1521 | 0 /* don't unmask intr */, | 1590 | 0 /* don't unmask intr */, |
1522 | 0 /* don't reset intr timer */); | 1591 | 0 /* don't reset intr timer */); |
1523 | 1592 | ||
1524 | err = vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); | 1593 | err = vnic_rq_fill(&enic->rq[rq], enic->rq_alloc_buf); |
1525 | 1594 | ||
1526 | /* Buffer allocation failed. Stay in polling mode | 1595 | /* Buffer allocation failed. Stay in polling mode |
1527 | * so we can try to fill the ring again. | 1596 | * so we can try to fill the ring again. |
@@ -1537,7 +1606,7 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) | |||
1537 | */ | 1606 | */ |
1538 | 1607 | ||
1539 | napi_complete(napi); | 1608 | napi_complete(napi); |
1540 | vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]); | 1609 | vnic_intr_unmask(&enic->intr[intr]); |
1541 | } | 1610 | } |
1542 | 1611 | ||
1543 | return work_done; | 1612 | return work_done; |
@@ -1579,7 +1648,7 @@ static void enic_free_intr(struct enic *enic) | |||
1579 | static int enic_request_intr(struct enic *enic) | 1648 | static int enic_request_intr(struct enic *enic) |
1580 | { | 1649 | { |
1581 | struct net_device *netdev = enic->netdev; | 1650 | struct net_device *netdev = enic->netdev; |
1582 | unsigned int i; | 1651 | unsigned int i, intr; |
1583 | int err = 0; | 1652 | int err = 0; |
1584 | 1653 | ||
1585 | switch (vnic_dev_get_intr_mode(enic->vdev)) { | 1654 | switch (vnic_dev_get_intr_mode(enic->vdev)) { |
@@ -1598,27 +1667,38 @@ static int enic_request_intr(struct enic *enic) | |||
1598 | 1667 | ||
1599 | case VNIC_DEV_INTR_MODE_MSIX: | 1668 | case VNIC_DEV_INTR_MODE_MSIX: |
1600 | 1669 | ||
1601 | sprintf(enic->msix[ENIC_MSIX_RQ].devname, | 1670 | for (i = 0; i < enic->rq_count; i++) { |
1602 | "%.11s-rx-0", netdev->name); | 1671 | intr = enic_msix_rq_intr(enic, i); |
1603 | enic->msix[ENIC_MSIX_RQ].isr = enic_isr_msix_rq; | 1672 | sprintf(enic->msix[intr].devname, |
1604 | enic->msix[ENIC_MSIX_RQ].devid = enic; | 1673 | "%.11s-rx-%d", netdev->name, i); |
1674 | enic->msix[intr].isr = enic_isr_msix_rq; | ||
1675 | enic->msix[intr].devid = &enic->napi[i]; | ||
1676 | } | ||
1605 | 1677 | ||
1606 | sprintf(enic->msix[ENIC_MSIX_WQ].devname, | 1678 | for (i = 0; i < enic->wq_count; i++) { |
1607 | "%.11s-tx-0", netdev->name); | 1679 | intr = enic_msix_wq_intr(enic, i); |
1608 | enic->msix[ENIC_MSIX_WQ].isr = enic_isr_msix_wq; | 1680 | sprintf(enic->msix[intr].devname, |
1609 | enic->msix[ENIC_MSIX_WQ].devid = enic; | 1681 | "%.11s-tx-%d", netdev->name, i); |
1682 | enic->msix[intr].isr = enic_isr_msix_wq; | ||
1683 | enic->msix[intr].devid = enic; | ||
1684 | } | ||
1610 | 1685 | ||
1611 | sprintf(enic->msix[ENIC_MSIX_ERR].devname, | 1686 | intr = enic_msix_err_intr(enic); |
1687 | sprintf(enic->msix[intr].devname, | ||
1612 | "%.11s-err", netdev->name); | 1688 | "%.11s-err", netdev->name); |
1613 | enic->msix[ENIC_MSIX_ERR].isr = enic_isr_msix_err; | 1689 | enic->msix[intr].isr = enic_isr_msix_err; |
1614 | enic->msix[ENIC_MSIX_ERR].devid = enic; | 1690 | enic->msix[intr].devid = enic; |
1615 | 1691 | ||
1616 | sprintf(enic->msix[ENIC_MSIX_NOTIFY].devname, | 1692 | intr = enic_msix_notify_intr(enic); |
1693 | sprintf(enic->msix[intr].devname, | ||
1617 | "%.11s-notify", netdev->name); | 1694 | "%.11s-notify", netdev->name); |
1618 | enic->msix[ENIC_MSIX_NOTIFY].isr = enic_isr_msix_notify; | 1695 | enic->msix[intr].isr = enic_isr_msix_notify; |
1619 | enic->msix[ENIC_MSIX_NOTIFY].devid = enic; | 1696 | enic->msix[intr].devid = enic; |
1697 | |||
1698 | for (i = 0; i < ARRAY_SIZE(enic->msix); i++) | ||
1699 | enic->msix[i].requested = 0; | ||
1620 | 1700 | ||
1621 | for (i = 0; i < ARRAY_SIZE(enic->msix); i++) { | 1701 | for (i = 0; i < enic->intr_count; i++) { |
1622 | err = request_irq(enic->msix_entry[i].vector, | 1702 | err = request_irq(enic->msix_entry[i].vector, |
1623 | enic->msix[i].isr, 0, | 1703 | enic->msix[i].isr, 0, |
1624 | enic->msix[i].devname, | 1704 | enic->msix[i].devname, |
@@ -1664,10 +1744,12 @@ static int enic_dev_notify_set(struct enic *enic) | |||
1664 | spin_lock(&enic->devcmd_lock); | 1744 | spin_lock(&enic->devcmd_lock); |
1665 | switch (vnic_dev_get_intr_mode(enic->vdev)) { | 1745 | switch (vnic_dev_get_intr_mode(enic->vdev)) { |
1666 | case VNIC_DEV_INTR_MODE_INTX: | 1746 | case VNIC_DEV_INTR_MODE_INTX: |
1667 | err = vnic_dev_notify_set(enic->vdev, ENIC_INTX_NOTIFY); | 1747 | err = vnic_dev_notify_set(enic->vdev, |
1748 | enic_legacy_notify_intr()); | ||
1668 | break; | 1749 | break; |
1669 | case VNIC_DEV_INTR_MODE_MSIX: | 1750 | case VNIC_DEV_INTR_MODE_MSIX: |
1670 | err = vnic_dev_notify_set(enic->vdev, ENIC_MSIX_NOTIFY); | 1751 | err = vnic_dev_notify_set(enic->vdev, |
1752 | enic_msix_notify_intr(enic)); | ||
1671 | break; | 1753 | break; |
1672 | default: | 1754 | default: |
1673 | err = vnic_dev_notify_set(enic->vdev, -1 /* no intr */); | 1755 | err = vnic_dev_notify_set(enic->vdev, -1 /* no intr */); |
@@ -1762,7 +1844,10 @@ static int enic_open(struct net_device *netdev) | |||
1762 | enic_set_multicast_list(netdev); | 1844 | enic_set_multicast_list(netdev); |
1763 | 1845 | ||
1764 | netif_wake_queue(netdev); | 1846 | netif_wake_queue(netdev); |
1765 | napi_enable(&enic->napi); | 1847 | |
1848 | for (i = 0; i < enic->rq_count; i++) | ||
1849 | napi_enable(&enic->napi[i]); | ||
1850 | |||
1766 | enic_dev_enable(enic); | 1851 | enic_dev_enable(enic); |
1767 | 1852 | ||
1768 | for (i = 0; i < enic->intr_count; i++) | 1853 | for (i = 0; i < enic->intr_count; i++) |
@@ -1797,7 +1882,10 @@ static int enic_stop(struct net_device *netdev) | |||
1797 | del_timer_sync(&enic->notify_timer); | 1882 | del_timer_sync(&enic->notify_timer); |
1798 | 1883 | ||
1799 | enic_dev_disable(enic); | 1884 | enic_dev_disable(enic); |
1800 | napi_disable(&enic->napi); | 1885 | |
1886 | for (i = 0; i < enic->rq_count; i++) | ||
1887 | napi_disable(&enic->napi[i]); | ||
1888 | |||
1801 | netif_carrier_off(netdev); | 1889 | netif_carrier_off(netdev); |
1802 | netif_tx_disable(netdev); | 1890 | netif_tx_disable(netdev); |
1803 | enic_dev_del_station_addr(enic); | 1891 | enic_dev_del_station_addr(enic); |
@@ -1857,11 +1945,16 @@ static void enic_poll_controller(struct net_device *netdev) | |||
1857 | { | 1945 | { |
1858 | struct enic *enic = netdev_priv(netdev); | 1946 | struct enic *enic = netdev_priv(netdev); |
1859 | struct vnic_dev *vdev = enic->vdev; | 1947 | struct vnic_dev *vdev = enic->vdev; |
1948 | unsigned int i, intr; | ||
1860 | 1949 | ||
1861 | switch (vnic_dev_get_intr_mode(vdev)) { | 1950 | switch (vnic_dev_get_intr_mode(vdev)) { |
1862 | case VNIC_DEV_INTR_MODE_MSIX: | 1951 | case VNIC_DEV_INTR_MODE_MSIX: |
1863 | enic_isr_msix_rq(enic->pdev->irq, enic); | 1952 | for (i = 0; i < enic->rq_count; i++) { |
1864 | enic_isr_msix_wq(enic->pdev->irq, enic); | 1953 | intr = enic_msix_rq_intr(enic, i); |
1954 | enic_isr_msix_rq(enic->msix_entry[intr].vector, enic); | ||
1955 | } | ||
1956 | intr = enic_msix_wq_intr(enic, i); | ||
1957 | enic_isr_msix_wq(enic->msix_entry[intr].vector, enic); | ||
1865 | break; | 1958 | break; |
1866 | case VNIC_DEV_INTR_MODE_MSI: | 1959 | case VNIC_DEV_INTR_MODE_MSI: |
1867 | enic_isr_msi(enic->pdev->irq, enic); | 1960 | enic_isr_msi(enic->pdev->irq, enic); |
@@ -1936,19 +2029,73 @@ static int enic_dev_hang_reset(struct enic *enic) | |||
1936 | return err; | 2029 | return err; |
1937 | } | 2030 | } |
1938 | 2031 | ||
1939 | static int enic_set_niccfg(struct enic *enic) | 2032 | static int enic_set_rsskey(struct enic *enic) |
2033 | { | ||
2034 | u64 rss_key_buf_pa; | ||
2035 | union vnic_rss_key *rss_key_buf_va = NULL; | ||
2036 | union vnic_rss_key rss_key = { | ||
2037 | .key[0].b = {85, 67, 83, 97, 119, 101, 115, 111, 109, 101}, | ||
2038 | .key[1].b = {80, 65, 76, 79, 117, 110, 105, 113, 117, 101}, | ||
2039 | .key[2].b = {76, 73, 78, 85, 88, 114, 111, 99, 107, 115}, | ||
2040 | .key[3].b = {69, 78, 73, 67, 105, 115, 99, 111, 111, 108}, | ||
2041 | }; | ||
2042 | int err; | ||
2043 | |||
2044 | rss_key_buf_va = pci_alloc_consistent(enic->pdev, | ||
2045 | sizeof(union vnic_rss_key), &rss_key_buf_pa); | ||
2046 | if (!rss_key_buf_va) | ||
2047 | return -ENOMEM; | ||
2048 | |||
2049 | memcpy(rss_key_buf_va, &rss_key, sizeof(union vnic_rss_key)); | ||
2050 | |||
2051 | spin_lock(&enic->devcmd_lock); | ||
2052 | err = enic_set_rss_key(enic, | ||
2053 | rss_key_buf_pa, | ||
2054 | sizeof(union vnic_rss_key)); | ||
2055 | spin_unlock(&enic->devcmd_lock); | ||
2056 | |||
2057 | pci_free_consistent(enic->pdev, sizeof(union vnic_rss_key), | ||
2058 | rss_key_buf_va, rss_key_buf_pa); | ||
2059 | |||
2060 | return err; | ||
2061 | } | ||
2062 | |||
2063 | static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits) | ||
2064 | { | ||
2065 | u64 rss_cpu_buf_pa; | ||
2066 | union vnic_rss_cpu *rss_cpu_buf_va = NULL; | ||
2067 | unsigned int i; | ||
2068 | int err; | ||
2069 | |||
2070 | rss_cpu_buf_va = pci_alloc_consistent(enic->pdev, | ||
2071 | sizeof(union vnic_rss_cpu), &rss_cpu_buf_pa); | ||
2072 | if (!rss_cpu_buf_va) | ||
2073 | return -ENOMEM; | ||
2074 | |||
2075 | for (i = 0; i < (1 << rss_hash_bits); i++) | ||
2076 | (*rss_cpu_buf_va).cpu[i/4].b[i%4] = i % enic->rq_count; | ||
2077 | |||
2078 | spin_lock(&enic->devcmd_lock); | ||
2079 | err = enic_set_rss_cpu(enic, | ||
2080 | rss_cpu_buf_pa, | ||
2081 | sizeof(union vnic_rss_cpu)); | ||
2082 | spin_unlock(&enic->devcmd_lock); | ||
2083 | |||
2084 | pci_free_consistent(enic->pdev, sizeof(union vnic_rss_cpu), | ||
2085 | rss_cpu_buf_va, rss_cpu_buf_pa); | ||
2086 | |||
2087 | return err; | ||
2088 | } | ||
2089 | |||
2090 | static int enic_set_niccfg(struct enic *enic, u8 rss_default_cpu, | ||
2091 | u8 rss_hash_type, u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable) | ||
1940 | { | 2092 | { |
1941 | const u8 rss_default_cpu = 0; | ||
1942 | const u8 rss_hash_type = 0; | ||
1943 | const u8 rss_hash_bits = 0; | ||
1944 | const u8 rss_base_cpu = 0; | ||
1945 | const u8 rss_enable = 0; | ||
1946 | const u8 tso_ipid_split_en = 0; | 2093 | const u8 tso_ipid_split_en = 0; |
1947 | const u8 ig_vlan_strip_en = 1; | 2094 | const u8 ig_vlan_strip_en = 1; |
1948 | int err; | 2095 | int err; |
1949 | 2096 | ||
1950 | /* Enable VLAN tag stripping. RSS not enabled (yet). | 2097 | /* Enable VLAN tag stripping. |
1951 | */ | 2098 | */ |
1952 | 2099 | ||
1953 | spin_lock(&enic->devcmd_lock); | 2100 | spin_lock(&enic->devcmd_lock); |
1954 | err = enic_set_nic_cfg(enic, | 2101 | err = enic_set_nic_cfg(enic, |
@@ -1961,6 +2108,35 @@ static int enic_set_niccfg(struct enic *enic) | |||
1961 | return err; | 2108 | return err; |
1962 | } | 2109 | } |
1963 | 2110 | ||
2111 | static int enic_set_rss_nic_cfg(struct enic *enic) | ||
2112 | { | ||
2113 | struct device *dev = enic_get_dev(enic); | ||
2114 | const u8 rss_default_cpu = 0; | ||
2115 | const u8 rss_hash_type = NIC_CFG_RSS_HASH_TYPE_IPV4 | | ||
2116 | NIC_CFG_RSS_HASH_TYPE_TCP_IPV4 | | ||
2117 | NIC_CFG_RSS_HASH_TYPE_IPV6 | | ||
2118 | NIC_CFG_RSS_HASH_TYPE_TCP_IPV6; | ||
2119 | const u8 rss_hash_bits = 7; | ||
2120 | const u8 rss_base_cpu = 0; | ||
2121 | u8 rss_enable = ENIC_SETTING(enic, RSS) && (enic->rq_count > 1); | ||
2122 | |||
2123 | if (rss_enable) { | ||
2124 | if (!enic_set_rsskey(enic)) { | ||
2125 | if (enic_set_rsscpu(enic, rss_hash_bits)) { | ||
2126 | rss_enable = 0; | ||
2127 | dev_warn(dev, "RSS disabled, " | ||
2128 | "Failed to set RSS cpu indirection table."); | ||
2129 | } | ||
2130 | } else { | ||
2131 | rss_enable = 0; | ||
2132 | dev_warn(dev, "RSS disabled, Failed to set RSS key.\n"); | ||
2133 | } | ||
2134 | } | ||
2135 | |||
2136 | return enic_set_niccfg(enic, rss_default_cpu, rss_hash_type, | ||
2137 | rss_hash_bits, rss_base_cpu, rss_enable); | ||
2138 | } | ||
2139 | |||
1964 | static int enic_dev_hang_notify(struct enic *enic) | 2140 | static int enic_dev_hang_notify(struct enic *enic) |
1965 | { | 2141 | { |
1966 | int err; | 2142 | int err; |
@@ -1998,7 +2174,7 @@ static void enic_reset(struct work_struct *work) | |||
1998 | enic_dev_hang_reset(enic); | 2174 | enic_dev_hang_reset(enic); |
1999 | enic_reset_multicast_list(enic); | 2175 | enic_reset_multicast_list(enic); |
2000 | enic_init_vnic_resources(enic); | 2176 | enic_init_vnic_resources(enic); |
2001 | enic_set_niccfg(enic); | 2177 | enic_set_rss_nic_cfg(enic); |
2002 | enic_dev_set_ig_vlan_rewrite_mode(enic); | 2178 | enic_dev_set_ig_vlan_rewrite_mode(enic); |
2003 | enic_open(enic->netdev); | 2179 | enic_open(enic->netdev); |
2004 | 2180 | ||
@@ -2007,12 +2183,12 @@ static void enic_reset(struct work_struct *work) | |||
2007 | 2183 | ||
2008 | static int enic_set_intr_mode(struct enic *enic) | 2184 | static int enic_set_intr_mode(struct enic *enic) |
2009 | { | 2185 | { |
2010 | unsigned int n = 1; | 2186 | unsigned int n = min_t(unsigned int, enic->rq_count, ENIC_RQ_MAX); |
2011 | unsigned int m = 1; | 2187 | unsigned int m = 1; |
2012 | unsigned int i; | 2188 | unsigned int i; |
2013 | 2189 | ||
2014 | /* Set interrupt mode (INTx, MSI, MSI-X) depending | 2190 | /* Set interrupt mode (INTx, MSI, MSI-X) depending |
2015 | * system capabilities. | 2191 | * on system capabilities. |
2016 | * | 2192 | * |
2017 | * Try MSI-X first | 2193 | * Try MSI-X first |
2018 | * | 2194 | * |
@@ -2025,21 +2201,47 @@ static int enic_set_intr_mode(struct enic *enic) | |||
2025 | for (i = 0; i < n + m + 2; i++) | 2201 | for (i = 0; i < n + m + 2; i++) |
2026 | enic->msix_entry[i].entry = i; | 2202 | enic->msix_entry[i].entry = i; |
2027 | 2203 | ||
2028 | if (enic->config.intr_mode < 1 && | 2204 | /* Use multiple RQs if RSS is enabled |
2205 | */ | ||
2206 | |||
2207 | if (ENIC_SETTING(enic, RSS) && | ||
2208 | enic->config.intr_mode < 1 && | ||
2029 | enic->rq_count >= n && | 2209 | enic->rq_count >= n && |
2030 | enic->wq_count >= m && | 2210 | enic->wq_count >= m && |
2031 | enic->cq_count >= n + m && | 2211 | enic->cq_count >= n + m && |
2032 | enic->intr_count >= n + m + 2 && | 2212 | enic->intr_count >= n + m + 2) { |
2033 | !pci_enable_msix(enic->pdev, enic->msix_entry, n + m + 2)) { | ||
2034 | 2213 | ||
2035 | enic->rq_count = n; | 2214 | if (!pci_enable_msix(enic->pdev, enic->msix_entry, n + m + 2)) { |
2036 | enic->wq_count = m; | ||
2037 | enic->cq_count = n + m; | ||
2038 | enic->intr_count = n + m + 2; | ||
2039 | 2215 | ||
2040 | vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_MSIX); | 2216 | enic->rq_count = n; |
2217 | enic->wq_count = m; | ||
2218 | enic->cq_count = n + m; | ||
2219 | enic->intr_count = n + m + 2; | ||
2041 | 2220 | ||
2042 | return 0; | 2221 | vnic_dev_set_intr_mode(enic->vdev, |
2222 | VNIC_DEV_INTR_MODE_MSIX); | ||
2223 | |||
2224 | return 0; | ||
2225 | } | ||
2226 | } | ||
2227 | |||
2228 | if (enic->config.intr_mode < 1 && | ||
2229 | enic->rq_count >= 1 && | ||
2230 | enic->wq_count >= m && | ||
2231 | enic->cq_count >= 1 + m && | ||
2232 | enic->intr_count >= 1 + m + 2) { | ||
2233 | if (!pci_enable_msix(enic->pdev, enic->msix_entry, 1 + m + 2)) { | ||
2234 | |||
2235 | enic->rq_count = 1; | ||
2236 | enic->wq_count = m; | ||
2237 | enic->cq_count = 1 + m; | ||
2238 | enic->intr_count = 1 + m + 2; | ||
2239 | |||
2240 | vnic_dev_set_intr_mode(enic->vdev, | ||
2241 | VNIC_DEV_INTR_MODE_MSIX); | ||
2242 | |||
2243 | return 0; | ||
2244 | } | ||
2043 | } | 2245 | } |
2044 | 2246 | ||
2045 | /* Next try MSI | 2247 | /* Next try MSI |
@@ -2149,7 +2351,11 @@ static const struct net_device_ops enic_netdev_ops = { | |||
2149 | 2351 | ||
2150 | static void enic_dev_deinit(struct enic *enic) | 2352 | static void enic_dev_deinit(struct enic *enic) |
2151 | { | 2353 | { |
2152 | netif_napi_del(&enic->napi); | 2354 | unsigned int i; |
2355 | |||
2356 | for (i = 0; i < enic->rq_count; i++) | ||
2357 | netif_napi_del(&enic->napi[i]); | ||
2358 | |||
2153 | enic_free_vnic_resources(enic); | 2359 | enic_free_vnic_resources(enic); |
2154 | enic_clear_intr_mode(enic); | 2360 | enic_clear_intr_mode(enic); |
2155 | } | 2361 | } |
@@ -2158,6 +2364,7 @@ static int enic_dev_init(struct enic *enic) | |||
2158 | { | 2364 | { |
2159 | struct device *dev = enic_get_dev(enic); | 2365 | struct device *dev = enic_get_dev(enic); |
2160 | struct net_device *netdev = enic->netdev; | 2366 | struct net_device *netdev = enic->netdev; |
2367 | unsigned int i; | ||
2161 | int err; | 2368 | int err; |
2162 | 2369 | ||
2163 | /* Get vNIC configuration | 2370 | /* Get vNIC configuration |
@@ -2202,7 +2409,7 @@ static int enic_dev_init(struct enic *enic) | |||
2202 | goto err_out_free_vnic_resources; | 2409 | goto err_out_free_vnic_resources; |
2203 | } | 2410 | } |
2204 | 2411 | ||
2205 | err = enic_set_niccfg(enic); | 2412 | err = enic_set_rss_nic_cfg(enic); |
2206 | if (err) { | 2413 | if (err) { |
2207 | dev_err(dev, "Failed to config nic, aborting\n"); | 2414 | dev_err(dev, "Failed to config nic, aborting\n"); |
2208 | goto err_out_free_vnic_resources; | 2415 | goto err_out_free_vnic_resources; |
@@ -2217,10 +2424,12 @@ static int enic_dev_init(struct enic *enic) | |||
2217 | 2424 | ||
2218 | switch (vnic_dev_get_intr_mode(enic->vdev)) { | 2425 | switch (vnic_dev_get_intr_mode(enic->vdev)) { |
2219 | default: | 2426 | default: |
2220 | netif_napi_add(netdev, &enic->napi, enic_poll, 64); | 2427 | netif_napi_add(netdev, &enic->napi[0], enic_poll, 64); |
2221 | break; | 2428 | break; |
2222 | case VNIC_DEV_INTR_MODE_MSIX: | 2429 | case VNIC_DEV_INTR_MODE_MSIX: |
2223 | netif_napi_add(netdev, &enic->napi, enic_poll_msix, 64); | 2430 | for (i = 0; i < enic->rq_count; i++) |
2431 | netif_napi_add(netdev, &enic->napi[i], | ||
2432 | enic_poll_msix, 64); | ||
2224 | break; | 2433 | break; |
2225 | } | 2434 | } |
2226 | 2435 | ||
diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c index 19a276cf7681..f111a37419ce 100644 --- a/drivers/net/enic/enic_res.c +++ b/drivers/net/enic/enic_res.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "vnic_intr.h" | 35 | #include "vnic_intr.h" |
36 | #include "vnic_stats.h" | 36 | #include "vnic_stats.h" |
37 | #include "vnic_nic.h" | 37 | #include "vnic_nic.h" |
38 | #include "vnic_rss.h" | ||
38 | #include "enic_res.h" | 39 | #include "enic_res.h" |
39 | #include "enic.h" | 40 | #include "enic.h" |
40 | 41 | ||
@@ -93,13 +94,14 @@ int enic_get_vnic_config(struct enic *enic) | |||
93 | INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX), | 94 | INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX), |
94 | c->intr_timer_usec); | 95 | c->intr_timer_usec); |
95 | 96 | ||
96 | dev_info(enic_get_dev(enic), "vNIC MAC addr %pM wq/rq %d/%d\n", | 97 | dev_info(enic_get_dev(enic), |
97 | enic->mac_addr, c->wq_desc_count, c->rq_desc_count); | 98 | "vNIC MAC addr %pM wq/rq %d/%d mtu %d\n", |
98 | dev_info(enic_get_dev(enic), "vNIC mtu %d csum tx/rx %d/%d " | 99 | enic->mac_addr, c->wq_desc_count, c->rq_desc_count, c->mtu); |
99 | "tso/lro %d/%d intr timer %d usec\n", | 100 | dev_info(enic_get_dev(enic), "vNIC csum tx/rx %d/%d " |
100 | c->mtu, ENIC_SETTING(enic, TXCSUM), | 101 | "tso/lro %d/%d intr timer %d usec rss %d\n", |
101 | ENIC_SETTING(enic, RXCSUM), ENIC_SETTING(enic, TSO), | 102 | ENIC_SETTING(enic, TXCSUM), ENIC_SETTING(enic, RXCSUM), |
102 | ENIC_SETTING(enic, LRO), c->intr_timer_usec); | 103 | ENIC_SETTING(enic, TSO), ENIC_SETTING(enic, LRO), |
104 | c->intr_timer_usec, ENIC_SETTING(enic, RSS)); | ||
103 | 105 | ||
104 | return 0; | 106 | return 0; |
105 | } | 107 | } |
@@ -148,6 +150,22 @@ int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type, | |||
148 | return vnic_dev_cmd(enic->vdev, CMD_NIC_CFG, &a0, &a1, wait); | 150 | return vnic_dev_cmd(enic->vdev, CMD_NIC_CFG, &a0, &a1, wait); |
149 | } | 151 | } |
150 | 152 | ||
153 | int enic_set_rss_key(struct enic *enic, dma_addr_t key_pa, u64 len) | ||
154 | { | ||
155 | u64 a0 = (u64)key_pa, a1 = len; | ||
156 | int wait = 1000; | ||
157 | |||
158 | return vnic_dev_cmd(enic->vdev, CMD_RSS_KEY, &a0, &a1, wait); | ||
159 | } | ||
160 | |||
161 | int enic_set_rss_cpu(struct enic *enic, dma_addr_t cpu_pa, u64 len) | ||
162 | { | ||
163 | u64 a0 = (u64)cpu_pa, a1 = len; | ||
164 | int wait = 1000; | ||
165 | |||
166 | return vnic_dev_cmd(enic->vdev, CMD_RSS_CPU, &a0, &a1, wait); | ||
167 | } | ||
168 | |||
151 | void enic_free_vnic_resources(struct enic *enic) | 169 | void enic_free_vnic_resources(struct enic *enic) |
152 | { | 170 | { |
153 | unsigned int i; | 171 | unsigned int i; |
@@ -164,18 +182,11 @@ void enic_free_vnic_resources(struct enic *enic) | |||
164 | 182 | ||
165 | void enic_get_res_counts(struct enic *enic) | 183 | void enic_get_res_counts(struct enic *enic) |
166 | { | 184 | { |
167 | enic->wq_count = min_t(int, | 185 | enic->wq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ); |
168 | vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ), | 186 | enic->rq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ); |
169 | ENIC_WQ_MAX); | 187 | enic->cq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ); |
170 | enic->rq_count = min_t(int, | 188 | enic->intr_count = vnic_dev_get_res_count(enic->vdev, |
171 | vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ), | 189 | RES_TYPE_INTR_CTRL); |
172 | ENIC_RQ_MAX); | ||
173 | enic->cq_count = min_t(int, | ||
174 | vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ), | ||
175 | ENIC_CQ_MAX); | ||
176 | enic->intr_count = min_t(int, | ||
177 | vnic_dev_get_res_count(enic->vdev, RES_TYPE_INTR_CTRL), | ||
178 | ENIC_INTR_MAX); | ||
179 | 190 | ||
180 | dev_info(enic_get_dev(enic), | 191 | dev_info(enic_get_dev(enic), |
181 | "vNIC resources avail: wq %d rq %d cq %d intr %d\n", | 192 | "vNIC resources avail: wq %d rq %d cq %d intr %d\n", |
diff --git a/drivers/net/enic/enic_res.h b/drivers/net/enic/enic_res.h index 3c59f541cb5d..83bd172c356c 100644 --- a/drivers/net/enic/enic_res.h +++ b/drivers/net/enic/enic_res.h | |||
@@ -137,6 +137,8 @@ int enic_del_vlan(struct enic *enic, u16 vlanid); | |||
137 | int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type, | 137 | int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type, |
138 | u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en, | 138 | u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en, |
139 | u8 ig_vlan_strip_en); | 139 | u8 ig_vlan_strip_en); |
140 | int enic_set_rss_key(struct enic *enic, dma_addr_t key_pa, u64 len); | ||
141 | int enic_set_rss_cpu(struct enic *enic, dma_addr_t cpu_pa, u64 len); | ||
140 | void enic_get_res_counts(struct enic *enic); | 142 | void enic_get_res_counts(struct enic *enic); |
141 | void enic_init_vnic_resources(struct enic *enic); | 143 | void enic_init_vnic_resources(struct enic *enic); |
142 | int enic_alloc_vnic_resources(struct enic *); | 144 | int enic_alloc_vnic_resources(struct enic *); |
diff --git a/drivers/net/enic/vnic_rss.h b/drivers/net/enic/vnic_rss.h new file mode 100644 index 000000000000..fa421baf45b8 --- /dev/null +++ b/drivers/net/enic/vnic_rss.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. | ||
3 | * Copyright 2007 Nuova Systems, Inc. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you may redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; version 2 of the License. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
10 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
11 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
12 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
13 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
15 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
16 | * SOFTWARE. | ||
17 | */ | ||
18 | |||
19 | #ifndef _VNIC_RSS_H_ | ||
20 | #define _VNIC_RSS_H_ | ||
21 | |||
22 | /* RSS key array */ | ||
23 | union vnic_rss_key { | ||
24 | struct { | ||
25 | u8 b[10]; | ||
26 | u8 b_pad[6]; | ||
27 | } key[4]; | ||
28 | u64 raw[8]; | ||
29 | }; | ||
30 | |||
31 | /* RSS cpu array */ | ||
32 | union vnic_rss_cpu { | ||
33 | struct { | ||
34 | u8 b[4] ; | ||
35 | u8 b_pad[4]; | ||
36 | } cpu[32]; | ||
37 | u64 raw[32]; | ||
38 | }; | ||
39 | |||
40 | #endif /* _VNIC_RSS_H_ */ | ||