Multique Fixes - Added ethtool stats for multiple queues - Added printout for an indication that mutliqueue is enabled/disabled - Fixed receive issue where tasks were not being assigned a cpu
Signed-off-by: Jeff Kirsher <[EMAIL PROTECTED]> Signed-off-by: John Ronciak <[EMAIL PROTECTED]> Signed-off-by: Jesse Brandeburg <[EMAIL PROTECTED]> diff -up linux-2.6/drivers/net/e1000/e1000.h linux-2.6.new/drivers/net/e1000/e1000.h --- linux-2.6/drivers/net/e1000/e1000.h 2005-11-14 16:20:34.000000000 -0800 +++ linux-2.6.new/drivers/net/e1000/e1000.h 2005-11-04 01:23:40.000000000 -0800 @@ -72,10 +72,6 @@ #include <linux/mii.h> #include <linux/ethtool.h> #include <linux/if_vlan.h> -#ifdef CONFIG_E1000_MQ -#include <linux/cpu.h> -#include <linux/smp.h> -#endif #define BAR_0 0 #define BAR_1 1 @@ -87,6 +87,10 @@ struct e1000_adapter; #include "e1000_hw.h" +#ifdef CONFIG_E1000_MQ +#include <linux/cpu.h> +#include <linux/smp.h> +#endif #ifdef DBG #define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args) @@ -169,6 +169,13 @@ struct e1000_buffer { uint16_t next_to_watch; }; +#ifdef CONFIG_E1000_MQ +struct e1000_queue_stats { + uint64_t packets; + uint64_t bytes; +}; +#endif + struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; }; struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; }; @@ -191,10 +189,12 @@ struct e1000_tx_ring { spinlock_t tx_lock; uint16_t tdh; uint16_t tdt; - uint64_t pkt; boolean_t last_tx_tso; +#ifdef CONFIG_E1000_MQ + struct e1000_queue_stats tx_stats; +#endif }; struct e1000_rx_ring { @@ -224,7 +215,9 @@ struct e1000_rx_ring { uint16_t rdh; uint16_t rdt; - uint64_t pkt; +#ifdef CONFIG_E1000_MQ + struct e1000_queue_stats rx_stats; +#endif }; #define E1000_DESC_UNUSED(R) \ @@ -306,7 +294,6 @@ struct e1000_adapter { #ifdef CONFIG_E1000_MQ struct net_device **cpu_netdev; /* per-cpu */ struct call_async_data_struct rx_sched_call_data; - int cpu_for_queue[4]; #endif int num_queues; diff -up linux-2.6/drivers/net/e1000/e1000_ethtool.c linux-2.6.new/drivers/net/e1000/e1000_ethtool.c --- linux-2.6/drivers/net/e1000/e1000_ethtool.c 2005-11-14 16:20:34.000000000 -0800 +++ linux-2.6.new/drivers/net/e1000/e1000_ethtool.c 2005-11-04 01:23:40.000000000 -0800 @@ -96,8 +96,17 @@ static const struct e1000_stats e1000_gs { "rx_header_split", E1000_STAT(rx_hdr_split) }, { "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) }, }; -#define E1000_STATS_LEN \ + +#ifdef CONFIG_E1000_MQ +#define E1000_QUEUE_STATS_LEN \ + (((struct e1000_adapter *)netdev->priv)->num_queues * 2) \ + * (sizeof(struct e1000_queue_stats) / sizeof(uint64_t)) +#else +#define E1000_QUEUE_STATS_LEN 0 +#endif +#define E1000_GLOBAL_STATS_LEN \ sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats) +#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN + E1000_QUEUE_STATS_LEN) static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = { "Register test (offline)", "Eeprom test (offline)", "Interrupt test (offline)", "Loopback test (offline)", @@ -1781,19 +1707,43 @@ e1000_nway_reset(struct net_device *netd struct ethtool_stats *stats, uint64_t *data) { struct e1000_adapter *adapter = netdev_priv(netdev); +#ifdef CONFIG_E1000_MQ + uint64_t *queue_stat; + int stat_count = sizeof(struct e1000_queue_stats) / sizeof(uint64_t); + int j, k; +#endif int i; e1000_update_stats(adapter); - for(i = 0; i < E1000_STATS_LEN; i++) { - char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset; - data[i] = (e1000_gstrings_stats[i].sizeof_stat == + for(i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { + char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset; + data[i] = (e1000_gstrings_stats[i].sizeof_stat == sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p; } +#ifdef CONFIG_E1000_MQ + for (j = 0; j < adapter->num_queues; j++) { + queue_stat = (uint64_t *)&adapter->tx_ring[j].tx_stats; + for (k = 0; k < stat_count; k++) + data[i + k] = queue_stat[k]; + i += k; + } + for (j = 0; j < adapter->num_queues; j++) { + queue_stat = (uint64_t *)&adapter->rx_ring[j].rx_stats; + for (k = 0; k < stat_count; k++) + data[i + k] = queue_stat[k]; + i += k; + } +#endif +/* BUG_ON(i != E1000_STATS_LEN); */ } static void e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) { +#ifdef CONFIG_E1000_MQ + struct e1000_adapter *adapter = netdev_priv(netdev); +#endif + uint8_t *p = data; int i; switch(stringset) { @@ -1802,11 +1707,26 @@ E1000_TEST_LEN*ETH_GSTRING_LEN); break; case ETH_SS_STATS: - for (i=0; i < E1000_STATS_LEN; i++) { - memcpy(data + i * ETH_GSTRING_LEN, - e1000_gstrings_stats[i].stat_string, - ETH_GSTRING_LEN); + for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { + memcpy(p, e1000_gstrings_stats[i].stat_string, + ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } +#ifdef CONFIG_E1000_MQ + for (i = 0; i < adapter->num_queues; i++) { + sprintf(p, "tx_queue_%u_packets", i); + p += ETH_GSTRING_LEN; + sprintf(p, "tx_queue_%u_bytes", i); + p += ETH_GSTRING_LEN; + } + for (i = 0; i < adapter->num_queues; i++) { + sprintf(p, "rx_queue_%u_packets", i); + p += ETH_GSTRING_LEN; + sprintf(p, "rx_queue_%u_bytes", i); + p += ETH_GSTRING_LEN; } +#endif +/* BUG_ON(p - data != E1000_STATS_LEN * ETH_GSTRING_LEN); */ break; } } diff -up linux-2.6/drivers/net/e1000/e1000_main.c linux-2.6.new/drivers/net/e1000/e1000_main.c --- linux-2.6/drivers/net/e1000/e1000_main.c 2005-11-14 16:20:34.000000000 -0800 +++ linux-2.6.new/drivers/net/e1000/e1000_main.c 2005-11-04 01:23:40.000000000 -0800 @@ -1043,6 +1043,13 @@ e1000_sw_init(struct e1000_adapter *adap break; } adapter->num_queues = min(adapter->num_queues, num_online_cpus()); + DPRINTK(DRV, INFO, "Multiqueue Enabled: Queue count = %u %s\n", + adapter->num_queues, + ((adapter->num_queues == 1) + ? ((num_online_cpus() > 1) + ? "(due to unsupported feature in current adapter)" + : "(due to unsupported system configuration)") + : "")); #else adapter->num_queues = 1; #endif @@ -1137,7 +1144,8 @@ e1000_setup_queue_mapping(struct e1000_a */ if (i < adapter->num_queues) { *per_cpu_ptr(adapter->cpu_netdev, cpu) = &adapter->polling_netdev[i]; - adapter->cpu_for_queue[i] = cpu; + adapter->rx_ring[i].cpu = cpu; + cpu_set(cpu, adapter->rx_sched_call_data.cpumask); } else *per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL; @@ -3283,26 +3129,27 @@ e1000_intr(int irq, void *data, struct p E1000_WRITE_FLUSH(hw); #ifdef CONFIG_E1000_MQ if (atomic_read(&adapter->rx_sched_call_data.count) == 0) { - cpu_set(adapter->cpu_for_queue[0], - adapter->rx_sched_call_data.cpumask); - for (i = 1; i < adapter->num_queues; i++) { - cpu_set(adapter->cpu_for_queue[i], + int j; + /* We must setup the cpumask once count == 0 since + * each cpu bit is cleared when the work is done. */ + for (j = 0; j < adapter->num_queues; j++) { + cpu_set(adapter->rx_ring[j].cpu, adapter->rx_sched_call_data.cpumask); - atomic_inc(&adapter->irq_sem); } - atomic_set(&adapter->rx_sched_call_data.count, i); + atomic_add(adapter->num_queues - 1, &adapter->irq_sem); + atomic_set(&adapter->rx_sched_call_data.count, + adapter->num_queues); smp_call_async_mask(&adapter->rx_sched_call_data); } else { printk("call_data.count == %u\n", atomic_read(&adapter->rx_sched_call_data.count)); } -#else /* if !CONFIG_E1000_MQ */ +#else if (likely(netif_rx_schedule_prep(&adapter->polling_netdev[0]))) __netif_rx_schedule(&adapter->polling_netdev[0]); else e1000_irq_enable(adapter); -#endif /* CONFIG_E1000_MQ */ - -#else /* if !CONFIG_E1000_NAPI */ +#endif +#else /* Writing IMC and IMS is needed for 82547. * Due to Hub Link bus being occupied, an interrupt * de-assertion message is not able to be sent. @@ -3326,7 +3129,7 @@ if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2) e1000_irq_enable(adapter); -#endif /* CONFIG_E1000_NAPI */ +#endif return IRQ_HANDLED; } @@ -3402,6 +3243,9 @@ e1000_clean_tx_irq(struct e1000_adapter buffer_info = &tx_ring->buffer_info[i]; cleaned = (i == eop); +#ifdef CONFIG_E1000_MQ + tx_ring->tx_stats.bytes += buffer_info->length; +#endif e1000_unmap_and_free_tx_resource(adapter, buffer_info); memset(tx_desc, 0, sizeof(struct e1000_tx_desc)); @@ -3408,8 +3243,10 @@ if (unlikely(++i == tx_ring->count)) i = 0; } - tx_ring->pkt++; - +#ifdef CONFIG_E1000_MQ + tx_ring->tx_stats.packets++; +#endif + eop = tx_ring->buffer_info[i].next_to_watch; eop_desc = E1000_TX_DESC(*tx_ring, eop); } @@ -3684,7 +3494,10 @@ e1000_clean_rx_irq(struct e1000_adapter } #endif /* CONFIG_E1000_NAPI */ netdev->last_rx = jiffies; - rx_ring->pkt++; +#ifdef CONFIG_E1000_MQ + rx_ring->rx_stats.packets++; + rx_ring->rx_stats.bytes += length; +#endif next_desc: rx_desc->status = 0; @@ -3841,7 +3625,10 @@ e1000_clean_rx_irq_ps(struct e1000_adapt } #endif /* CONFIG_E1000_NAPI */ netdev->last_rx = jiffies; - rx_ring->pkt++; +#ifdef CONFIG_E1000_MQ + rx_ring->rx_stats.packets++; + rx_ring->rx_stats.bytes += length; +#endif next_desc: rx_desc->wb.middle.status_error &= ~0xFF; - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html