diff options
-rw-r--r-- | drivers/net/e1000/e1000.h | 26 | ||||
-rw-r--r-- | drivers/net/e1000/e1000_ethtool.c | 65 | ||||
-rw-r--r-- | drivers/net/e1000/e1000_main.c | 47 |
3 files changed, 120 insertions, 18 deletions
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 5940f7a223bc..0a084e915dd6 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h | |||
@@ -72,10 +72,6 @@ | |||
72 | #include <linux/mii.h> | 72 | #include <linux/mii.h> |
73 | #include <linux/ethtool.h> | 73 | #include <linux/ethtool.h> |
74 | #include <linux/if_vlan.h> | 74 | #include <linux/if_vlan.h> |
75 | #ifdef CONFIG_E1000_MQ | ||
76 | #include <linux/cpu.h> | ||
77 | #include <linux/smp.h> | ||
78 | #endif | ||
79 | 75 | ||
80 | #define BAR_0 0 | 76 | #define BAR_0 0 |
81 | #define BAR_1 1 | 77 | #define BAR_1 1 |
@@ -87,6 +83,10 @@ | |||
87 | struct e1000_adapter; | 83 | struct e1000_adapter; |
88 | 84 | ||
89 | #include "e1000_hw.h" | 85 | #include "e1000_hw.h" |
86 | #ifdef CONFIG_E1000_MQ | ||
87 | #include <linux/cpu.h> | ||
88 | #include <linux/smp.h> | ||
89 | #endif | ||
90 | 90 | ||
91 | #ifdef DBG | 91 | #ifdef DBG |
92 | #define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args) | 92 | #define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args) |
@@ -169,6 +169,13 @@ struct e1000_buffer { | |||
169 | uint16_t next_to_watch; | 169 | uint16_t next_to_watch; |
170 | }; | 170 | }; |
171 | 171 | ||
172 | #ifdef CONFIG_E1000_MQ | ||
173 | struct e1000_queue_stats { | ||
174 | uint64_t packets; | ||
175 | uint64_t bytes; | ||
176 | }; | ||
177 | #endif | ||
178 | |||
172 | struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; }; | 179 | struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; }; |
173 | struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; }; | 180 | struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; }; |
174 | 181 | ||
@@ -194,6 +201,9 @@ struct e1000_tx_ring { | |||
194 | 201 | ||
195 | boolean_t last_tx_tso; | 202 | boolean_t last_tx_tso; |
196 | 203 | ||
204 | #ifdef CONFIG_E1000_MQ | ||
205 | struct e1000_queue_stats tx_stats; | ||
206 | #endif | ||
197 | }; | 207 | }; |
198 | 208 | ||
199 | struct e1000_rx_ring { | 209 | struct e1000_rx_ring { |
@@ -223,6 +233,9 @@ struct e1000_rx_ring { | |||
223 | 233 | ||
224 | uint16_t rdh; | 234 | uint16_t rdh; |
225 | uint16_t rdt; | 235 | uint16_t rdt; |
236 | #ifdef CONFIG_E1000_MQ | ||
237 | struct e1000_queue_stats rx_stats; | ||
238 | #endif | ||
226 | }; | 239 | }; |
227 | 240 | ||
228 | #define E1000_DESC_UNUSED(R) \ | 241 | #define E1000_DESC_UNUSED(R) \ |
@@ -255,6 +268,9 @@ struct e1000_adapter { | |||
255 | uint16_t link_speed; | 268 | uint16_t link_speed; |
256 | uint16_t link_duplex; | 269 | uint16_t link_duplex; |
257 | spinlock_t stats_lock; | 270 | spinlock_t stats_lock; |
271 | #ifdef CONFIG_E1000_NAPI | ||
272 | spinlock_t tx_queue_lock; | ||
273 | #endif | ||
258 | atomic_t irq_sem; | 274 | atomic_t irq_sem; |
259 | struct work_struct tx_timeout_task; | 275 | struct work_struct tx_timeout_task; |
260 | struct work_struct watchdog_task; | 276 | struct work_struct watchdog_task; |
@@ -302,7 +318,7 @@ struct e1000_adapter { | |||
302 | #ifdef CONFIG_E1000_MQ | 318 | #ifdef CONFIG_E1000_MQ |
303 | struct net_device **cpu_netdev; /* per-cpu */ | 319 | struct net_device **cpu_netdev; /* per-cpu */ |
304 | struct call_async_data_struct rx_sched_call_data; | 320 | struct call_async_data_struct rx_sched_call_data; |
305 | int cpu_for_queue[4]; | 321 | cpumask_t cpumask; |
306 | #endif | 322 | #endif |
307 | int num_tx_queues; | 323 | int num_tx_queues; |
308 | int num_rx_queues; | 324 | int num_rx_queues; |
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index fa9a4659369a..ffdf76b725bc 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c | |||
@@ -96,8 +96,18 @@ static const struct e1000_stats e1000_gstrings_stats[] = { | |||
96 | { "rx_header_split", E1000_STAT(rx_hdr_split) }, | 96 | { "rx_header_split", E1000_STAT(rx_hdr_split) }, |
97 | { "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) }, | 97 | { "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) }, |
98 | }; | 98 | }; |
99 | #define E1000_STATS_LEN \ | 99 | |
100 | #ifdef CONFIG_E1000_MQ | ||
101 | #define E1000_QUEUE_STATS_LEN \ | ||
102 | (((struct e1000_adapter *)netdev->priv)->num_tx_queues + \ | ||
103 | ((struct e1000_adapter *)netdev->priv)->num_rx_queues) \ | ||
104 | * (sizeof(struct e1000_queue_stats) / sizeof(uint64_t)) | ||
105 | #else | ||
106 | #define E1000_QUEUE_STATS_LEN 0 | ||
107 | #endif | ||
108 | #define E1000_GLOBAL_STATS_LEN \ | ||
100 | sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats) | 109 | sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats) |
110 | #define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN + E1000_QUEUE_STATS_LEN) | ||
101 | static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = { | 111 | static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = { |
102 | "Register test (offline)", "Eeprom test (offline)", | 112 | "Register test (offline)", "Eeprom test (offline)", |
103 | "Interrupt test (offline)", "Loopback test (offline)", | 113 | "Interrupt test (offline)", "Loopback test (offline)", |
@@ -1746,19 +1756,43 @@ e1000_get_ethtool_stats(struct net_device *netdev, | |||
1746 | struct ethtool_stats *stats, uint64_t *data) | 1756 | struct ethtool_stats *stats, uint64_t *data) |
1747 | { | 1757 | { |
1748 | struct e1000_adapter *adapter = netdev_priv(netdev); | 1758 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1759 | #ifdef CONFIG_E1000_MQ | ||
1760 | uint64_t *queue_stat; | ||
1761 | int stat_count = sizeof(struct e1000_queue_stats) / sizeof(uint64_t); | ||
1762 | int j, k; | ||
1763 | #endif | ||
1749 | int i; | 1764 | int i; |
1750 | 1765 | ||
1751 | e1000_update_stats(adapter); | 1766 | e1000_update_stats(adapter); |
1752 | for(i = 0; i < E1000_STATS_LEN; i++) { | 1767 | for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { |
1753 | char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset; | 1768 | char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset; |
1754 | data[i] = (e1000_gstrings_stats[i].sizeof_stat == | 1769 | data[i] = (e1000_gstrings_stats[i].sizeof_stat == |
1755 | sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p; | 1770 | sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p; |
1756 | } | 1771 | } |
1772 | #ifdef CONFIG_E1000_MQ | ||
1773 | for (j = 0; j < adapter->num_tx_queues; j++) { | ||
1774 | queue_stat = (uint64_t *)&adapter->tx_ring[j].tx_stats; | ||
1775 | for (k = 0; k < stat_count; k++) | ||
1776 | data[i + k] = queue_stat[k]; | ||
1777 | i += k; | ||
1778 | } | ||
1779 | for (j = 0; j < adapter->num_rx_queues; j++) { | ||
1780 | queue_stat = (uint64_t *)&adapter->rx_ring[j].rx_stats; | ||
1781 | for (k = 0; k < stat_count; k++) | ||
1782 | data[i + k] = queue_stat[k]; | ||
1783 | i += k; | ||
1784 | } | ||
1785 | #endif | ||
1786 | /* BUG_ON(i != E1000_STATS_LEN); */ | ||
1757 | } | 1787 | } |
1758 | 1788 | ||
1759 | static void | 1789 | static void |
1760 | e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) | 1790 | e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) |
1761 | { | 1791 | { |
1792 | #ifdef CONFIG_E1000_MQ | ||
1793 | struct e1000_adapter *adapter = netdev_priv(netdev); | ||
1794 | #endif | ||
1795 | uint8_t *p = data; | ||
1762 | int i; | 1796 | int i; |
1763 | 1797 | ||
1764 | switch(stringset) { | 1798 | switch(stringset) { |
@@ -1767,11 +1801,26 @@ e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) | |||
1767 | E1000_TEST_LEN*ETH_GSTRING_LEN); | 1801 | E1000_TEST_LEN*ETH_GSTRING_LEN); |
1768 | break; | 1802 | break; |
1769 | case ETH_SS_STATS: | 1803 | case ETH_SS_STATS: |
1770 | for (i=0; i < E1000_STATS_LEN; i++) { | 1804 | for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { |
1771 | memcpy(data + i * ETH_GSTRING_LEN, | 1805 | memcpy(p, e1000_gstrings_stats[i].stat_string, |
1772 | e1000_gstrings_stats[i].stat_string, | 1806 | ETH_GSTRING_LEN); |
1773 | ETH_GSTRING_LEN); | 1807 | p += ETH_GSTRING_LEN; |
1808 | } | ||
1809 | #ifdef CONFIG_E1000_MQ | ||
1810 | for (i = 0; i < adapter->num_tx_queues; i++) { | ||
1811 | sprintf(p, "tx_queue_%u_packets", i); | ||
1812 | p += ETH_GSTRING_LEN; | ||
1813 | sprintf(p, "tx_queue_%u_bytes", i); | ||
1814 | p += ETH_GSTRING_LEN; | ||
1774 | } | 1815 | } |
1816 | for (i = 0; i < adapter->num_rx_queues; i++) { | ||
1817 | sprintf(p, "rx_queue_%u_packets", i); | ||
1818 | p += ETH_GSTRING_LEN; | ||
1819 | sprintf(p, "rx_queue_%u_bytes", i); | ||
1820 | p += ETH_GSTRING_LEN; | ||
1821 | } | ||
1822 | #endif | ||
1823 | /* BUG_ON(p - data != E1000_STATS_LEN * ETH_GSTRING_LEN); */ | ||
1775 | break; | 1824 | break; |
1776 | } | 1825 | } |
1777 | } | 1826 | } |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 540c8561fc24..4016264a7919 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -433,6 +433,12 @@ e1000_up(struct e1000_adapter *adapter) | |||
433 | return err; | 433 | return err; |
434 | } | 434 | } |
435 | 435 | ||
436 | #ifdef CONFIG_E1000_MQ | ||
437 | e1000_setup_queue_mapping(adapter); | ||
438 | #endif | ||
439 | |||
440 | adapter->tx_queue_len = netdev->tx_queue_len; | ||
441 | |||
436 | mod_timer(&adapter->watchdog_timer, jiffies); | 442 | mod_timer(&adapter->watchdog_timer, jiffies); |
437 | 443 | ||
438 | #ifdef CONFIG_E1000_NAPI | 444 | #ifdef CONFIG_E1000_NAPI |
@@ -467,6 +473,7 @@ e1000_down(struct e1000_adapter *adapter) | |||
467 | #ifdef CONFIG_E1000_NAPI | 473 | #ifdef CONFIG_E1000_NAPI |
468 | netif_poll_disable(netdev); | 474 | netif_poll_disable(netdev); |
469 | #endif | 475 | #endif |
476 | netdev->tx_queue_len = adapter->tx_queue_len; | ||
470 | adapter->link_speed = 0; | 477 | adapter->link_speed = 0; |
471 | adapter->link_duplex = 0; | 478 | adapter->link_duplex = 0; |
472 | netif_carrier_off(netdev); | 479 | netif_carrier_off(netdev); |
@@ -989,6 +996,15 @@ e1000_sw_init(struct e1000_adapter *adapter) | |||
989 | } | 996 | } |
990 | adapter->num_rx_queues = min(adapter->num_rx_queues, num_online_cpus()); | 997 | adapter->num_rx_queues = min(adapter->num_rx_queues, num_online_cpus()); |
991 | adapter->num_tx_queues = min(adapter->num_tx_queues, num_online_cpus()); | 998 | adapter->num_tx_queues = min(adapter->num_tx_queues, num_online_cpus()); |
999 | DPRINTK(DRV, INFO, "Multiqueue Enabled: Rx Queue count = %u %s\n", | ||
1000 | adapter->num_rx_queues, | ||
1001 | ((adapter->num_rx_queues == 1) | ||
1002 | ? ((num_online_cpus() > 1) | ||
1003 | ? "(due to unsupported feature in current adapter)" | ||
1004 | : "(due to unsupported system configuration)") | ||
1005 | : "")); | ||
1006 | DPRINTK(DRV, INFO, "Multiqueue Enabled: Tx Queue count = %u\n", | ||
1007 | adapter->num_tx_queues); | ||
992 | #else | 1008 | #else |
993 | adapter->num_tx_queues = 1; | 1009 | adapter->num_tx_queues = 1; |
994 | adapter->num_rx_queues = 1; | 1010 | adapter->num_rx_queues = 1; |
@@ -1007,10 +1023,7 @@ e1000_sw_init(struct e1000_adapter *adapter) | |||
1007 | dev_hold(&adapter->polling_netdev[i]); | 1023 | dev_hold(&adapter->polling_netdev[i]); |
1008 | set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state); | 1024 | set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state); |
1009 | } | 1025 | } |
1010 | #endif | 1026 | spin_lock_init(&adapter->tx_queue_lock); |
1011 | |||
1012 | #ifdef CONFIG_E1000_MQ | ||
1013 | e1000_setup_queue_mapping(adapter); | ||
1014 | #endif | 1027 | #endif |
1015 | 1028 | ||
1016 | atomic_set(&adapter->irq_sem, 1); | 1029 | atomic_set(&adapter->irq_sem, 1); |
@@ -1058,6 +1071,14 @@ e1000_alloc_queues(struct e1000_adapter *adapter) | |||
1058 | memset(adapter->polling_netdev, 0, size); | 1071 | memset(adapter->polling_netdev, 0, size); |
1059 | #endif | 1072 | #endif |
1060 | 1073 | ||
1074 | #ifdef CONFIG_E1000_MQ | ||
1075 | adapter->rx_sched_call_data.func = e1000_rx_schedule; | ||
1076 | adapter->rx_sched_call_data.info = adapter->netdev; | ||
1077 | |||
1078 | adapter->cpu_netdev = alloc_percpu(struct net_device *); | ||
1079 | adapter->cpu_tx_ring = alloc_percpu(struct e1000_tx_ring *); | ||
1080 | #endif | ||
1081 | |||
1061 | return E1000_SUCCESS; | 1082 | return E1000_SUCCESS; |
1062 | } | 1083 | } |
1063 | 1084 | ||
@@ -1084,7 +1105,8 @@ e1000_setup_queue_mapping(struct e1000_adapter *adapter) | |||
1084 | */ | 1105 | */ |
1085 | if (i < adapter->num_rx_queues) { | 1106 | if (i < adapter->num_rx_queues) { |
1086 | *per_cpu_ptr(adapter->cpu_netdev, cpu) = &adapter->polling_netdev[i]; | 1107 | *per_cpu_ptr(adapter->cpu_netdev, cpu) = &adapter->polling_netdev[i]; |
1087 | adapter->cpu_for_queue[i] = cpu; | 1108 | adapter->rx_ring[i].cpu = cpu; |
1109 | cpu_set(cpu, adapter->cpumask); | ||
1088 | } else | 1110 | } else |
1089 | *per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL; | 1111 | *per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL; |
1090 | 1112 | ||
@@ -3337,6 +3359,10 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, | |||
3337 | if(unlikely(++i == tx_ring->count)) i = 0; | 3359 | if(unlikely(++i == tx_ring->count)) i = 0; |
3338 | } | 3360 | } |
3339 | 3361 | ||
3362 | #ifdef CONFIG_E1000_MQ | ||
3363 | tx_ring->tx_stats.packets++; | ||
3364 | #endif | ||
3365 | |||
3340 | eop = tx_ring->buffer_info[i].next_to_watch; | 3366 | eop = tx_ring->buffer_info[i].next_to_watch; |
3341 | eop_desc = E1000_TX_DESC(*tx_ring, eop); | 3367 | eop_desc = E1000_TX_DESC(*tx_ring, eop); |
3342 | } | 3368 | } |
@@ -3365,6 +3391,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, | |||
3365 | eop = tx_ring->buffer_info[i].next_to_watch; | 3391 | eop = tx_ring->buffer_info[i].next_to_watch; |
3366 | eop_desc = E1000_TX_DESC(*tx_ring, eop); | 3392 | eop_desc = E1000_TX_DESC(*tx_ring, eop); |
3367 | DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" | 3393 | DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" |
3394 | " Tx Queue <%lu>\n" | ||
3368 | " TDH <%x>\n" | 3395 | " TDH <%x>\n" |
3369 | " TDT <%x>\n" | 3396 | " TDT <%x>\n" |
3370 | " next_to_use <%x>\n" | 3397 | " next_to_use <%x>\n" |
@@ -3375,6 +3402,8 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, | |||
3375 | " next_to_watch <%x>\n" | 3402 | " next_to_watch <%x>\n" |
3376 | " jiffies <%lx>\n" | 3403 | " jiffies <%lx>\n" |
3377 | " next_to_watch.status <%x>\n", | 3404 | " next_to_watch.status <%x>\n", |
3405 | (unsigned long)((tx_ring - adapter->tx_ring) / | ||
3406 | sizeof(struct e1000_tx_ring)), | ||
3378 | readl(adapter->hw.hw_addr + tx_ring->tdh), | 3407 | readl(adapter->hw.hw_addr + tx_ring->tdh), |
3379 | readl(adapter->hw.hw_addr + tx_ring->tdt), | 3408 | readl(adapter->hw.hw_addr + tx_ring->tdt), |
3380 | tx_ring->next_to_use, | 3409 | tx_ring->next_to_use, |
@@ -3541,6 +3570,10 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, | |||
3541 | } | 3570 | } |
3542 | #endif /* CONFIG_E1000_NAPI */ | 3571 | #endif /* CONFIG_E1000_NAPI */ |
3543 | netdev->last_rx = jiffies; | 3572 | netdev->last_rx = jiffies; |
3573 | #ifdef CONFIG_E1000_MQ | ||
3574 | rx_ring->rx_stats.packets++; | ||
3575 | rx_ring->rx_stats.bytes += length; | ||
3576 | #endif | ||
3544 | 3577 | ||
3545 | next_desc: | 3578 | next_desc: |
3546 | rx_desc->status = 0; | 3579 | rx_desc->status = 0; |
@@ -3671,6 +3704,10 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, | |||
3671 | } | 3704 | } |
3672 | #endif /* CONFIG_E1000_NAPI */ | 3705 | #endif /* CONFIG_E1000_NAPI */ |
3673 | netdev->last_rx = jiffies; | 3706 | netdev->last_rx = jiffies; |
3707 | #ifdef CONFIG_E1000_MQ | ||
3708 | rx_ring->rx_stats.packets++; | ||
3709 | rx_ring->rx_stats.bytes += length; | ||
3710 | #endif | ||
3674 | 3711 | ||
3675 | next_desc: | 3712 | next_desc: |
3676 | rx_desc->wb.middle.status_error &= ~0xFF; | 3713 | rx_desc->wb.middle.status_error &= ~0xFF; |