aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/cisco/enic/enic.h27
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c72
2 files changed, 99 insertions, 0 deletions
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index 6401ba99457f..1671fa3332c2 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -50,6 +50,7 @@ struct enic_msix_entry {
50 char devname[IFNAMSIZ]; 50 char devname[IFNAMSIZ];
51 irqreturn_t (*isr)(int, void *); 51 irqreturn_t (*isr)(int, void *);
52 void *devid; 52 void *devid;
53 cpumask_var_t affinity_mask;
53}; 54};
54 55
55/* Store only the lower range. Higher range is given by fw. */ 56/* Store only the lower range. Higher range is given by fw. */
@@ -263,6 +264,32 @@ static inline unsigned int enic_msix_notify_intr(struct enic *enic)
263 return enic->rq_count + enic->wq_count + 1; 264 return enic->rq_count + enic->wq_count + 1;
264} 265}
265 266
267static inline bool enic_is_err_intr(struct enic *enic, int intr)
268{
269 switch (vnic_dev_get_intr_mode(enic->vdev)) {
270 case VNIC_DEV_INTR_MODE_INTX:
271 return intr == enic_legacy_err_intr();
272 case VNIC_DEV_INTR_MODE_MSIX:
273 return intr == enic_msix_err_intr(enic);
274 case VNIC_DEV_INTR_MODE_MSI:
275 default:
276 return false;
277 }
278}
279
280static inline bool enic_is_notify_intr(struct enic *enic, int intr)
281{
282 switch (vnic_dev_get_intr_mode(enic->vdev)) {
283 case VNIC_DEV_INTR_MODE_INTX:
284 return intr == enic_legacy_notify_intr();
285 case VNIC_DEV_INTR_MODE_MSIX:
286 return intr == enic_msix_notify_intr(enic);
287 case VNIC_DEV_INTR_MODE_MSI:
288 default:
289 return false;
290 }
291}
292
266static inline int enic_dma_map_check(struct enic *enic, dma_addr_t dma_addr) 293static inline int enic_dma_map_check(struct enic *enic, dma_addr_t dma_addr)
267{ 294{
268 if (unlikely(pci_dma_mapping_error(enic->pdev, dma_addr))) { 295 if (unlikely(pci_dma_mapping_error(enic->pdev, dma_addr))) {
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 0c22fd014378..b36643ef0593 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -39,6 +39,7 @@
39#include <linux/prefetch.h> 39#include <linux/prefetch.h>
40#include <net/ip6_checksum.h> 40#include <net/ip6_checksum.h>
41#include <linux/ktime.h> 41#include <linux/ktime.h>
42#include <linux/numa.h>
42#ifdef CONFIG_RFS_ACCEL 43#ifdef CONFIG_RFS_ACCEL
43#include <linux/cpu_rmap.h> 44#include <linux/cpu_rmap.h>
44#endif 45#endif
@@ -112,6 +113,71 @@ static struct enic_intr_mod_range mod_range[ENIC_MAX_LINK_SPEEDS] = {
112 {3, 6}, /* 10 - 40 Gbps */ 113 {3, 6}, /* 10 - 40 Gbps */
113}; 114};
114 115
116static void enic_init_affinity_hint(struct enic *enic)
117{
118 int numa_node = dev_to_node(&enic->pdev->dev);
119 int i;
120
121 for (i = 0; i < enic->intr_count; i++) {
122 if (enic_is_err_intr(enic, i) || enic_is_notify_intr(enic, i) ||
123 (enic->msix[i].affinity_mask &&
124 !cpumask_empty(enic->msix[i].affinity_mask)))
125 continue;
126 if (zalloc_cpumask_var(&enic->msix[i].affinity_mask,
127 GFP_KERNEL))
128 cpumask_set_cpu(cpumask_local_spread(i, numa_node),
129 enic->msix[i].affinity_mask);
130 }
131}
132
133static void enic_free_affinity_hint(struct enic *enic)
134{
135 int i;
136
137 for (i = 0; i < enic->intr_count; i++) {
138 if (enic_is_err_intr(enic, i) || enic_is_notify_intr(enic, i))
139 continue;
140 free_cpumask_var(enic->msix[i].affinity_mask);
141 }
142}
143
144static void enic_set_affinity_hint(struct enic *enic)
145{
146 int i;
147 int err;
148
149 for (i = 0; i < enic->intr_count; i++) {
150 if (enic_is_err_intr(enic, i) ||
151 enic_is_notify_intr(enic, i) ||
152 !enic->msix[i].affinity_mask ||
153 cpumask_empty(enic->msix[i].affinity_mask))
154 continue;
155 err = irq_set_affinity_hint(enic->msix_entry[i].vector,
156 enic->msix[i].affinity_mask);
157 if (err)
158 netdev_warn(enic->netdev, "irq_set_affinity_hint failed, err %d\n",
159 err);
160 }
161
162 for (i = 0; i < enic->wq_count; i++) {
163 int wq_intr = enic_msix_wq_intr(enic, i);
164
165 if (enic->msix[wq_intr].affinity_mask &&
166 !cpumask_empty(enic->msix[wq_intr].affinity_mask))
167 netif_set_xps_queue(enic->netdev,
168 enic->msix[wq_intr].affinity_mask,
169 i);
170 }
171}
172
173static void enic_unset_affinity_hint(struct enic *enic)
174{
175 int i;
176
177 for (i = 0; i < enic->intr_count; i++)
178 irq_set_affinity_hint(enic->msix_entry[i].vector, NULL);
179}
180
115int enic_is_dynamic(struct enic *enic) 181int enic_is_dynamic(struct enic *enic)
116{ 182{
117 return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN; 183 return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN;
@@ -1649,6 +1715,8 @@ static int enic_open(struct net_device *netdev)
1649 netdev_err(netdev, "Unable to request irq.\n"); 1715 netdev_err(netdev, "Unable to request irq.\n");
1650 return err; 1716 return err;
1651 } 1717 }
1718 enic_init_affinity_hint(enic);
1719 enic_set_affinity_hint(enic);
1652 1720
1653 err = enic_dev_notify_set(enic); 1721 err = enic_dev_notify_set(enic);
1654 if (err) { 1722 if (err) {
@@ -1701,6 +1769,7 @@ err_out_free_rq:
1701 vnic_rq_clean(&enic->rq[i], enic_free_rq_buf); 1769 vnic_rq_clean(&enic->rq[i], enic_free_rq_buf);
1702 enic_dev_notify_unset(enic); 1770 enic_dev_notify_unset(enic);
1703err_out_free_intr: 1771err_out_free_intr:
1772 enic_unset_affinity_hint(enic);
1704 enic_free_intr(enic); 1773 enic_free_intr(enic);
1705 1774
1706 return err; 1775 return err;
@@ -1754,6 +1823,7 @@ static int enic_stop(struct net_device *netdev)
1754 } 1823 }
1755 1824
1756 enic_dev_notify_unset(enic); 1825 enic_dev_notify_unset(enic);
1826 enic_unset_affinity_hint(enic);
1757 enic_free_intr(enic); 1827 enic_free_intr(enic);
1758 1828
1759 for (i = 0; i < enic->wq_count; i++) 1829 for (i = 0; i < enic->wq_count; i++)
@@ -2309,6 +2379,7 @@ static void enic_dev_deinit(struct enic *enic)
2309 2379
2310 enic_free_vnic_resources(enic); 2380 enic_free_vnic_resources(enic);
2311 enic_clear_intr_mode(enic); 2381 enic_clear_intr_mode(enic);
2382 enic_free_affinity_hint(enic);
2312} 2383}
2313 2384
2314static void enic_kdump_kernel_config(struct enic *enic) 2385static void enic_kdump_kernel_config(struct enic *enic)
@@ -2404,6 +2475,7 @@ static int enic_dev_init(struct enic *enic)
2404 return 0; 2475 return 0;
2405 2476
2406err_out_free_vnic_resources: 2477err_out_free_vnic_resources:
2478 enic_free_affinity_hint(enic);
2407 enic_clear_intr_mode(enic); 2479 enic_clear_intr_mode(enic);
2408 enic_free_vnic_resources(enic); 2480 enic_free_vnic_resources(enic);
2409 2481