aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen/netxen_nic_main.c
diff options
context:
space:
mode:
authorDhananjay Phadke <dhananjay@netxen.com>2009-03-13 10:52:05 -0400
committerDavid S. Miller <davem@davemloft.net>2009-03-14 17:00:33 -0400
commitd8b100c5da003b6f8c410453e1e6e74ced8d1cc1 (patch)
tree75d895254bb70859ef5c3b4cab2d5da313af8e87 /drivers/net/netxen/netxen_nic_main.c
parent9b3ef55c6ddbe8c7b76707eae9a77d874fe2cec0 (diff)
netxen: add receive side scaling (rss) support
This patch enables the load balancing capability of firmware and hardware to spray traffic into different cpus through separate rx msix interrupts. The feature is being enabled for NX3031, NX2031 (old) will be enabled later. This depends on msi-x and compatibility with msi and legacy is maintained by enabling single rx ring. Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/netxen/netxen_nic_main.c')
-rw-r--r--drivers/net/netxen/netxen_nic_main.c157
1 files changed, 118 insertions, 39 deletions
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 00eaeee235e..274d1e0c893 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -135,20 +135,71 @@ static uint32_t msi_tgt_status[8] = {
135 135
136static struct netxen_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG; 136static struct netxen_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG;
137 137
138static inline void netxen_nic_disable_int(struct netxen_adapter *adapter) 138static inline void netxen_nic_disable_int(struct nx_host_sds_ring *sds_ring)
139{ 139{
140 adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0); 140 struct netxen_adapter *adapter = sds_ring->adapter;
141
142 adapter->pci_write_normalize(adapter, sds_ring->crb_intr_mask, 0);
141} 143}
142 144
143static inline void netxen_nic_enable_int(struct netxen_adapter *adapter) 145static inline void netxen_nic_enable_int(struct nx_host_sds_ring *sds_ring)
144{ 146{
145 adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0x1); 147 struct netxen_adapter *adapter = sds_ring->adapter;
148
149 adapter->pci_write_normalize(adapter, sds_ring->crb_intr_mask, 0x1);
146 150
147 if (!NETXEN_IS_MSI_FAMILY(adapter)) 151 if (!NETXEN_IS_MSI_FAMILY(adapter))
148 adapter->pci_write_immediate(adapter, 152 adapter->pci_write_immediate(adapter,
149 adapter->legacy_intr.tgt_mask_reg, 0xfbff); 153 adapter->legacy_intr.tgt_mask_reg, 0xfbff);
150} 154}
151 155
156static void
157netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev)
158{
159 int ring;
160 struct nx_host_sds_ring *sds_ring;
161 struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
162
163 if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
164 adapter->max_sds_rings = (num_online_cpus() >= 4) ? 4 : 2;
165 else
166 adapter->max_sds_rings = 1;
167
168 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
169 sds_ring = &recv_ctx->sds_rings[ring];
170 netif_napi_add(netdev, &sds_ring->napi,
171 netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
172 }
173}
174
175static void
176netxen_napi_enable(struct netxen_adapter *adapter)
177{
178 int ring;
179 struct nx_host_sds_ring *sds_ring;
180 struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
181
182 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
183 sds_ring = &recv_ctx->sds_rings[ring];
184 napi_enable(&sds_ring->napi);
185 netxen_nic_enable_int(sds_ring);
186 }
187}
188
189static void
190netxen_napi_disable(struct netxen_adapter *adapter)
191{
192 int ring;
193 struct nx_host_sds_ring *sds_ring;
194 struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
195
196 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
197 sds_ring = &recv_ctx->sds_rings[ring];
198 netxen_nic_disable_int(sds_ring);
199 napi_disable(&sds_ring->napi);
200 }
201}
202
152static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id) 203static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id)
153{ 204{
154 struct pci_dev *pdev = adapter->pdev; 205 struct pci_dev *pdev = adapter->pdev;
@@ -226,7 +277,6 @@ static void netxen_check_options(struct netxen_adapter *adapter)
226 adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS; 277 adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS;
227 adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS; 278 adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS;
228 279
229 adapter->max_possible_rss_rings = 1;
230 return; 280 return;
231} 281}
232 282
@@ -447,6 +497,7 @@ request_msi:
447 dev_info(&pdev->dev, "using msi interrupts\n"); 497 dev_info(&pdev->dev, "using msi interrupts\n");
448 } else 498 } else
449 dev_info(&pdev->dev, "using legacy interrupts\n"); 499 dev_info(&pdev->dev, "using legacy interrupts\n");
500 adapter->msix_entries[0].vector = pdev->irq;
450 } 501 }
451} 502}
452 503
@@ -671,8 +722,12 @@ static int
671netxen_nic_request_irq(struct netxen_adapter *adapter) 722netxen_nic_request_irq(struct netxen_adapter *adapter)
672{ 723{
673 irq_handler_t handler; 724 irq_handler_t handler;
725 struct nx_host_sds_ring *sds_ring;
726 int err, ring;
727
674 unsigned long flags = IRQF_SAMPLE_RANDOM; 728 unsigned long flags = IRQF_SAMPLE_RANDOM;
675 struct net_device *netdev = adapter->netdev; 729 struct net_device *netdev = adapter->netdev;
730 struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
676 731
677 if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) || 732 if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) ||
678 (adapter->intr_scheme != INTR_SCHEME_PERPORT)) { 733 (adapter->intr_scheme != INTR_SCHEME_PERPORT)) {
@@ -693,8 +748,30 @@ netxen_nic_request_irq(struct netxen_adapter *adapter)
693 } 748 }
694 adapter->irq = netdev->irq; 749 adapter->irq = netdev->irq;
695 750
696 return request_irq(adapter->irq, handler, 751 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
697 flags, netdev->name, adapter); 752 sds_ring = &recv_ctx->sds_rings[ring];
753 sprintf(sds_ring->name, "%16s[%d]", netdev->name, ring);
754 err = request_irq(sds_ring->irq, handler,
755 flags, sds_ring->name, sds_ring);
756 if (err)
757 return err;
758 }
759
760 return 0;
761}
762
763static void
764netxen_nic_free_irq(struct netxen_adapter *adapter)
765{
766 int ring;
767 struct nx_host_sds_ring *sds_ring;
768
769 struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
770
771 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
772 sds_ring = &recv_ctx->sds_rings[ring];
773 free_irq(sds_ring->irq, sds_ring);
774 }
698} 775}
699 776
700static int 777static int
@@ -719,8 +796,10 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
719 adapter->ahw.linkup = 0; 796 adapter->ahw.linkup = 0;
720 mod_timer(&adapter->watchdog_timer, jiffies); 797 mod_timer(&adapter->watchdog_timer, jiffies);
721 798
722 napi_enable(&adapter->napi); 799 netxen_napi_enable(adapter);
723 netxen_nic_enable_int(adapter); 800
801 if (adapter->max_sds_rings > 1)
802 netxen_config_rss(adapter, 1);
724 803
725 return 0; 804 return 0;
726} 805}
@@ -730,13 +809,11 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
730{ 809{
731 netif_carrier_off(netdev); 810 netif_carrier_off(netdev);
732 netif_stop_queue(netdev); 811 netif_stop_queue(netdev);
733 napi_disable(&adapter->napi); 812 netxen_napi_disable(adapter);
734 813
735 if (adapter->stop_port) 814 if (adapter->stop_port)
736 adapter->stop_port(adapter); 815 adapter->stop_port(adapter);
737 816
738 netxen_nic_disable_int(adapter);
739
740 netxen_release_tx_buffers(adapter); 817 netxen_release_tx_buffers(adapter);
741 818
742 FLUSH_SCHEDULED_WORK(); 819 FLUSH_SCHEDULED_WORK();
@@ -750,6 +827,7 @@ netxen_nic_attach(struct netxen_adapter *adapter)
750 struct net_device *netdev = adapter->netdev; 827 struct net_device *netdev = adapter->netdev;
751 struct pci_dev *pdev = adapter->pdev; 828 struct pci_dev *pdev = adapter->pdev;
752 int err, ring; 829 int err, ring;
830 struct nx_host_rds_ring *rds_ring;
753 831
754 err = netxen_init_firmware(adapter); 832 err = netxen_init_firmware(adapter);
755 if (err != 0) { 833 if (err != 0) {
@@ -788,8 +866,10 @@ netxen_nic_attach(struct netxen_adapter *adapter)
788 netxen_nic_update_cmd_consumer(adapter, 0); 866 netxen_nic_update_cmd_consumer(adapter, 0);
789 } 867 }
790 868
791 for (ring = 0; ring < adapter->max_rds_rings; ring++) 869 for (ring = 0; ring < adapter->max_rds_rings; ring++) {
792 netxen_post_rx_buffers(adapter, ring); 870 rds_ring = &adapter->recv_ctx.rds_rings[ring];
871 netxen_post_rx_buffers(adapter, ring, rds_ring);
872 }
793 873
794 err = netxen_nic_request_irq(adapter); 874 err = netxen_nic_request_irq(adapter);
795 if (err) { 875 if (err) {
@@ -812,8 +892,7 @@ err_out_free_sw:
812static void 892static void
813netxen_nic_detach(struct netxen_adapter *adapter) 893netxen_nic_detach(struct netxen_adapter *adapter)
814{ 894{
815 if (adapter->irq) 895 netxen_nic_free_irq(adapter);
816 free_irq(adapter->irq, adapter);
817 896
818 netxen_release_rx_buffers(adapter); 897 netxen_release_rx_buffers(adapter);
819 netxen_free_hw_resources(adapter); 898 netxen_free_hw_resources(adapter);
@@ -883,14 +962,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
883 goto err_out_free_netdev; 962 goto err_out_free_netdev;
884 963
885 rwlock_init(&adapter->adapter_lock); 964 rwlock_init(&adapter->adapter_lock);
965 spin_lock_init(&adapter->tx_clean_lock);
886 966
887 err = netxen_setup_pci_map(adapter); 967 err = netxen_setup_pci_map(adapter);
888 if (err) 968 if (err)
889 goto err_out_free_netdev; 969 goto err_out_free_netdev;
890 970
891 netif_napi_add(netdev, &adapter->napi,
892 netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
893
894 /* This will be reset for mezz cards */ 971 /* This will be reset for mezz cards */
895 adapter->portnum = pci_func_id; 972 adapter->portnum = pci_func_id;
896 adapter->rx_csum = 1; 973 adapter->rx_csum = 1;
@@ -963,10 +1040,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
963 1040
964 netxen_setup_intr(adapter); 1041 netxen_setup_intr(adapter);
965 1042
966 if (adapter->flags & NETXEN_NIC_MSIX_ENABLED) 1043 netdev->irq = adapter->msix_entries[0].vector;
967 netdev->irq = adapter->msix_entries[0].vector; 1044
968 else 1045 netxen_napi_add(adapter, netdev);
969 netdev->irq = pdev->irq;
970 1046
971 err = netxen_receive_peg_ready(adapter); 1047 err = netxen_receive_peg_ready(adapter);
972 if (err) 1048 if (err)
@@ -1520,13 +1596,11 @@ static void netxen_tx_timeout_task(struct work_struct *work)
1520 printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", 1596 printk(KERN_ERR "%s %s: transmit timeout, resetting.\n",
1521 netxen_nic_driver_name, adapter->netdev->name); 1597 netxen_nic_driver_name, adapter->netdev->name);
1522 1598
1523 netxen_nic_disable_int(adapter); 1599 netxen_napi_disable(adapter);
1524 napi_disable(&adapter->napi);
1525 1600
1526 adapter->netdev->trans_start = jiffies; 1601 adapter->netdev->trans_start = jiffies;
1527 1602
1528 napi_enable(&adapter->napi); 1603 netxen_napi_enable(adapter);
1529 netxen_nic_enable_int(adapter);
1530 netif_wake_queue(adapter->netdev); 1604 netif_wake_queue(adapter->netdev);
1531} 1605}
1532 1606
@@ -1564,7 +1638,8 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
1564 1638
1565static irqreturn_t netxen_intr(int irq, void *data) 1639static irqreturn_t netxen_intr(int irq, void *data)
1566{ 1640{
1567 struct netxen_adapter *adapter = data; 1641 struct nx_host_sds_ring *sds_ring = data;
1642 struct netxen_adapter *adapter = sds_ring->adapter;
1568 u32 status = 0; 1643 u32 status = 0;
1569 1644
1570 status = adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); 1645 status = adapter->pci_read_immediate(adapter, ISR_INT_VECTOR);
@@ -1595,7 +1670,7 @@ static irqreturn_t netxen_intr(int irq, void *data)
1595 1670
1596 /* clear interrupt */ 1671 /* clear interrupt */
1597 if (adapter->fw_major < 4) 1672 if (adapter->fw_major < 4)
1598 netxen_nic_disable_int(adapter); 1673 netxen_nic_disable_int(sds_ring);
1599 1674
1600 adapter->pci_write_immediate(adapter, 1675 adapter->pci_write_immediate(adapter,
1601 adapter->legacy_intr.tgt_status_reg, 1676 adapter->legacy_intr.tgt_status_reg,
@@ -1604,45 +1679,49 @@ static irqreturn_t netxen_intr(int irq, void *data)
1604 adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); 1679 adapter->pci_read_immediate(adapter, ISR_INT_VECTOR);
1605 adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); 1680 adapter->pci_read_immediate(adapter, ISR_INT_VECTOR);
1606 1681
1607 napi_schedule(&adapter->napi); 1682 napi_schedule(&sds_ring->napi);
1608 1683
1609 return IRQ_HANDLED; 1684 return IRQ_HANDLED;
1610} 1685}
1611 1686
1612static irqreturn_t netxen_msi_intr(int irq, void *data) 1687static irqreturn_t netxen_msi_intr(int irq, void *data)
1613{ 1688{
1614 struct netxen_adapter *adapter = data; 1689 struct nx_host_sds_ring *sds_ring = data;
1690 struct netxen_adapter *adapter = sds_ring->adapter;
1615 1691
1616 /* clear interrupt */ 1692 /* clear interrupt */
1617 adapter->pci_write_immediate(adapter, 1693 adapter->pci_write_immediate(adapter,
1618 msi_tgt_status[adapter->ahw.pci_func], 0xffffffff); 1694 msi_tgt_status[adapter->ahw.pci_func], 0xffffffff);
1619 1695
1620 napi_schedule(&adapter->napi); 1696 napi_schedule(&sds_ring->napi);
1621 return IRQ_HANDLED; 1697 return IRQ_HANDLED;
1622} 1698}
1623 1699
1624static irqreturn_t netxen_msix_intr(int irq, void *data) 1700static irqreturn_t netxen_msix_intr(int irq, void *data)
1625{ 1701{
1626 struct netxen_adapter *adapter = data; 1702 struct nx_host_sds_ring *sds_ring = data;
1627 1703
1628 napi_schedule(&adapter->napi); 1704 napi_schedule(&sds_ring->napi);
1629 return IRQ_HANDLED; 1705 return IRQ_HANDLED;
1630} 1706}
1631 1707
1632static int netxen_nic_poll(struct napi_struct *napi, int budget) 1708static int netxen_nic_poll(struct napi_struct *napi, int budget)
1633{ 1709{
1634 struct netxen_adapter *adapter = 1710 struct nx_host_sds_ring *sds_ring =
1635 container_of(napi, struct netxen_adapter, napi); 1711 container_of(napi, struct nx_host_sds_ring, napi);
1712
1713 struct netxen_adapter *adapter = sds_ring->adapter;
1714
1636 int tx_complete; 1715 int tx_complete;
1637 int work_done; 1716 int work_done;
1638 1717
1639 tx_complete = netxen_process_cmd_ring(adapter); 1718 tx_complete = netxen_process_cmd_ring(adapter);
1640 1719
1641 work_done = netxen_process_rcv_ring(adapter, budget); 1720 work_done = netxen_process_rcv_ring(sds_ring, budget);
1642 1721
1643 if ((work_done < budget) && tx_complete) { 1722 if ((work_done < budget) && tx_complete) {
1644 napi_complete(&adapter->napi); 1723 napi_complete(&sds_ring->napi);
1645 netxen_nic_enable_int(adapter); 1724 netxen_nic_enable_int(sds_ring);
1646 } 1725 }
1647 1726
1648 return work_done; 1727 return work_done;