Netdev List
 help / color / mirror / Atom feed
* Re: [RFC] NAPI as kobject proposal
From: David Miller @ 2010-02-04  1:33 UTC (permalink / raw)
  To: shemminger; +Cc: netdev
In-Reply-To: <20100129101839.36944ba5@nehalam>

From: Stephen Hemminger <shemminger@vyatta.com>
Date: Fri, 29 Jan 2010 10:18:39 -0800

> As part of receive packet steering there is a requirement to add an
> additional parameter to this for the CPU map.

Hmmm, where did this come from?

The RPS maps are per-device.

I think I vaguely recall you "suggesting" that the RPS maps become
per-NAPI.

But, firstly, I didn't see any movement in that part of the
discussion.

And, secondly, I don't think this makes any sense at all.

Things are already overly complicated as it is.  Having the user know
what traffic goes to a particular RX queue (ie. NAPI instance) and set
the RPS map in some way specific to that RX queue is over the top.

If the issue is the case of sharing a NAPI instance between two
devices, there are a few other ways to deal with this.

One I would suggest is to simply clone the RPS map amongst the
devices sharing a NAPI instance.

I currently see NAPI kobjects is just an over-abstraction for a
perceived need rather than a real one.

^ permalink raw reply

* Re: lockdep complaining about btusb during hibernation
From: Tejun Heo @ 2010-02-04  1:33 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Alan Stern, Marcel Holtmann, linux-pm, netdev, Rafael J. Wysocki,
	Eric W. Biederman
In-Reply-To: <201002031828.53945.oliver@neukum.org>

Looks like another sysfs annotation problem.  cc'ing Eric.

On 02/04/2010 02:28 AM, Oliver Neukum wrote:
> Hi,
> 
> I've got lockdep complaining in the latest Linus tree when doing STD.
> 
> 	Regards
> 		Oliver
> 
> Feb  3 17:02:59 vanamonde kernel: =======================================================
> Feb  3 17:02:59 vanamonde kernel: [ INFO: possible circular locking dependency detected ]
> Feb  3 17:02:59 vanamonde kernel: 2.6.33-rc6-0.1-default #50
> Feb  3 17:02:59 vanamonde kernel: -------------------------------------------------------
> Feb  3 17:03:00 vanamonde kernel: bash/2406 is trying to acquire lock:
> Feb  3 17:03:00 vanamonde kernel:  (rtnl_mutex){+.+.+.}, at: [<ffffffff812b74c6>] rtnl_lock+0x12/0x14
> Feb  3 17:03:00 vanamonde kernel: 
> Feb  3 17:03:00 vanamonde kernel: but task is already holding lock:
> Feb  3 17:03:00 vanamonde kernel:  (pm_mutex){+.+.+.}, at: [<ffffffff81077e1c>] hibernate+0x17/0x16d
> Feb  3 17:03:00 vanamonde kernel: 
> Feb  3 17:03:00 vanamonde kernel: which lock already depends on the new lock.
> Feb  3 17:03:00 vanamonde kernel: 
> Feb  3 17:03:00 vanamonde kernel: 
> Feb  3 17:03:00 vanamonde kernel: the existing dependency chain (in reverse order) is:
> Feb  3 17:03:01 vanamonde bluetoothd[1780]: Stopping security manager 0
> Feb  3 17:03:04 vanamonde bluetoothd[1780]: HCI dev 0 down
> Feb  3 17:03:04 vanamonde kernel: 
> Feb  3 17:03:04 vanamonde kernel: -> #2 (pm_mutex){+.+.+.}:
> Feb  3 17:03:04 vanamonde kernel:        [<ffffffff8106ab91>] __lock_acquire+0x135e/0x16eb
> Feb  3 17:03:04 vanamonde kernel:        [<ffffffff8106afea>] lock_acquire+0xcc/0xe9
> Feb  3 17:03:04 vanamonde kernel:        [<ffffffff81331e2a>] mutex_lock_nested+0x54/0x2b5
> Feb  3 17:03:04 vanamonde kernel:        [<ffffffff81077c06>] resume_store+0x61/0xa2
> Feb  3 17:03:04 vanamonde kernel:        [<ffffffff811d3fef>] kobj_attr_store+0x17/0x19
> Feb  3 17:03:04 vanamonde kernel:        [<ffffffff8114332a>] sysfs_write_file+0x103/0x13f
> Feb  3 17:03:04 vanamonde bluetoothd[1780]: Adapter /org/bluez/1775/hci0 has been disabled
> Feb  3 17:03:05 vanamonde bluetoothd[1780]: HCI dev 0 unregistered
> Feb  3 17:03:05 vanamonde bluetoothd[1780]: Unregister path: /org/bluez/1775/hci0
> Feb  3 17:03:05 vanamonde bluetoothd[1780]: HCI dev 0 registered
> Feb  3 17:03:05 vanamonde kernel:        [<ffffffff810ed676>] vfs_write+0xad/0x172
> Feb  3 17:03:05 vanamonde kernel:        [<ffffffff810ed7f4>] sys_write+0x45/0x6c
> Feb  3 17:03:05 vanamonde kernel:        [<ffffffff810029ab>] system_call_fastpath+0x16/0x1b
> Feb  3 17:03:05 vanamonde kernel: 
> Feb  3 17:03:05 vanamonde kernel: -> #1 (s_active){++++.+}:
> Feb  3 17:03:06 vanamonde bluetoothd[1780]: HCI dev 0 up
> Feb  3 17:03:06 vanamonde bluetoothd[1780]: Starting security manager 0
> Feb  3 17:03:06 vanamonde kernel:        [<ffffffff8106ab91>] __lock_acquire+0x135e/0x16eb
> Feb  3 17:03:06 vanamonde kernel:        [<ffffffff8106afea>] lock_acquire+0xcc/0xe9
> Feb  3 17:03:06 vanamonde kernel:        [<ffffffff81143f56>] sysfs_deactivate+0x86/0xc3
> Feb  3 17:03:06 vanamonde kernel:        [<ffffffff81144633>] sysfs_addrm_finish+0x31/0x5a
> Feb  3 17:03:06 vanamonde kernel:        [<ffffffff81142931>] sysfs_hash_and_remove+0x4e/0x65
> Feb  3 17:03:06 vanamonde kernel:        [<ffffffff81145814>] sysfs_remove_group+0x8c/0xc5
> Feb  3 17:03:06 vanamonde kernel:        [<ffffffff81269570>] dpm_sysfs_remove+0x14/0x16
> Feb  3 17:03:06 vanamonde kernel:        [<ffffffff81263d37>] device_del+0x47/0x181
> Feb  3 17:03:06 vanamonde bluetoothd[1780]: Parsing /etc/bluetooth/serial.conf failed: No such file or directory
> Feb  3 17:03:07 vanamonde kernel:        [<ffffffff812ba61c>] netdev_unregister_kobject+0x24/0x28
> Feb  3 17:03:07 vanamonde kernel:        [<ffffffff812ae837>] rollback_registered_many+0x29b/0x300
> Feb  3 17:03:07 vanamonde kernel:        [<ffffffff812ae97d>] unregister_netdevice_queue+0x7f/0xb2
> Feb  3 17:03:07 vanamonde kernel:        [<ffffffff812ae9cc>] unregister_netdev+0x1c/0x23
> Feb  3 17:03:07 vanamonde kernel:        [<ffffffffa04730c4>] usbnet_disconnect+0x87/0xba [usbnet]
> Feb  3 17:03:07 vanamonde kernel:        [<ffffffffa00bb6ac>] usb_unbind_interface+0x69/0xf4 [usbcore]
> Feb  3 17:03:07 vanamonde kernel:        [<ffffffff8126617e>] __device_release_driver+0x76/0xcc
> Feb  3 17:03:07 vanamonde bluetoothd[1780]: Adapter /org/bluez/1775/hci0 has been enabled
> Feb  3 17:03:07 vanamonde kernel:        [<ffffffff812662a2>] device_release_driver+0x1e/0x2b
> Feb  3 17:03:07 vanamonde kernel:        [<ffffffff81265797>] bus_remove_device+0xa8/0xbd
> Feb  3 17:03:07 vanamonde kernel:        [<ffffffff81263e22>] device_del+0x132/0x181
> Feb  3 17:03:07 vanamonde kernel:        [<ffffffffa00b8446>] usb_disable_device+0x101/0x17e [usbcore]
> Feb  3 17:03:07 vanamonde kernel:        [<ffffffffa00b2c24>] usb_disconnect+0xdb/0x150 [usbcore]
> Feb  3 17:03:07 vanamonde kernel:        [<ffffffffa00b434e>] hub_thread+0x6e6/0x1268 [usbcore]
> Feb  3 17:03:07 vanamonde kernel:        [<ffffffff8105837b>] kthread+0x7a/0x82
> Feb  3 17:03:07 vanamonde kernel:        [<ffffffff810037d4>] kernel_thread_helper+0x4/0x10
> Feb  3 17:03:07 vanamonde kernel: 
> Feb  3 17:03:08 vanamonde kernel: -> #0 (rtnl_mutex){+.+.+.}:
> Feb  3 17:03:08 vanamonde kernel:        [<ffffffff8106a841>] __lock_acquire+0x100e/0x16eb
> Feb  3 17:03:08 vanamonde kernel:        [<ffffffff8106afea>] lock_acquire+0xcc/0xe9
> Feb  3 17:03:08 vanamonde kernel:        [<ffffffff81331e2a>] mutex_lock_nested+0x54/0x2b5
> Feb  3 17:03:08 vanamonde kernel:        [<ffffffff812b74c6>] rtnl_lock+0x12/0x14
> Feb  3 17:03:08 vanamonde kernel:        [<ffffffffa020c452>] wiphy_suspend+0x35/0x58 [cfg80211]
> Feb  3 17:03:08 vanamonde kernel:        [<ffffffff81269c34>] legacy_suspend+0x29/0x63
> Feb  3 17:03:08 vanamonde kernel:        [<ffffffff81269faa>] dpm_suspend_start+0x2e5/0x444
> Feb  3 17:03:08 vanamonde kernel:        [<ffffffff81077c8b>] hibernation_snapshot+0x44/0x1be
> Feb  3 17:03:08 vanamonde kernel:        [<ffffffff81077ece>] hibernate+0xc9/0x16d
> Feb  3 17:03:09 vanamonde kernel:        [<ffffffff81076d33>] state_store+0x57/0xce
> Feb  3 17:03:09 vanamonde kernel:        [<ffffffff811d3fef>] kobj_attr_store+0x17/0x19
> Feb  3 17:03:09 vanamonde kernel:        [<ffffffff8114332a>] sysfs_write_file+0x103/0x13f
> Feb  3 17:03:09 vanamonde kernel:        [<ffffffff810ed676>] vfs_write+0xad/0x172
> Feb  3 17:03:09 vanamonde kernel:        [<ffffffff810ed7f4>] sys_write+0x45/0x6c
> Feb  3 17:03:09 vanamonde kernel:        [<ffffffff810029ab>] system_call_fastpath+0x16/0x1b
> Feb  3 17:03:09 vanamonde kernel: 
> Feb  3 17:03:09 vanamonde kernel: other info that might help us debug this:
> Feb  3 17:03:09 vanamonde kernel: 
> Feb  3 17:03:09 vanamonde kernel: 4 locks held by bash/2406:
> Feb  3 17:03:09 vanamonde kernel:  #0:  (&buffer->mutex){+.+.+.}, at: [<ffffffff8114325e>] sysfs_write_file+0x37/0x13f
> Feb  3 17:03:09 vanamonde kernel:  #1:  (s_active){++++.+}, at: [<ffffffff8114489f>] sysfs_get_active_two+0x1f/0x44
> Feb  3 17:03:09 vanamonde kernel:  #2:  (s_active){++++.+}, at: [<ffffffff811448ac>] sysfs_get_active_two+0x2c/0x44
> Feb  3 17:03:09 vanamonde kernel:  #3:  (pm_mutex){+.+.+.}, at: [<ffffffff81077e1c>] hibernate+0x17/0x16d
> Feb  3 17:03:09 vanamonde kernel: 
> Feb  3 17:03:09 vanamonde kernel: stack backtrace:
> Feb  3 17:03:09 vanamonde kernel: Pid: 2406, comm: bash Not tainted 2.6.33-rc6-0.1-default #50
> Feb  3 17:03:09 vanamonde kernel: Call Trace:
> Feb  3 17:03:09 vanamonde kernel:  [<ffffffff813336ef>] ? _raw_spin_unlock_irqrestore+0x33/0x41
> Feb  3 17:03:09 vanamonde kernel:  [<ffffffff810692f5>] print_circular_bug+0xaf/0xbe
> Feb  3 17:03:10 vanamonde kernel:  [<ffffffff8106a841>] __lock_acquire+0x100e/0x16eb
> Feb  3 17:03:10 vanamonde kernel:  [<ffffffff8106afea>] lock_acquire+0xcc/0xe9
> Feb  3 17:03:10 vanamonde kernel:  [<ffffffff812b74c6>] ? rtnl_lock+0x12/0x14
> Feb  3 17:03:10 vanamonde kernel:  [<ffffffffa020c41d>] ? wiphy_suspend+0x0/0x58 [cfg80211]
> Feb  3 17:03:10 vanamonde kernel:  [<ffffffff81331e2a>] mutex_lock_nested+0x54/0x2b5
> Feb  3 17:03:10 vanamonde kernel:  [<ffffffff812b74c6>] ? rtnl_lock+0x12/0x14
> Feb  3 17:03:10 vanamonde kernel:  [<ffffffffa020c41d>] ? wiphy_suspend+0x0/0x58 [cfg80211]
> Feb  3 17:03:10 vanamonde kernel:  [<ffffffff812b74c6>] rtnl_lock+0x12/0x14
> Feb  3 17:03:10 vanamonde kernel:  [<ffffffffa020c452>] wiphy_suspend+0x35/0x58 [cfg80211]
> Feb  3 17:03:10 vanamonde kernel:  [<ffffffff81269c34>] legacy_suspend+0x29/0x63
> Feb  3 17:03:11 vanamonde kernel:  [<ffffffff81269faa>] dpm_suspend_start+0x2e5/0x444
> Feb  3 17:03:11 vanamonde kernel:  [<ffffffff81077c8b>] hibernation_snapshot+0x44/0x1be
> Feb  3 17:03:11 vanamonde kernel:  [<ffffffff81077ece>] hibernate+0xc9/0x16d
> Feb  3 17:03:11 vanamonde kernel:  [<ffffffff81076d33>] state_store+0x57/0xce
> Feb  3 17:03:11 vanamonde kernel:  [<ffffffff811d3fef>] kobj_attr_store+0x17/0x19
> Feb  3 17:03:11 vanamonde kernel:  [<ffffffff8114332a>] sysfs_write_file+0x103/0x13f
> Feb  3 17:03:11 vanamonde kernel:  [<ffffffff810ed676>] vfs_write+0xad/0x172
> Feb  3 17:03:11 vanamonde kernel:  [<ffffffff81068c13>] ? trace_hardirqs_on_caller+0x10c/0x130
> Feb  3 17:03:11 vanamonde kernel:  [<ffffffff810ed7f4>] sys_write+0x45/0x6c
> Feb  3 17:03:11 vanamonde kernel:  [<ffffffff810029ab>] system_call_fastpath+0x16/0x1b
> Feb  3 17:03:11 vanamonde kernel: btusb_intr_complete: hci0 urb ffff8801357f1080 failed to resubmit (1)
> Feb  3 17:03:11 vanamonde kernel: uhci_hcd 0000:00:1a.2: release dev 2 ep81-INT, period 1, phase 0, 23 us
> Feb  3 17:03:11 vanamonde kernel: btusb_bulk_complete: hci0 urb ffff88013967be40 failed to resubmit (1)
> Feb  3 17:03:11 vanamonde kernel: btusb_bulk_complete: hci0 urb ffff88013967bf00 failed to resubmit (1)
> 


-- 
tejun

^ permalink raw reply

* [net-next-2.6 PATCH 2/2] e1000: call pci_save_state after pci_restore_state
From: Jeff Kirsher @ 2010-02-04  0:49 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Nicholas Nunley, Jeff Kirsher
In-Reply-To: <20100204004926.16084.32526.stgit@localhost.localdomain>

From: Nick Nunley <nicholasx.d.nunley@intel.com>

This patch adds a call to pci_save_state() immediately after
the call to pci_restore_state(). Due to a change in the behavior
of pci_restore_state() it is necessary to call pci_save_state()
to keep the state_saved flag. This patch is based on a similar
patch for ixgbe.

Signed-off-by: Nicholas Nunley <nicholasx.d.nunley@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000/e1000_main.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 4ff50d6..3b14dd7 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -847,6 +847,9 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
 		goto err_pci_reg;
 
 	pci_set_master(pdev);
+	err = pci_save_state(pdev);
+	if (err)
+		goto err_alloc_etherdev;
 
 	err = -ENOMEM;
 	netdev = alloc_etherdev(sizeof(struct e1000_adapter));
@@ -4596,6 +4599,7 @@ static int e1000_resume(struct pci_dev *pdev)
 
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
+	pci_save_state(pdev);
 
 	if (adapter->need_ioport)
 		err = pci_enable_device(pdev);


^ permalink raw reply related

* [net-next-2.6 PATCH 1/2] e1000: Report link status in ethtool when interface is down
From: Jeff Kirsher @ 2010-02-04  0:49 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Nicholas Nunley, Jeff Kirsher

From: Nick Nunley <nicholasx.d.nunley@intel.com>

With this change ethtool will correctly report link status when
the interface is down. Currently ethtool reports the link as not
detected when the interface is down.

Signed-off-by: Nicholas Nunley <nicholasx.d.nunley@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000/e1000.h         |    1 +
 drivers/net/e1000/e1000_ethtool.c |   19 ++++++++++++++++++-
 drivers/net/e1000/e1000_main.c    |    2 +-
 3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index e8932db..9902b33 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -349,6 +349,7 @@ extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
 extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
 extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
 extern void e1000_update_stats(struct e1000_adapter *adapter);
+extern bool e1000_has_link(struct e1000_adapter *adapter);
 extern void e1000_power_up_phy(struct e1000_adapter *);
 extern void e1000_set_ethtool_ops(struct net_device *netdev);
 extern void e1000_check_options(struct e1000_adapter *adapter);
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 13e9ece..c67e931 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -215,6 +215,23 @@ static int e1000_set_settings(struct net_device *netdev,
 	return 0;
 }
 
+static u32 e1000_get_link(struct net_device *netdev)
+{
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+
+	/*
+	 * If the link is not reported up to netdev, interrupts are disabled,
+	 * and so the physical link state may have changed since we last
+	 * looked. Set get_link_status to make sure that the true link
+	 * state is interrogated, rather than pulling a cached and possibly
+	 * stale link state from the driver.
+	 */
+	if (!netif_carrier_ok(netdev))
+		adapter->hw.get_link_status = 1;
+
+	return e1000_has_link(adapter);
+}
+
 static void e1000_get_pauseparam(struct net_device *netdev,
 				 struct ethtool_pauseparam *pause)
 {
@@ -1892,7 +1909,7 @@ static const struct ethtool_ops e1000_ethtool_ops = {
 	.get_msglevel           = e1000_get_msglevel,
 	.set_msglevel           = e1000_set_msglevel,
 	.nway_reset             = e1000_nway_reset,
-	.get_link               = ethtool_op_get_link,
+	.get_link               = e1000_get_link,
 	.get_eeprom_len         = e1000_get_eeprom_len,
 	.get_eeprom             = e1000_get_eeprom,
 	.set_eeprom             = e1000_set_eeprom,
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index b608528..4ff50d6 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -2246,7 +2246,7 @@ static void e1000_82547_tx_fifo_stall(unsigned long data)
 	}
 }
 
-static bool e1000_has_link(struct e1000_adapter *adapter)
+bool e1000_has_link(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	bool link_active = false;


^ permalink raw reply related

* [PATCH] net: emaclite: adding MDIO and phy lib support
From: John Linn @ 2010-02-04  0:49 UTC (permalink / raw)
  To: netdev, linuxppc-dev, jgarzik, grant.likely, jwboyer
  Cc: john.williams, John Linn, Sadanand Mutyala

These changes add MDIO and phy lib support to the driver as the
IP core now supports the MDIO bus.

The MDIO bus and phy are added as a child to the emaclite in the device
tree as illustrated below.

mdio {
	#address-cells = <1>;
	#size-cells = <0>;
	phy0: phy@7 {
		reg = <7>;
	} ;
}

Signed-off-by: Sadanand Mutyala <Sadanand.Mutyala@xilinx.com>
Signed-off-by: John Linn <john.linn@xilinx.com>
---
 drivers/net/Kconfig           |    1 +
 drivers/net/xilinx_emaclite.c |  362 ++++++++++++++++++++++++++++++++++++-----
 2 files changed, 319 insertions(+), 44 deletions(-)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 396fd38..2056cd2 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1947,6 +1947,7 @@ config ATL2
 config XILINX_EMACLITE
 	tristate "Xilinx 10/100 Ethernet Lite support"
 	depends on PPC32 || MICROBLAZE
+	select PHYLIB
 	help
 	  This driver supports the 10/100 Ethernet Lite from Xilinx.
 
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index 83a044d..8c7d7ae 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -22,11 +22,17 @@
 
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
+#include <linux/of_mdio.h>
+#include <linux/phy.h>
 
 #define DRIVER_NAME "xilinx_emaclite"
 
 /* Register offsets for the EmacLite Core */
 #define XEL_TXBUFF_OFFSET 	0x0		/* Transmit Buffer */
+#define XEL_MDIOADDR_OFFSET	0x07E4		/* MDIO Address Register */
+#define XEL_MDIOWR_OFFSET	0x07E8		/* MDIO Write Data Register */
+#define XEL_MDIORD_OFFSET	0x07EC		/* MDIO Read Data Register */
+#define XEL_MDIOCTRL_OFFSET	0x07F0		/* MDIO Control Register */
 #define XEL_GIER_OFFSET		0x07F8		/* GIE Register */
 #define XEL_TSR_OFFSET		0x07FC		/* Tx status */
 #define XEL_TPLR_OFFSET		0x07F4		/* Tx packet length */
@@ -37,6 +43,22 @@
 
 #define XEL_BUFFER_OFFSET	0x0800		/* Next Tx/Rx buffer's offset */
 
+/* MDIO Address Register Bit Masks */
+#define XEL_MDIOADDR_REGADR_MASK  0x0000001F	/* Register Address */
+#define XEL_MDIOADDR_PHYADR_MASK  0x000003E0	/* PHY Address */
+#define XEL_MDIOADDR_PHYADR_SHIFT 5
+#define XEL_MDIOADDR_OP_MASK	  0x00000400	/* RD/WR Operation */
+
+/* MDIO Write Data Register Bit Masks */
+#define XEL_MDIOWR_WRDATA_MASK	  0x0000FFFF	/* Data to be Written */
+
+/* MDIO Read Data Register Bit Masks */
+#define XEL_MDIORD_RDDATA_MASK	  0x0000FFFF	/* Data to be Read */
+
+/* MDIO Control Register Bit Masks */
+#define XEL_MDIOCTRL_MDIOSTS_MASK 0x00000001	/* MDIO Status Mask */
+#define XEL_MDIOCTRL_MDIOEN_MASK  0x00000008	/* MDIO Enable */
+
 /* Global Interrupt Enable Register (GIER) Bit Masks */
 #define XEL_GIER_GIE_MASK	0x80000000 	/* Global Enable */
 
@@ -87,6 +109,12 @@
  * @reset_lock:		lock used for synchronization
  * @deferred_skb:	holds an skb (for transmission at a later time) when the
  *			Tx buffer is not free
+ * @phy_dev:		pointer to the PHY device
+ * @phy_node:		pointer to the PHY device node
+ * @mii_bus:		pointer to the MII bus
+ * @mdio_irqs:		IRQs table for MDIO bus
+ * @last_link:		last link status
+ * @has_mdio:		indicates whether MDIO is included in the HW
  */
 struct net_local {
 
@@ -100,6 +128,15 @@ struct net_local {
 
 	spinlock_t reset_lock;
 	struct sk_buff *deferred_skb;
+
+	struct phy_device *phy_dev;
+	struct device_node *phy_node;
+
+	struct mii_bus *mii_bus;
+	int mdio_irqs[PHY_MAX_ADDR];
+
+	int last_link;
+	bool has_mdio;
 };
 
 
@@ -431,7 +468,7 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
 }
 
 /**
- * xemaclite_set_mac_address - Set the MAC address for this device
+ * xemaclite_update_address - Update the MAC address in the device
  * @drvdata:	Pointer to the Emaclite device private data
  * @address_ptr:Pointer to the MAC address (MAC address is a 48-bit value)
  *
@@ -441,8 +478,8 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
  * The MAC address can be programmed using any of the two transmit
  * buffers (if configured).
  */
-static void xemaclite_set_mac_address(struct net_local *drvdata,
-				      u8 *address_ptr)
+static void xemaclite_update_address(struct net_local *drvdata,
+				     u8 *address_ptr)
 {
 	void __iomem *addr;
 	u32 reg_data;
@@ -465,6 +502,30 @@ static void xemaclite_set_mac_address(struct net_local *drvdata,
 }
 
 /**
+ * xemaclite_set_mac_address - Set the MAC address for this device
+ * @dev:	Pointer to the network device instance
+ * @addr:	Void pointer to the sockaddr structure
+ *
+ * This function copies the HW address from the sockaddr strucutre to the
+ * net_device structure and updates the address in HW.
+ *
+ * Return:	Error if the net device is busy or 0 if the addr is set
+ *		successfully
+ */
+static int xemaclite_set_mac_address(struct net_device *dev, void *address)
+{
+	struct net_local *lp = (struct net_local *) netdev_priv(dev);
+	struct sockaddr *addr = address;
+
+	if (netif_running(dev))
+		return -EBUSY;
+
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+	xemaclite_update_address(lp, dev->dev_addr);
+	return 0;
+}
+
+/**
  * xemaclite_tx_timeout - Callback for Tx Timeout
  * @dev:	Pointer to the network device
  *
@@ -641,12 +702,195 @@ static irqreturn_t xemaclite_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+/**********************/
+/* MDIO Bus functions */
+/**********************/
+/**
+ * xemaclite_mdio_read - Read from a given MII management register
+ * @bus:	the mii_bus struct
+ * @phy_id:	the phy address
+ * @reg:	register number to read from
+ *
+ * This function waits till the device is ready to accept a new MDIO
+ * request and then writes the phy address to the MDIO Address register
+ * and reads data from MDIO Read Data register, when its available.
+ *
+ * Return:	Value read from the MII management register
+ */
+static int xemaclite_mdio_read(struct mii_bus *bus, int phy_id, int reg)
+{
+	struct net_local *lp = bus->priv;
+	u32 ctrl_reg;
+	u32 rc;
+
+	/* Wait till the device is ready */
+	do {
+		ctrl_reg = in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET);
+	} while (ctrl_reg & XEL_MDIOCTRL_MDIOSTS_MASK);
+
+	/* Write the PHY address, register number and set the OP bit in the
+	 * MDIO Address register. Set the Status bit in the MDIO Control
+	 * register to start a MDIO read transaction.
+	 */
+	out_be32(lp->base_addr + XEL_MDIOADDR_OFFSET,
+		 XEL_MDIOADDR_OP_MASK |
+		 ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg));
+	out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET,
+		 ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK);
+
+	/* Wait for the device to complete the transaction and read the value
+	 * from MDIO Read Data register.
+	 */
+	do {
+		ctrl_reg = in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET);
+	} while (ctrl_reg & XEL_MDIOCTRL_MDIOSTS_MASK);
+	rc = in_be32(lp->base_addr + XEL_MDIORD_OFFSET);
+
+	dev_dbg(&lp->ndev->dev,
+		"xemaclite_mdio_read(phy_id=%i, reg=%x) == %x\n",
+		phy_id, reg, rc);
+
+	return rc;
+}
+
+/**
+ * xemaclite_mdio_write - Write to a given MII management register
+ * @bus:	the mii_bus struct
+ * @phy_id:	the phy address
+ * @reg:	register number to write to
+ * @val:	value to write to the register number specified by reg
+ *
+ * This fucntion waits till the device is ready to accept a new MDIO
+ * request and then writes the val to the MDIO Write Data register.
+ */
+static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg,
+				u16 val)
+{
+	struct net_local *lp = bus->priv;
+	u32 ctrl_reg;
+
+	dev_dbg(&lp->ndev->dev,
+		"xemaclite_mdio_write(phy_id=%i, reg=%x, val=%x)\n",
+		phy_id, reg, val);
+
+	/* Wait till the device is ready */
+	do {
+		ctrl_reg = in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET);
+	} while (ctrl_reg & XEL_MDIOCTRL_MDIOSTS_MASK);
+
+	/* Write the PHY address, register number and clear the OP bit in the
+	 * MDIO Address register and then write the value into the MDIO Write
+	 * Data register. Finally, set the Status bit in the MDIO Control
+	 * register to start a MDIO write transaction.
+	 */
+	out_be32(lp->base_addr + XEL_MDIOADDR_OFFSET,
+		 ~XEL_MDIOADDR_OP_MASK &
+		 ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg));
+	out_be32(lp->base_addr + XEL_MDIOWR_OFFSET, val);
+	out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET,
+		 ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK);
+
+	return 0;
+}
+
+/**
+ * xemaclite_mdio_reset - Reset the mdio bus.
+ * @bus:	Pointer to the MII bus
+ *
+ * This function is required(?) as per Documentation/networking/phy.txt.
+ * There is no reset in this device; this function always returns 0.
+ */
+static int xemaclite_mdio_reset(struct mii_bus *bus)
+{
+	return 0;
+}
+
+/**
+ * xemaclite_mdio_setup - Register mii_bus for the Emaclite device
+ * @lp:		Pointer to the Emaclite device private data
+ * @ofdev:	Pointer to OF device structure
+ *
+ * This function enables MDIO bus in the Emaclite device and registers a
+ * mii_bus.
+ *
+ * Return:	0 upon success or a negative error upon failure
+ */
+static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
+{
+	struct mii_bus *bus;
+	int rc;
+	struct resource res;
+	struct device_node *np = of_get_parent(lp->phy_node);
+
+	/* Don't register the MDIO bus if the phy_node or its parent node
+	 * can't be found.
+	 */
+	if (!np)
+		return -ENODEV;
+
+	/* Enable the MDIO bus by asserting the enable bit in MDIO Control
+	 * register.
+	 */
+	out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET,
+		 XEL_MDIOCTRL_MDIOEN_MASK);
+
+	bus = mdiobus_alloc();
+	if (!bus)
+		return -ENOMEM;
+
+	of_address_to_resource(np, 0, &res);
+	snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx",
+		 (unsigned long long)res.start);
+	bus->priv = lp;
+	bus->name = "Xilinx Emaclite MDIO";
+	bus->read = xemaclite_mdio_read;
+	bus->write = xemaclite_mdio_write;
+	bus->reset = xemaclite_mdio_reset;
+	bus->parent = dev;
+	bus->irq = lp->mdio_irqs; /* preallocated IRQ table */
+
+	lp->mii_bus = bus;
+
+	rc = of_mdiobus_register(bus, np);
+	if (rc)
+		goto err_register;
+
+	return 0;
+
+err_register:
+	mdiobus_free(bus);
+	return rc;
+}
+
+/**
+ * xemaclite_adjust_link - Link state callback for the Emaclite device
+ * @ndev: pointer to net_device struct
+ *
+ * There's nothing in the Emaclite device to be configured when the link
+ * state changes. We just print the status.
+ */
+void xemaclite_adjust_link(struct net_device *ndev)
+{
+	struct net_local *lp = netdev_priv(ndev);
+	struct phy_device *phy = lp->phy_dev;
+	int link_state;
+
+	/* hash together the state values to decide if something has changed */
+	link_state = phy->speed | (phy->duplex << 1) | phy->link;
+
+	if (lp->last_link != link_state) {
+		lp->last_link = link_state;
+		phy_print_status(phy);
+	}
+}
+
 /**
  * xemaclite_open - Open the network device
  * @dev:	Pointer to the network device
  *
  * This function sets the MAC address, requests an IRQ and enables interrupts
  * for the Emaclite device and starts the Tx queue.
+ * It also connects to the phy device, if MDIO is included in Emaclite device.
  */
 static int xemaclite_open(struct net_device *dev)
 {
@@ -656,14 +900,50 @@ static int xemaclite_open(struct net_device *dev)
 	/* Just to be safe, stop the device first */
 	xemaclite_disable_interrupts(lp);
 
+	if (lp->phy_node) {
+		u32 bmcr;
+
+		lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node,
+					     xemaclite_adjust_link, 0,
+					     PHY_INTERFACE_MODE_MII);
+		if (!lp->phy_dev) {
+			dev_err(&lp->ndev->dev, "of_phy_connect() failed\n");
+			return -ENODEV;
+		}
+
+		/* EmacLite doesn't support giga-bit speeds */
+		lp->phy_dev->supported &= (PHY_BASIC_FEATURES);
+		lp->phy_dev->advertising = lp->phy_dev->supported;
+
+		/* Don't advertise 1000BASE-T Full/Half duplex speeds */
+		xemaclite_mdio_write(lp->mii_bus, lp->phy_dev->addr,
+				     MII_CTRL1000, 0x00);
+		/* Advertise only 10 and 100mbps full/half duplex speeds */
+		xemaclite_mdio_write(lp->mii_bus, lp->phy_dev->addr,
+				     MII_ADVERTISE, ADVERTISE_ALL);
+
+		/* Restart auto negotiation */
+		bmcr = xemaclite_mdio_read(lp->mii_bus,
+					   lp->phy_dev->addr, MII_BMCR);
+		bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+		xemaclite_mdio_write(lp->mii_bus, lp->phy_dev->addr,
+				     MII_BMCR, bmcr);
+
+		phy_start(lp->phy_dev);
+	}
+
 	/* Set the MAC address each time opened */
-	xemaclite_set_mac_address(lp, dev->dev_addr);
+	xemaclite_update_address(lp, dev->dev_addr);
 
 	/* Grab the IRQ */
 	retval = request_irq(dev->irq, xemaclite_interrupt, 0, dev->name, dev);
 	if (retval) {
 		dev_err(&lp->ndev->dev, "Could not allocate interrupt %d\n",
 			dev->irq);
+		if (lp->phy_dev)
+			phy_disconnect(lp->phy_dev);
+		lp->phy_dev = NULL;
+
 		return retval;
 	}
 
@@ -682,6 +962,7 @@ static int xemaclite_open(struct net_device *dev)
  *
  * This function stops the Tx queue, disables interrupts and frees the IRQ for
  * the Emaclite device.
+ * It also disconnects the phy device associated with the Emaclite device.
  */
 static int xemaclite_close(struct net_device *dev)
 {
@@ -691,6 +972,10 @@ static int xemaclite_close(struct net_device *dev)
 	xemaclite_disable_interrupts(lp);
 	free_irq(dev->irq, dev);
 
+	if (lp->phy_dev)
+		phy_disconnect(lp->phy_dev);
+	lp->phy_dev = NULL;
+
 	return 0;
 }
 
@@ -754,42 +1039,6 @@ static int xemaclite_send(struct sk_buff *orig_skb, struct net_device *dev)
 }
 
 /**
- * xemaclite_ioctl - Perform IO Control operations on the network device
- * @dev:	Pointer to the network device
- * @rq:		Pointer to the interface request structure
- * @cmd:	IOCTL command
- *
- * The only IOCTL operation supported by this function is setting the MAC
- * address. An error is reported if any other operations are requested.
- *
- * Return:	0 to indicate success, or a negative error for failure.
- */
-static int xemaclite_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct net_local *lp = (struct net_local *) netdev_priv(dev);
-	struct hw_addr_data *hw_addr = (struct hw_addr_data *) &rq->ifr_hwaddr;
-
-	switch (cmd) {
-	case SIOCETHTOOL:
-		return -EIO;
-
-	case SIOCSIFHWADDR:
-		dev_err(&lp->ndev->dev, "SIOCSIFHWADDR\n");
-
-		/* Copy MAC address in from user space */
-		copy_from_user((void __force *) dev->dev_addr,
-			       (void __user __force *) hw_addr,
-			       IFHWADDRLEN);
-		xemaclite_set_mac_address(lp, dev->dev_addr);
-		break;
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	return 0;
-}
-
-/**
  * xemaclite_remove_ndev - Free the network device
  * @ndev:	Pointer to the network device to be freed
  *
@@ -840,6 +1089,8 @@ static struct net_device_ops xemaclite_netdev_ops;
  * This function probes for the Emaclite device in the device tree.
  * It initializes the driver data structure and the hardware, sets the MAC
  * address and registers the network device.
+ * It also registers a mii_bus for the Emaclite device, if MDIO is included
+ * in the device.
  *
  * Return:	0, if the driver is bound to the Emaclite device, or
  *		a negative error if there is failure.
@@ -853,7 +1104,6 @@ static int __devinit xemaclite_of_probe(struct of_device *ofdev,
 	struct net_local *lp = NULL;
 	struct device *dev = &ofdev->dev;
 	const void *mac_address;
-
 	int rc = 0;
 
 	dev_info(dev, "Device Tree Probing\n");
@@ -880,6 +1130,7 @@ static int __devinit xemaclite_of_probe(struct of_device *ofdev,
 	}
 
 	dev_set_drvdata(dev, ndev);
+	SET_NETDEV_DEV(ndev, &ofdev->dev);
 
 	ndev->irq = r_irq.start;
 	ndev->mem_start = r_mem.start;
@@ -923,7 +1174,16 @@ static int __devinit xemaclite_of_probe(struct of_device *ofdev,
 	out_be32(lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET, 0);
 
 	/* Set the MAC address in the EmacLite device */
-	xemaclite_set_mac_address(lp, ndev->dev_addr);
+	xemaclite_update_address(lp, ndev->dev_addr);
+
+	/* Check if MDIO is included in the HW */
+	lp->has_mdio = get_bool(ofdev, "xlnx,include-mdio");
+	if (lp->has_mdio) {
+		lp->phy_node = of_parse_phandle(ofdev->node, "phy-handle", 0);
+		rc = xemaclite_mdio_setup(lp, &ofdev->dev);
+		if (rc)
+			dev_warn(&ofdev->dev, "error registering MDIO bus\n");
+	}
 
 	dev_info(dev,
 		 "MAC address is now %2x:%2x:%2x:%2x:%2x:%2x\n",
@@ -972,12 +1232,25 @@ static int __devexit xemaclite_of_remove(struct of_device *of_dev)
 	struct device *dev = &of_dev->dev;
 	struct net_device *ndev = dev_get_drvdata(dev);
 
+	struct net_local *lp = (struct net_local *) netdev_priv(ndev);
+
+	/* Un-register the mii_bus, if configured */
+	if (lp->has_mdio) {
+		mdiobus_unregister(lp->mii_bus);
+		kfree(lp->mii_bus->irq);
+		mdiobus_free(lp->mii_bus);
+		lp->mii_bus = NULL;
+	}
+
 	unregister_netdev(ndev);
 
+	if (lp->phy_node)
+		of_node_put(lp->phy_node);
+	lp->phy_node = NULL;
+
 	release_mem_region(ndev->mem_start, ndev->mem_end-ndev->mem_start + 1);
 
 	xemaclite_remove_ndev(ndev);
-
 	dev_set_drvdata(dev, NULL);
 
 	return 0;
@@ -987,7 +1260,7 @@ static struct net_device_ops xemaclite_netdev_ops = {
 	.ndo_open		= xemaclite_open,
 	.ndo_stop		= xemaclite_close,
 	.ndo_start_xmit		= xemaclite_send,
-	.ndo_do_ioctl		= xemaclite_ioctl,
+	.ndo_set_mac_address	= xemaclite_set_mac_address,
 	.ndo_tx_timeout		= xemaclite_tx_timeout,
 	.ndo_get_stats		= xemaclite_get_stats,
 };
@@ -999,6 +1272,7 @@ static struct of_device_id xemaclite_of_match[] __devinitdata = {
 	{ .compatible = "xlnx,xps-ethernetlite-1.00.a", },
 	{ .compatible = "xlnx,xps-ethernetlite-2.00.a", },
 	{ .compatible = "xlnx,xps-ethernetlite-2.01.a", },
+	{ .compatible = "xlnx,xps-ethernetlite-3.00.a", },
 	{ /* end of list */ },
 };
 MODULE_DEVICE_TABLE(of, xemaclite_of_match);
-- 
1.6.2.1



This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.



^ permalink raw reply related

* [net-next-2.6 PATCH v2] ixgbe: only process one ixgbe_watchdog_task at a time.
From: Jeff Kirsher @ 2010-02-04  0:23 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, John Fastabend, Jeff Kirsher

From: John Fastabend <john.r.fastabend@intel.com>

Processing multiple ixgbe_watchdog_task calls may cause
the link_up variable and IXGBE_FLAG_NEED_LINK_UPDATE flag
to be set incorrectly.  In the worse case this is causing
the netif_carrier_off to be called inappropriately which
results in an interface that can't be brought up.

Although schedule_work() will only schedule the task if
it is not already on the work queue the WORK_STRUCT_PENDING
bits are cleared just before calling the work function.
This allows WORK_STRUCT_PENDING to be cleared, the work
function to start and meanwhile schedule another task.

This patch adds a mutex to the watchdog task. This bug is
actualized by changing DCB settings or doing extended
cable pull or reset tests.

Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/ixgbe/ixgbe.h      |   17 ++++++++---------
 drivers/net/ixgbe/ixgbe_main.c |   13 +++++++++----
 2 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index a1f1115..bffbe0d 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -342,15 +342,14 @@ struct ixgbe_adapter {
 #define IXGBE_FLAG_VMDQ_ENABLED                 (u32)(1 << 19)
 #define IXGBE_FLAG_FAN_FAIL_CAPABLE             (u32)(1 << 20)
 #define IXGBE_FLAG_NEED_LINK_UPDATE             (u32)(1 << 22)
-#define IXGBE_FLAG_IN_WATCHDOG_TASK             (u32)(1 << 23)
-#define IXGBE_FLAG_IN_SFP_LINK_TASK             (u32)(1 << 24)
-#define IXGBE_FLAG_IN_SFP_MOD_TASK              (u32)(1 << 25)
-#define IXGBE_FLAG_FDIR_HASH_CAPABLE            (u32)(1 << 26)
-#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE         (u32)(1 << 27)
-#define IXGBE_FLAG_FCOE_CAPABLE                 (u32)(1 << 28)
-#define IXGBE_FLAG_FCOE_ENABLED                 (u32)(1 << 29)
-#define IXGBE_FLAG_SRIOV_CAPABLE                (u32)(1 << 30)
-#define IXGBE_FLAG_SRIOV_ENABLED                (u32)(1 << 31)
+#define IXGBE_FLAG_IN_SFP_LINK_TASK             (u32)(1 << 23)
+#define IXGBE_FLAG_IN_SFP_MOD_TASK              (u32)(1 << 24)
+#define IXGBE_FLAG_FDIR_HASH_CAPABLE            (u32)(1 << 25)
+#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE         (u32)(1 << 26)
+#define IXGBE_FLAG_FCOE_CAPABLE                 (u32)(1 << 27)
+#define IXGBE_FLAG_FCOE_ENABLED                 (u32)(1 << 28)
+#define IXGBE_FLAG_SRIOV_CAPABLE                (u32)(1 << 29)
+#define IXGBE_FLAG_SRIOV_ENABLED                (u32)(1 << 30)
 
 	u32 flags2;
 #define IXGBE_FLAG2_RSC_CAPABLE                 (u32)(1)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 5914b9b..267fbdd 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -5043,6 +5043,8 @@ static void ixgbe_fdir_reinit_task(struct work_struct *work)
 	netif_tx_start_all_queues(adapter->netdev);
 }
 
+static DEFINE_MUTEX(ixgbe_watchdog_lock);
+
 /**
  * ixgbe_watchdog_task - worker thread to bring link up
  * @work: pointer to work_struct containing our data
@@ -5054,13 +5056,16 @@ static void ixgbe_watchdog_task(struct work_struct *work)
 	                                             watchdog_task);
 	struct net_device *netdev = adapter->netdev;
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32 link_speed = adapter->link_speed;
-	bool link_up = adapter->link_up;
+	u32 link_speed;
+	bool link_up;
 	int i;
 	struct ixgbe_ring *tx_ring;
 	int some_tx_pending = 0;
 
-	adapter->flags |= IXGBE_FLAG_IN_WATCHDOG_TASK;
+	mutex_lock(&ixgbe_watchdog_lock);
+
+	link_up = adapter->link_up;
+	link_speed = adapter->link_speed;
 
 	if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE) {
 		hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
@@ -5149,7 +5154,7 @@ static void ixgbe_watchdog_task(struct work_struct *work)
 	}
 
 	ixgbe_update_stats(adapter);
-	adapter->flags &= ~IXGBE_FLAG_IN_WATCHDOG_TASK;
+	mutex_unlock(&ixgbe_watchdog_lock);
 }
 
 static int ixgbe_tso(struct ixgbe_adapter *adapter,


^ permalink raw reply related

* [net-next-2.6 PATCH v2 2/2] ixgbe: Make descriptor ring allocations NUMA-aware
From: Jeff Kirsher @ 2010-02-04  0:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Peter P Waskiewicz Jr, Jeff Kirsher
In-Reply-To: <20100204001804.15798.98344.stgit@localhost.localdomain>

From: PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com>

This patch allocates the ring structures themselves on each
NUMA node along with the buffer_info structures.  This way we
don't allocate the entire ring memory on a single node in one
big block, thus reducing NUMA node memory crosstalk.

Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/ixgbe/ixgbe.h         |    5 -
 drivers/net/ixgbe/ixgbe_ethtool.c |   71 +++++-----
 drivers/net/ixgbe/ixgbe_fcoe.c    |    4 -
 drivers/net/ixgbe/ixgbe_main.c    |  276 ++++++++++++++++++++-----------------
 4 files changed, 189 insertions(+), 167 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index f34512e..a1f1115 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -175,6 +175,7 @@ struct ixgbe_ring {
 
 	struct ixgbe_queue_stats stats;
 	unsigned long reinit_state;
+	int numa_node;
 	u64 rsc_count;			/* stat for coalesced packets */
 	u64 rsc_flush;			/* stats for flushed packets */
 	u32 restart_queue;		/* track tx queue restarts */
@@ -293,7 +294,7 @@ struct ixgbe_adapter {
 	u16 eitr_high;
 
 	/* TX */
-	struct ixgbe_ring *tx_ring ____cacheline_aligned_in_smp; /* One per active queue */
+	struct ixgbe_ring *tx_ring[MAX_TX_QUEUES] ____cacheline_aligned_in_smp;
 	int num_tx_queues;
 	u32 tx_timeout_count;
 	bool detect_tx_hung;
@@ -302,7 +303,7 @@ struct ixgbe_adapter {
 	u64 lsc_int;
 
 	/* RX */
-	struct ixgbe_ring *rx_ring ____cacheline_aligned_in_smp; /* One per active queue */
+	struct ixgbe_ring *rx_ring[MAX_RX_QUEUES] ____cacheline_aligned_in_smp;
 	int num_rx_queues;
 	int num_rx_pools;		/* == num_rx_queues in 82598 */
 	int num_rx_queues_per_pool;	/* 1 if 82598, can be many if 82599 */
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 1525c86..07a9410 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -834,8 +834,8 @@ static void ixgbe_get_ringparam(struct net_device *netdev,
                                 struct ethtool_ringparam *ring)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	struct ixgbe_ring *tx_ring = adapter->tx_ring;
-	struct ixgbe_ring *rx_ring = adapter->rx_ring;
+	struct ixgbe_ring *tx_ring = adapter->tx_ring[0];
+	struct ixgbe_ring *rx_ring = adapter->rx_ring[0];
 
 	ring->rx_max_pending = IXGBE_MAX_RXD;
 	ring->tx_max_pending = IXGBE_MAX_TXD;
@@ -867,8 +867,8 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
 	new_tx_count = min(new_tx_count, (u32)IXGBE_MAX_TXD);
 	new_tx_count = ALIGN(new_tx_count, IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE);
 
-	if ((new_tx_count == adapter->tx_ring->count) &&
-	    (new_rx_count == adapter->rx_ring->count)) {
+	if ((new_tx_count == adapter->tx_ring[0]->count) &&
+	    (new_rx_count == adapter->rx_ring[0]->count)) {
 		/* nothing to do */
 		return 0;
 	}
@@ -878,25 +878,24 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
 
 	if (!netif_running(adapter->netdev)) {
 		for (i = 0; i < adapter->num_tx_queues; i++)
-			adapter->tx_ring[i].count = new_tx_count;
+			adapter->tx_ring[i]->count = new_tx_count;
 		for (i = 0; i < adapter->num_rx_queues; i++)
-			adapter->rx_ring[i].count = new_rx_count;
+			adapter->rx_ring[i]->count = new_rx_count;
 		adapter->tx_ring_count = new_tx_count;
 		adapter->rx_ring_count = new_rx_count;
-		goto err_setup;
+		goto clear_reset;
 	}
 
-	temp_tx_ring = kcalloc(adapter->num_tx_queues,
-	                       sizeof(struct ixgbe_ring), GFP_KERNEL);
+	temp_tx_ring = vmalloc(adapter->num_tx_queues * sizeof(struct ixgbe_ring));
 	if (!temp_tx_ring) {
 		err = -ENOMEM;
-		goto err_setup;
+		goto clear_reset;
 	}
 
 	if (new_tx_count != adapter->tx_ring_count) {
-		memcpy(temp_tx_ring, adapter->tx_ring,
-		       adapter->num_tx_queues * sizeof(struct ixgbe_ring));
 		for (i = 0; i < adapter->num_tx_queues; i++) {
+			memcpy(&temp_tx_ring[i], adapter->tx_ring[i],
+			       sizeof(struct ixgbe_ring));
 			temp_tx_ring[i].count = new_tx_count;
 			err = ixgbe_setup_tx_resources(adapter,
 			                               &temp_tx_ring[i]);
@@ -904,28 +903,24 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
 				while (i) {
 					i--;
 					ixgbe_free_tx_resources(adapter,
-					                        &temp_tx_ring[i]);
+					                      &temp_tx_ring[i]);
 				}
-				goto err_setup;
+				goto clear_reset;
 			}
 		}
 		need_update = true;
 	}
 
-	temp_rx_ring = kcalloc(adapter->num_rx_queues,
-	                       sizeof(struct ixgbe_ring), GFP_KERNEL);
-	if ((!temp_rx_ring) && (need_update)) {
-		for (i = 0; i < adapter->num_tx_queues; i++)
-			ixgbe_free_tx_resources(adapter, &temp_tx_ring[i]);
-		kfree(temp_tx_ring);
+	temp_rx_ring = vmalloc(adapter->num_rx_queues * sizeof(struct ixgbe_ring));
+	if (!temp_rx_ring) {
 		err = -ENOMEM;
 		goto err_setup;
 	}
 
 	if (new_rx_count != adapter->rx_ring_count) {
-		memcpy(temp_rx_ring, adapter->rx_ring,
-		       adapter->num_rx_queues * sizeof(struct ixgbe_ring));
 		for (i = 0; i < adapter->num_rx_queues; i++) {
+			memcpy(&temp_rx_ring[i], adapter->rx_ring[i],
+			       sizeof(struct ixgbe_ring));
 			temp_rx_ring[i].count = new_rx_count;
 			err = ixgbe_setup_rx_resources(adapter,
 			                               &temp_rx_ring[i]);
@@ -947,22 +942,32 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
 
 		/* tx */
 		if (new_tx_count != adapter->tx_ring_count) {
-			kfree(adapter->tx_ring);
-			adapter->tx_ring = temp_tx_ring;
-			temp_tx_ring = NULL;
+			for (i = 0; i < adapter->num_tx_queues; i++) {
+				ixgbe_free_tx_resources(adapter,
+				                        adapter->tx_ring[i]);
+				memcpy(adapter->tx_ring[i], &temp_tx_ring[i],
+				       sizeof(struct ixgbe_ring));
+			}
 			adapter->tx_ring_count = new_tx_count;
 		}
 
 		/* rx */
 		if (new_rx_count != adapter->rx_ring_count) {
-			kfree(adapter->rx_ring);
-			adapter->rx_ring = temp_rx_ring;
-			temp_rx_ring = NULL;
+			for (i = 0; i < adapter->num_rx_queues; i++) {
+				ixgbe_free_rx_resources(adapter,
+				                        adapter->rx_ring[i]);
+				memcpy(adapter->rx_ring[i], &temp_rx_ring[i],
+				       sizeof(struct ixgbe_ring));
+			}
 			adapter->rx_ring_count = new_rx_count;
 		}
 		ixgbe_up(adapter);
 	}
+
+	vfree(temp_rx_ring);
 err_setup:
+	vfree(temp_tx_ring);
+clear_reset:
 	clear_bit(__IXGBE_RESETTING, &adapter->state);
 	return err;
 }
@@ -1007,13 +1012,13 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
 		           sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
 	}
 	for (j = 0; j < adapter->num_tx_queues; j++) {
-		queue_stat = (u64 *)&adapter->tx_ring[j].stats;
+		queue_stat = (u64 *)&adapter->tx_ring[j]->stats;
 		for (k = 0; k < stat_count; k++)
 			data[i + k] = queue_stat[k];
 		i += k;
 	}
 	for (j = 0; j < adapter->num_rx_queues; j++) {
-		queue_stat = (u64 *)&adapter->rx_ring[j].stats;
+		queue_stat = (u64 *)&adapter->rx_ring[j]->stats;
 		for (k = 0; k < stat_count; k++)
 			data[i + k] = queue_stat[k];
 		i += k;
@@ -1627,7 +1632,7 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)
 	reg_data |= IXGBE_RXDCTL_ENABLE;
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(0), reg_data);
 	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
-		int j = adapter->rx_ring[0].reg_idx;
+		int j = adapter->rx_ring[0]->reg_idx;
 		u32 k;
 		for (k = 0; k < 10; k++) {
 			if (IXGBE_READ_REG(&adapter->hw,
@@ -2011,7 +2016,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
-	ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0].work_limit;
+	ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0]->work_limit;
 
 	/* only valid if in constant ITR mode */
 	switch (adapter->rx_itr_setting) {
@@ -2064,7 +2069,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
 		return -EINVAL;
 
 	if (ec->tx_max_coalesced_frames_irq)
-		adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq;
+		adapter->tx_ring[0]->work_limit = ec->tx_max_coalesced_frames_irq;
 
 	if (ec->rx_coalesce_usecs > 1) {
 		/* check the limits */
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c
index e9a20c8..4123dec 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ixgbe/ixgbe_fcoe.c
@@ -525,7 +525,7 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
 		for (i = 0; i < IXGBE_FCRETA_SIZE; i++) {
 			fcoe_i = f->mask + i % f->indices;
 			fcoe_i &= IXGBE_FCRETA_ENTRY_MASK;
-			fcoe_q = adapter->rx_ring[fcoe_i].reg_idx;
+			fcoe_q = adapter->rx_ring[fcoe_i]->reg_idx;
 			IXGBE_WRITE_REG(hw, IXGBE_FCRETA(i), fcoe_q);
 		}
 		IXGBE_WRITE_REG(hw, IXGBE_FCRECTL, IXGBE_FCRECTL_ENA);
@@ -533,7 +533,7 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
 	} else  {
 		/* Use single rx queue for FCoE */
 		fcoe_i = f->mask;
-		fcoe_q = adapter->rx_ring[fcoe_i].reg_idx;
+		fcoe_q = adapter->rx_ring[fcoe_i]->reg_idx;
 		IXGBE_WRITE_REG(hw, IXGBE_FCRECTL, 0);
 		IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FCOE),
 				IXGBE_ETQS_QUEUE_EN |
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 315369f..5914b9b 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -494,7 +494,7 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
 {
 	u32 rxctrl;
 	int cpu = get_cpu();
-	int q = rx_ring - adapter->rx_ring;
+	int q = rx_ring->reg_idx;
 
 	if (rx_ring->cpu != cpu) {
 		rxctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q));
@@ -522,7 +522,7 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
 {
 	u32 txctrl;
 	int cpu = get_cpu();
-	int q = tx_ring - adapter->tx_ring;
+	int q = tx_ring->reg_idx;
 	struct ixgbe_hw *hw = &adapter->hw;
 
 	if (tx_ring->cpu != cpu) {
@@ -556,12 +556,12 @@ static void ixgbe_setup_dca(struct ixgbe_adapter *adapter)
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2);
 
 	for (i = 0; i < adapter->num_tx_queues; i++) {
-		adapter->tx_ring[i].cpu = -1;
-		ixgbe_update_tx_dca(adapter, &adapter->tx_ring[i]);
+		adapter->tx_ring[i]->cpu = -1;
+		ixgbe_update_tx_dca(adapter, adapter->tx_ring[i]);
 	}
 	for (i = 0; i < adapter->num_rx_queues; i++) {
-		adapter->rx_ring[i].cpu = -1;
-		ixgbe_update_rx_dca(adapter, &adapter->rx_ring[i]);
+		adapter->rx_ring[i]->cpu = -1;
+		ixgbe_update_rx_dca(adapter, adapter->rx_ring[i]);
 	}
 }
 
@@ -1032,7 +1032,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
 		                       adapter->num_rx_queues);
 
 		for (i = 0; i < q_vector->rxr_count; i++) {
-			j = adapter->rx_ring[r_idx].reg_idx;
+			j = adapter->rx_ring[r_idx]->reg_idx;
 			ixgbe_set_ivar(adapter, 0, j, v_idx);
 			r_idx = find_next_bit(q_vector->rxr_idx,
 			                      adapter->num_rx_queues,
@@ -1042,7 +1042,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
 		                       adapter->num_tx_queues);
 
 		for (i = 0; i < q_vector->txr_count; i++) {
-			j = adapter->tx_ring[r_idx].reg_idx;
+			j = adapter->tx_ring[r_idx]->reg_idx;
 			ixgbe_set_ivar(adapter, 1, j, v_idx);
 			r_idx = find_next_bit(q_vector->txr_idx,
 			                      adapter->num_tx_queues,
@@ -1182,7 +1182,7 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
 
 	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
 	for (i = 0; i < q_vector->txr_count; i++) {
-		tx_ring = &(adapter->tx_ring[r_idx]);
+		tx_ring = adapter->tx_ring[r_idx];
 		ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
 		                           q_vector->tx_itr,
 		                           tx_ring->total_packets,
@@ -1197,7 +1197,7 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
 
 	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
 	for (i = 0; i < q_vector->rxr_count; i++) {
-		rx_ring = &(adapter->rx_ring[r_idx]);
+		rx_ring = adapter->rx_ring[r_idx];
 		ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
 		                           q_vector->rx_itr,
 		                           rx_ring->total_packets,
@@ -1319,7 +1319,7 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
 			netif_tx_stop_all_queues(netdev);
 			for (i = 0; i < adapter->num_tx_queues; i++) {
 				struct ixgbe_ring *tx_ring =
-				                           &adapter->tx_ring[i];
+				                            adapter->tx_ring[i];
 				if (test_and_clear_bit(__IXGBE_FDIR_INIT_DONE,
 				                       &tx_ring->reinit_state))
 					schedule_work(&adapter->fdir_reinit_task);
@@ -1378,7 +1378,7 @@ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
 
 	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
 	for (i = 0; i < q_vector->txr_count; i++) {
-		tx_ring = &(adapter->tx_ring[r_idx]);
+		tx_ring = adapter->tx_ring[r_idx];
 		tx_ring->total_bytes = 0;
 		tx_ring->total_packets = 0;
 		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
@@ -1406,7 +1406,7 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data)
 
 	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
 	for (i = 0;  i < q_vector->rxr_count; i++) {
-		rx_ring = &(adapter->rx_ring[r_idx]);
+		rx_ring = adapter->rx_ring[r_idx];
 		rx_ring->total_bytes = 0;
 		rx_ring->total_packets = 0;
 		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
@@ -1436,7 +1436,7 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
 
 	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
 	for (i = 0; i < q_vector->txr_count; i++) {
-		ring = &(adapter->tx_ring[r_idx]);
+		ring = adapter->tx_ring[r_idx];
 		ring->total_bytes = 0;
 		ring->total_packets = 0;
 		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
@@ -1445,7 +1445,7 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
 
 	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
 	for (i = 0; i < q_vector->rxr_count; i++) {
-		ring = &(adapter->rx_ring[r_idx]);
+		ring = adapter->rx_ring[r_idx];
 		ring->total_bytes = 0;
 		ring->total_packets = 0;
 		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
@@ -1476,7 +1476,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
 	long r_idx;
 
 	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
-	rx_ring = &(adapter->rx_ring[r_idx]);
+	rx_ring = adapter->rx_ring[r_idx];
 #ifdef CONFIG_IXGBE_DCA
 	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
 		ixgbe_update_rx_dca(adapter, rx_ring);
@@ -1517,7 +1517,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
 
 	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
 	for (i = 0; i < q_vector->txr_count; i++) {
-		ring = &(adapter->tx_ring[r_idx]);
+		ring = adapter->tx_ring[r_idx];
 #ifdef CONFIG_IXGBE_DCA
 		if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
 			ixgbe_update_tx_dca(adapter, ring);
@@ -1533,7 +1533,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
 	budget = max(budget, 1);
 	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
 	for (i = 0; i < q_vector->rxr_count; i++) {
-		ring = &(adapter->rx_ring[r_idx]);
+		ring = adapter->rx_ring[r_idx];
 #ifdef CONFIG_IXGBE_DCA
 		if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
 			ixgbe_update_rx_dca(adapter, ring);
@@ -1544,7 +1544,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
 	}
 
 	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
-	ring = &(adapter->rx_ring[r_idx]);
+	ring = adapter->rx_ring[r_idx];
 	/* If all Rx work done, exit the polling mode */
 	if (work_done < budget) {
 		napi_complete(napi);
@@ -1577,7 +1577,7 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
 	long r_idx;
 
 	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
-	tx_ring = &(adapter->tx_ring[r_idx]);
+	tx_ring = adapter->tx_ring[r_idx];
 #ifdef CONFIG_IXGBE_DCA
 	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
 		ixgbe_update_tx_dca(adapter, tx_ring);
@@ -1762,8 +1762,8 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter)
 	struct ixgbe_q_vector *q_vector = adapter->q_vector[0];
 	u8 current_itr;
 	u32 new_itr = q_vector->eitr;
-	struct ixgbe_ring *rx_ring = &adapter->rx_ring[0];
-	struct ixgbe_ring *tx_ring = &adapter->tx_ring[0];
+	struct ixgbe_ring *rx_ring = adapter->rx_ring[0];
+	struct ixgbe_ring *tx_ring = adapter->tx_ring[0];
 
 	q_vector->tx_itr = ixgbe_update_itr(adapter, new_itr,
 	                                    q_vector->tx_itr,
@@ -1875,10 +1875,10 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
 	ixgbe_check_fan_failure(adapter, eicr);
 
 	if (napi_schedule_prep(&(q_vector->napi))) {
-		adapter->tx_ring[0].total_packets = 0;
-		adapter->tx_ring[0].total_bytes = 0;
-		adapter->rx_ring[0].total_packets = 0;
-		adapter->rx_ring[0].total_bytes = 0;
+		adapter->tx_ring[0]->total_packets = 0;
+		adapter->tx_ring[0]->total_bytes = 0;
+		adapter->rx_ring[0]->total_packets = 0;
+		adapter->rx_ring[0]->total_bytes = 0;
 		/* would disable interrupts here but EIAM disabled it */
 		__napi_schedule(&(q_vector->napi));
 	}
@@ -2010,7 +2010,7 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
 
 	/* Setup the HW Tx Head and Tail descriptor pointers */
 	for (i = 0; i < adapter->num_tx_queues; i++) {
-		struct ixgbe_ring *ring = &adapter->tx_ring[i];
+		struct ixgbe_ring *ring = adapter->tx_ring[i];
 		j = ring->reg_idx;
 		tdba = ring->dma;
 		tdlen = ring->count * sizeof(union ixgbe_adv_tx_desc);
@@ -2020,8 +2020,8 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
 		IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j), tdlen);
 		IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0);
 		IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0);
-		adapter->tx_ring[i].head = IXGBE_TDH(j);
-		adapter->tx_ring[i].tail = IXGBE_TDT(j);
+		adapter->tx_ring[i]->head = IXGBE_TDH(j);
+		adapter->tx_ring[i]->tail = IXGBE_TDT(j);
 		/*
 		 * Disable Tx Head Writeback RO bit, since this hoses
 		 * bookkeeping if things aren't delivered in order.
@@ -2168,7 +2168,7 @@ static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, int index)
 	u32 rscctrl;
 	int rx_buf_len;
 
-	rx_ring = &adapter->rx_ring[index];
+	rx_ring = adapter->rx_ring[index];
 	j = rx_ring->reg_idx;
 	rx_buf_len = rx_ring->rx_buf_len;
 	rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j));
@@ -2266,7 +2266,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
 #endif
 	IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
 
-	rdlen = adapter->rx_ring[0].count * sizeof(union ixgbe_adv_rx_desc);
+	rdlen = adapter->rx_ring[0]->count * sizeof(union ixgbe_adv_rx_desc);
 	/* disable receives while setting up the descriptors */
 	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
 	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN);
@@ -2276,7 +2276,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
 	 * the Base and Length of the Rx Descriptor Ring
 	 */
 	for (i = 0; i < adapter->num_rx_queues; i++) {
-		rx_ring = &adapter->rx_ring[i];
+		rx_ring = adapter->rx_ring[i];
 		rdba = rx_ring->dma;
 		j = rx_ring->reg_idx;
 		IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), (rdba & DMA_BIT_MASK(32)));
@@ -2483,7 +2483,7 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev,
 	} else if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
 		for (i = 0; i < adapter->num_rx_queues; i++) {
 			u32 ctrl;
-			j = adapter->rx_ring[i].reg_idx;
+			j = adapter->rx_ring[i]->reg_idx;
 			ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(j));
 			ctrl |= IXGBE_RXDCTL_VME;
 			IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(j), ctrl);
@@ -2646,7 +2646,7 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
 	ixgbe_dcb_hw_config(&adapter->hw, &adapter->dcb_cfg);
 
 	for (i = 0; i < adapter->num_tx_queues; i++) {
-		j = adapter->tx_ring[i].reg_idx;
+		j = adapter->tx_ring[i]->reg_idx;
 		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
 		/* PThresh workaround for Tx hang with DFP enabled. */
 		txdctl |= 32;
@@ -2663,7 +2663,7 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
 		vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
 		IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
 		for (i = 0; i < adapter->num_rx_queues; i++) {
-			j = adapter->rx_ring[i].reg_idx;
+			j = adapter->rx_ring[i]->reg_idx;
 			vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
 			vlnctrl |= IXGBE_RXDCTL_VME;
 			IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(j), vlnctrl);
@@ -2703,7 +2703,7 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
 #endif /* IXGBE_FCOE */
 	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
 		for (i = 0; i < adapter->num_tx_queues; i++)
-			adapter->tx_ring[i].atr_sample_rate =
+			adapter->tx_ring[i]->atr_sample_rate =
 			                               adapter->atr_sample_rate;
 		ixgbe_init_fdir_signature_82599(hw, adapter->fdir_pballoc);
 	} else if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) {
@@ -2713,8 +2713,8 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
 	ixgbe_configure_tx(adapter);
 	ixgbe_configure_rx(adapter);
 	for (i = 0; i < adapter->num_rx_queues; i++)
-		ixgbe_alloc_rx_buffers(adapter, &adapter->rx_ring[i],
-		                       (adapter->rx_ring[i].count - 1));
+		ixgbe_alloc_rx_buffers(adapter, adapter->rx_ring[i],
+		                       (adapter->rx_ring[i]->count - 1));
 }
 
 static inline bool ixgbe_is_sfp(struct ixgbe_hw *hw)
@@ -2797,7 +2797,7 @@ link_cfg_out:
 static inline void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter,
 	                                      int rxr)
 {
-	int j = adapter->rx_ring[rxr].reg_idx;
+	int j = adapter->rx_ring[rxr]->reg_idx;
 	int k;
 
 	for (k = 0; k < IXGBE_MAX_RX_DESC_POLL; k++) {
@@ -2811,8 +2811,8 @@ static inline void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter,
 		DPRINTK(DRV, ERR, "RXDCTL.ENABLE on Rx queue %d "
 		        "not set within the polling period\n", rxr);
 	}
-	ixgbe_release_rx_desc(&adapter->hw, &adapter->rx_ring[rxr],
-	                      (adapter->rx_ring[rxr].count - 1));
+	ixgbe_release_rx_desc(&adapter->hw, adapter->rx_ring[rxr],
+	                      (adapter->rx_ring[rxr]->count - 1));
 }
 
 static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
@@ -2899,7 +2899,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
 	}
 
 	for (i = 0; i < adapter->num_tx_queues; i++) {
-		j = adapter->tx_ring[i].reg_idx;
+		j = adapter->tx_ring[i]->reg_idx;
 		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
 		/* enable WTHRESH=8 descriptors, to encourage burst writeback */
 		txdctl |= (8 << 16);
@@ -2913,7 +2913,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
 		IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl);
 	}
 	for (i = 0; i < adapter->num_tx_queues; i++) {
-		j = adapter->tx_ring[i].reg_idx;
+		j = adapter->tx_ring[i]->reg_idx;
 		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
 		txdctl |= IXGBE_TXDCTL_ENABLE;
 		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
@@ -2932,7 +2932,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
 	}
 
 	for (i = 0; i < num_rx_rings; i++) {
-		j = adapter->rx_ring[i].reg_idx;
+		j = adapter->rx_ring[i]->reg_idx;
 		rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
 		/* enable PTHRESH=32 descriptors (half the internal cache)
 		 * and HTHRESH=0 descriptors (to minimize latency on fetch),
@@ -3006,7 +3006,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
 
 	for (i = 0; i < adapter->num_tx_queues; i++)
 		set_bit(__IXGBE_FDIR_INIT_DONE,
-		        &(adapter->tx_ring[i].reinit_state));
+		        &(adapter->tx_ring[i]->reinit_state));
 
 	/* enable transmits */
 	netif_tx_start_all_queues(netdev);
@@ -3177,7 +3177,7 @@ static void ixgbe_clean_all_rx_rings(struct ixgbe_adapter *adapter)
 	int i;
 
 	for (i = 0; i < adapter->num_rx_queues; i++)
-		ixgbe_clean_rx_ring(adapter, &adapter->rx_ring[i]);
+		ixgbe_clean_rx_ring(adapter, adapter->rx_ring[i]);
 }
 
 /**
@@ -3189,7 +3189,7 @@ static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter)
 	int i;
 
 	for (i = 0; i < adapter->num_tx_queues; i++)
-		ixgbe_clean_tx_ring(adapter, &adapter->tx_ring[i]);
+		ixgbe_clean_tx_ring(adapter, adapter->tx_ring[i]);
 }
 
 void ixgbe_down(struct ixgbe_adapter *adapter)
@@ -3240,7 +3240,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
 
 	/* disable transmits in the hardware now that interrupts are off */
 	for (i = 0; i < adapter->num_tx_queues; i++) {
-		j = adapter->tx_ring[i].reg_idx;
+		j = adapter->tx_ring[i]->reg_idx;
 		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
 		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j),
 		                (txdctl & ~IXGBE_TXDCTL_ENABLE));
@@ -3280,13 +3280,13 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
 
 #ifdef CONFIG_IXGBE_DCA
 	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
-		ixgbe_update_tx_dca(adapter, adapter->tx_ring);
-		ixgbe_update_rx_dca(adapter, adapter->rx_ring);
+		ixgbe_update_tx_dca(adapter, adapter->tx_ring[0]);
+		ixgbe_update_rx_dca(adapter, adapter->rx_ring[0]);
 	}
 #endif
 
-	tx_clean_complete = ixgbe_clean_tx_irq(q_vector, adapter->tx_ring);
-	ixgbe_clean_rx_irq(q_vector, adapter->rx_ring, &work_done, budget);
+	tx_clean_complete = ixgbe_clean_tx_irq(q_vector, adapter->tx_ring[0]);
+	ixgbe_clean_rx_irq(q_vector, adapter->rx_ring[0], &work_done, budget);
 
 	if (!tx_clean_complete)
 		work_done = budget;
@@ -3574,9 +3574,9 @@ static inline bool ixgbe_cache_ring_rss(struct ixgbe_adapter *adapter)
 
 	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
 		for (i = 0; i < adapter->num_rx_queues; i++)
-			adapter->rx_ring[i].reg_idx = i;
+			adapter->rx_ring[i]->reg_idx = i;
 		for (i = 0; i < adapter->num_tx_queues; i++)
-			adapter->tx_ring[i].reg_idx = i;
+			adapter->tx_ring[i]->reg_idx = i;
 		ret = true;
 	} else {
 		ret = false;
@@ -3603,8 +3603,8 @@ static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter)
 		if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
 			/* the number of queues is assumed to be symmetric */
 			for (i = 0; i < dcb_i; i++) {
-				adapter->rx_ring[i].reg_idx = i << 3;
-				adapter->tx_ring[i].reg_idx = i << 2;
+				adapter->rx_ring[i]->reg_idx = i << 3;
+				adapter->tx_ring[i]->reg_idx = i << 2;
 			}
 			ret = true;
 		} else if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
@@ -3622,18 +3622,18 @@ static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter)
 				 * Rx TC0-TC7 are offset by 16 queues each
 				 */
 				for (i = 0; i < 3; i++) {
-					adapter->tx_ring[i].reg_idx = i << 5;
-					adapter->rx_ring[i].reg_idx = i << 4;
+					adapter->tx_ring[i]->reg_idx = i << 5;
+					adapter->rx_ring[i]->reg_idx = i << 4;
 				}
 				for ( ; i < 5; i++) {
-					adapter->tx_ring[i].reg_idx =
+					adapter->tx_ring[i]->reg_idx =
 					                         ((i + 2) << 4);
-					adapter->rx_ring[i].reg_idx = i << 4;
+					adapter->rx_ring[i]->reg_idx = i << 4;
 				}
 				for ( ; i < dcb_i; i++) {
-					adapter->tx_ring[i].reg_idx =
+					adapter->tx_ring[i]->reg_idx =
 					                         ((i + 8) << 3);
-					adapter->rx_ring[i].reg_idx = i << 4;
+					adapter->rx_ring[i]->reg_idx = i << 4;
 				}
 
 				ret = true;
@@ -3646,12 +3646,12 @@ static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter)
 				 *
 				 * Rx TC0-TC3 are offset by 32 queues each
 				 */
-				adapter->tx_ring[0].reg_idx = 0;
-				adapter->tx_ring[1].reg_idx = 64;
-				adapter->tx_ring[2].reg_idx = 96;
-				adapter->tx_ring[3].reg_idx = 112;
+				adapter->tx_ring[0]->reg_idx = 0;
+				adapter->tx_ring[1]->reg_idx = 64;
+				adapter->tx_ring[2]->reg_idx = 96;
+				adapter->tx_ring[3]->reg_idx = 112;
 				for (i = 0 ; i < dcb_i; i++)
-					adapter->rx_ring[i].reg_idx = i << 5;
+					adapter->rx_ring[i]->reg_idx = i << 5;
 
 				ret = true;
 			} else {
@@ -3684,9 +3684,9 @@ static bool inline ixgbe_cache_ring_fdir(struct ixgbe_adapter *adapter)
 	    ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
 	     (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))) {
 		for (i = 0; i < adapter->num_rx_queues; i++)
-			adapter->rx_ring[i].reg_idx = i;
+			adapter->rx_ring[i]->reg_idx = i;
 		for (i = 0; i < adapter->num_tx_queues; i++)
-			adapter->tx_ring[i].reg_idx = i;
+			adapter->tx_ring[i]->reg_idx = i;
 		ret = true;
 	}
 
@@ -3714,8 +3714,8 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter)
 
 			ixgbe_cache_ring_dcb(adapter);
 			/* find out queues in TC for FCoE */
-			fcoe_rx_i = adapter->rx_ring[fcoe->tc].reg_idx + 1;
-			fcoe_tx_i = adapter->tx_ring[fcoe->tc].reg_idx + 1;
+			fcoe_rx_i = adapter->rx_ring[fcoe->tc]->reg_idx + 1;
+			fcoe_tx_i = adapter->tx_ring[fcoe->tc]->reg_idx + 1;
 			/*
 			 * In 82599, the number of Tx queues for each traffic
 			 * class for both 8-TC and 4-TC modes are:
@@ -3746,8 +3746,8 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter)
 			fcoe_tx_i = f->mask;
 		}
 		for (i = 0; i < f->indices; i++, fcoe_rx_i++, fcoe_tx_i++) {
-			adapter->rx_ring[f->mask + i].reg_idx = fcoe_rx_i;
-			adapter->tx_ring[f->mask + i].reg_idx = fcoe_tx_i;
+			adapter->rx_ring[f->mask + i]->reg_idx = fcoe_rx_i;
+			adapter->tx_ring[f->mask + i]->reg_idx = fcoe_tx_i;
 		}
 		ret = true;
 	}
@@ -3765,8 +3765,8 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter)
  */
 static inline bool ixgbe_cache_ring_sriov(struct ixgbe_adapter *adapter)
 {
-	adapter->rx_ring[0].reg_idx = adapter->num_vfs * 2;
-	adapter->tx_ring[0].reg_idx = adapter->num_vfs * 2;
+	adapter->rx_ring[0]->reg_idx = adapter->num_vfs * 2;
+	adapter->tx_ring[0]->reg_idx = adapter->num_vfs * 2;
 	if (adapter->num_vfs)
 		return true;
 	else
@@ -3787,8 +3787,8 @@ static inline bool ixgbe_cache_ring_sriov(struct ixgbe_adapter *adapter)
 static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
 {
 	/* start with default case */
-	adapter->rx_ring[0].reg_idx = 0;
-	adapter->tx_ring[0].reg_idx = 0;
+	adapter->rx_ring[0]->reg_idx = 0;
+	adapter->tx_ring[0]->reg_idx = 0;
 
 	if (ixgbe_cache_ring_sriov(adapter))
 		return;
@@ -3821,33 +3821,63 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
 static int ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
 {
 	int i;
-
-	adapter->tx_ring = kcalloc(adapter->num_tx_queues,
-	                           sizeof(struct ixgbe_ring), GFP_KERNEL);
-	if (!adapter->tx_ring)
-		goto err_tx_ring_allocation;
-
-	adapter->rx_ring = kcalloc(adapter->num_rx_queues,
-	                           sizeof(struct ixgbe_ring), GFP_KERNEL);
-	if (!adapter->rx_ring)
-		goto err_rx_ring_allocation;
+	int orig_node = adapter->node;
 
 	for (i = 0; i < adapter->num_tx_queues; i++) {
-		adapter->tx_ring[i].count = adapter->tx_ring_count;
-		adapter->tx_ring[i].queue_index = i;
+		struct ixgbe_ring *ring = adapter->tx_ring[i];
+		if (orig_node == -1) {
+			int cur_node = next_online_node(adapter->node);
+			if (cur_node == MAX_NUMNODES)
+				cur_node = first_online_node;
+			adapter->node = cur_node;
+		}
+		ring = kzalloc_node(sizeof(struct ixgbe_ring), GFP_KERNEL,
+		                    adapter->node);
+		if (!ring)
+			ring = kzalloc(sizeof(struct ixgbe_ring), GFP_KERNEL);
+		if (!ring)
+			goto err_tx_ring_allocation;
+		ring->count = adapter->tx_ring_count;
+		ring->queue_index = i;
+		ring->numa_node = adapter->node;
+
+		adapter->tx_ring[i] = ring;
 	}
 
+	/* Restore the adapter's original node */
+	adapter->node = orig_node;
+
 	for (i = 0; i < adapter->num_rx_queues; i++) {
-		adapter->rx_ring[i].count = adapter->rx_ring_count;
-		adapter->rx_ring[i].queue_index = i;
+		struct ixgbe_ring *ring = adapter->rx_ring[i];
+		if (orig_node == -1) {
+			int cur_node = next_online_node(adapter->node);
+			if (cur_node == MAX_NUMNODES)
+				cur_node = first_online_node;
+			adapter->node = cur_node;
+		}
+		ring = kzalloc_node(sizeof(struct ixgbe_ring), GFP_KERNEL,
+		                    adapter->node);
+		if (!ring)
+			ring = kzalloc(sizeof(struct ixgbe_ring), GFP_KERNEL);
+		if (!ring)
+			goto err_rx_ring_allocation;
+		ring->count = adapter->rx_ring_count;
+		ring->queue_index = i;
+		ring->numa_node = adapter->node;
+
+		adapter->rx_ring[i] = ring;
 	}
 
+	/* Restore the adapter's original node */
+	adapter->node = orig_node;
+
 	ixgbe_cache_ring_register(adapter);
 
 	return 0;
 
 err_rx_ring_allocation:
-	kfree(adapter->tx_ring);
+	for (i = 0; i < adapter->num_tx_queues; i++)
+		kfree(adapter->tx_ring[i]);
 err_tx_ring_allocation:
 	return -ENOMEM;
 }
@@ -4077,10 +4107,16 @@ err_set_interrupt:
  **/
 void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter)
 {
-	kfree(adapter->tx_ring);
-	kfree(adapter->rx_ring);
-	adapter->tx_ring = NULL;
-	adapter->rx_ring = NULL;
+	int i;
+
+	for (i = 0; i < adapter->num_tx_queues; i++) {
+		kfree(adapter->tx_ring[i]);
+		adapter->tx_ring[i] = NULL;
+	}
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		kfree(adapter->rx_ring[i]);
+		adapter->rx_ring[i] = NULL;
+	}
 
 	ixgbe_free_q_vectors(adapter);
 	ixgbe_reset_interrupt_capability(adapter);
@@ -4272,7 +4308,7 @@ int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter,
 	int size;
 
 	size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count;
-	tx_ring->tx_buffer_info = vmalloc_node(size, adapter->node);
+	tx_ring->tx_buffer_info = vmalloc_node(size, tx_ring->numa_node);
 	if (!tx_ring->tx_buffer_info)
 		tx_ring->tx_buffer_info = vmalloc(size);
 	if (!tx_ring->tx_buffer_info)
@@ -4314,25 +4350,15 @@ err:
 static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter)
 {
 	int i, err = 0;
-	int orig_node = adapter->node;
 
 	for (i = 0; i < adapter->num_tx_queues; i++) {
-		if (orig_node == -1) {
-			int cur_node = next_online_node(adapter->node);
-			if (cur_node == MAX_NUMNODES)
-				cur_node = first_online_node;
-			adapter->node = cur_node;
-		}
-		err = ixgbe_setup_tx_resources(adapter, &adapter->tx_ring[i]);
+		err = ixgbe_setup_tx_resources(adapter, adapter->tx_ring[i]);
 		if (!err)
 			continue;
 		DPRINTK(PROBE, ERR, "Allocation for Tx Queue %u failed\n", i);
 		break;
 	}
 
-	/* reset the node back to its starting value */
-	adapter->node = orig_node;
-
 	return err;
 }
 
@@ -4396,25 +4422,15 @@ alloc_failed:
 static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter)
 {
 	int i, err = 0;
-	int orig_node = adapter->node;
 
 	for (i = 0; i < adapter->num_rx_queues; i++) {
-		if (orig_node == -1) {
-			int cur_node = next_online_node(adapter->node);
-			if (cur_node == MAX_NUMNODES)
-				cur_node = first_online_node;
-			adapter->node = cur_node;
-		}
-		err = ixgbe_setup_rx_resources(adapter, &adapter->rx_ring[i]);
+		err = ixgbe_setup_rx_resources(adapter, adapter->rx_ring[i]);
 		if (!err)
 			continue;
 		DPRINTK(PROBE, ERR, "Allocation for Rx Queue %u failed\n", i);
 		break;
 	}
 
-	/* reset the node back to its starting value */
-	adapter->node = orig_node;
-
 	return err;
 }
 
@@ -4451,8 +4467,8 @@ static void ixgbe_free_all_tx_resources(struct ixgbe_adapter *adapter)
 	int i;
 
 	for (i = 0; i < adapter->num_tx_queues; i++)
-		if (adapter->tx_ring[i].desc)
-			ixgbe_free_tx_resources(adapter, &adapter->tx_ring[i]);
+		if (adapter->tx_ring[i]->desc)
+			ixgbe_free_tx_resources(adapter, adapter->tx_ring[i]);
 }
 
 /**
@@ -4488,8 +4504,8 @@ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter)
 	int i;
 
 	for (i = 0; i < adapter->num_rx_queues; i++)
-		if (adapter->rx_ring[i].desc)
-			ixgbe_free_rx_resources(adapter, &adapter->rx_ring[i]);
+		if (adapter->rx_ring[i]->desc)
+			ixgbe_free_rx_resources(adapter, adapter->rx_ring[i]);
 }
 
 /**
@@ -4766,8 +4782,8 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
 			adapter->hw_rx_no_dma_resources +=
 			                     IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
 		for (i = 0; i < adapter->num_rx_queues; i++) {
-			rsc_count += adapter->rx_ring[i].rsc_count;
-			rsc_flush += adapter->rx_ring[i].rsc_flush;
+			rsc_count += adapter->rx_ring[i]->rsc_count;
+			rsc_flush += adapter->rx_ring[i]->rsc_flush;
 		}
 		adapter->rsc_total_count = rsc_count;
 		adapter->rsc_total_flush = rsc_flush;
@@ -4775,11 +4791,11 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
 
 	/* gather some stats to the adapter struct that are per queue */
 	for (i = 0; i < adapter->num_tx_queues; i++)
-		restart_queue += adapter->tx_ring[i].restart_queue;
+		restart_queue += adapter->tx_ring[i]->restart_queue;
 	adapter->restart_queue = restart_queue;
 
 	for (i = 0; i < adapter->num_rx_queues; i++)
-		non_eop_descs += adapter->rx_ring[i].non_eop_descs;
+		non_eop_descs += adapter->rx_ring[i]->non_eop_descs;
 	adapter->non_eop_descs = non_eop_descs;
 
 	adapter->stats.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
@@ -5018,7 +5034,7 @@ static void ixgbe_fdir_reinit_task(struct work_struct *work)
 	if (ixgbe_reinit_fdir_tables_82599(hw) == 0) {
 		for (i = 0; i < adapter->num_tx_queues; i++)
 			set_bit(__IXGBE_FDIR_INIT_DONE,
-			        &(adapter->tx_ring[i].reinit_state));
+			        &(adapter->tx_ring[i]->reinit_state));
 	} else {
 		DPRINTK(PROBE, ERR, "failed to finish FDIR re-initialization, "
 		        "ignored adding FDIR ATR filters \n");
@@ -5115,7 +5131,7 @@ static void ixgbe_watchdog_task(struct work_struct *work)
 
 	if (!netif_carrier_ok(netdev)) {
 		for (i = 0; i < adapter->num_tx_queues; i++) {
-			tx_ring = &adapter->tx_ring[i];
+			tx_ring = adapter->tx_ring[i];
 			if (tx_ring->next_to_use != tx_ring->next_to_clean) {
 				some_tx_pending = 1;
 				break;
@@ -5614,7 +5630,7 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
 		}
 	}
 
-	tx_ring = &adapter->tx_ring[skb->queue_mapping];
+	tx_ring = adapter->tx_ring[skb->queue_mapping];
 
 	if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&
 	    (skb->protocol == htons(ETH_P_FCOE))) {


^ permalink raw reply related

* [net-next-2.6 PATCH v2 1/2] ixgbe: Allocate driver resources per NUMA node
From: Jeff Kirsher @ 2010-02-04  0:18 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Jesse Brandeburg, Peter P Waskiewicz Jr,
	Jeff Kirsher

From: Jesse Brandeburg <jesse.brandeburg@intel.com>

The default policy for the current driver is to do all its memory
allocation on whatever processor is running insmod/modprobe.  This
is less than optimal.

This driver's default mode of operation will be to use each node for each
subsequent transmit/receive queue.  The most efficient allocation will be
to then have the interrupts bound in such a way as to match up the
interrupt of the queue to the cpu where its memory was allocated.

Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/ixgbe/ixgbe.h      |    2 ++
 drivers/net/ixgbe/ixgbe_main.c |   37 ++++++++++++++++++++++++++++++++++---
 2 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index e576fb4..f34512e 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -400,6 +400,8 @@ struct ixgbe_adapter {
 	u32 wol;
 	u16 eeprom_version;
 
+	int node;
+
 	/* SR-IOV */
 	DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS);
 	unsigned int num_vfs;
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 6369852..315369f 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -3946,7 +3946,11 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
 	}
 
 	for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
-		q_vector = kzalloc(sizeof(struct ixgbe_q_vector), GFP_KERNEL);
+		q_vector = kzalloc_node(sizeof(struct ixgbe_q_vector),
+		                        GFP_KERNEL, adapter->node);
+		if (!q_vector)
+			q_vector = kzalloc(sizeof(struct ixgbe_q_vector),
+			                   GFP_KERNEL);
 		if (!q_vector)
 			goto err_out;
 		q_vector->adapter = adapter;
@@ -4246,6 +4250,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
 	/* enable rx csum by default */
 	adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
 
+	/* get assigned NUMA node */
+	adapter->node = dev_to_node(&pdev->dev);
+
 	set_bit(__IXGBE_DOWN, &adapter->state);
 
 	return 0;
@@ -4265,7 +4272,9 @@ int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter,
 	int size;
 
 	size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count;
-	tx_ring->tx_buffer_info = vmalloc(size);
+	tx_ring->tx_buffer_info = vmalloc_node(size, adapter->node);
+	if (!tx_ring->tx_buffer_info)
+		tx_ring->tx_buffer_info = vmalloc(size);
 	if (!tx_ring->tx_buffer_info)
 		goto err;
 	memset(tx_ring->tx_buffer_info, 0, size);
@@ -4305,8 +4314,15 @@ err:
 static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter)
 {
 	int i, err = 0;
+	int orig_node = adapter->node;
 
 	for (i = 0; i < adapter->num_tx_queues; i++) {
+		if (orig_node == -1) {
+			int cur_node = next_online_node(adapter->node);
+			if (cur_node == MAX_NUMNODES)
+				cur_node = first_online_node;
+			adapter->node = cur_node;
+		}
 		err = ixgbe_setup_tx_resources(adapter, &adapter->tx_ring[i]);
 		if (!err)
 			continue;
@@ -4314,6 +4330,9 @@ static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter)
 		break;
 	}
 
+	/* reset the node back to its starting value */
+	adapter->node = orig_node;
+
 	return err;
 }
 
@@ -4331,7 +4350,9 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
 	int size;
 
 	size = sizeof(struct ixgbe_rx_buffer) * rx_ring->count;
-	rx_ring->rx_buffer_info = vmalloc(size);
+	rx_ring->rx_buffer_info = vmalloc_node(size, adapter->node);
+	if (!rx_ring->rx_buffer_info)
+		rx_ring->rx_buffer_info = vmalloc(size);
 	if (!rx_ring->rx_buffer_info) {
 		DPRINTK(PROBE, ERR,
 		        "vmalloc allocation failed for the rx desc ring\n");
@@ -4375,8 +4396,15 @@ alloc_failed:
 static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter)
 {
 	int i, err = 0;
+	int orig_node = adapter->node;
 
 	for (i = 0; i < adapter->num_rx_queues; i++) {
+		if (orig_node == -1) {
+			int cur_node = next_online_node(adapter->node);
+			if (cur_node == MAX_NUMNODES)
+				cur_node = first_online_node;
+			adapter->node = cur_node;
+		}
 		err = ixgbe_setup_rx_resources(adapter, &adapter->rx_ring[i]);
 		if (!err)
 			continue;
@@ -4384,6 +4412,9 @@ static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter)
 		break;
 	}
 
+	/* reset the node back to its starting value */
+	adapter->node = orig_node;
+
 	return err;
 }
 


^ permalink raw reply related

* [PATCH v2 net-next-2.6] packet: Add GSO/csum offload support.
From: Sridhar Samudrala @ 2010-02-03 23:22 UTC (permalink / raw)
  To: Herbert Xu, Michael S. Tsirkin; +Cc: netdev

This patch adds GSO/checksum offload to af_packet sockets using
virtio_net_hdr. Based on Rusty's patch to add this support to tun.
It allows GSO/checksum offload to be enabled when using raw socket
backend with virtio_net.
Adds PACKET_VNET_HDR socket option to prepend virtio_net_hdr in the
receive path and process/skip virtio_net_hdr in the send path. This
option is only allowed with SOCK_RAW sockets attached to ethernet
type devices.

v2 updates
----------
Michael's Comments
- Perform length check in packet_snd() when GSO is off even when
  vnet_hdr is present.
- Check for SKB_GSO_FCOE type and return -EINVAL
- don't allow tx/rx ring when vnet_hdr is enabled.
Herbert's Comments
- Removed ethernet specific code.
- protocol value is assumed to be passed in by the caller.

Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>

diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h
index 4021d47..aa57a5f 100644
--- a/include/linux/if_packet.h
+++ b/include/linux/if_packet.h
@@ -46,6 +46,7 @@ struct sockaddr_ll {
 #define PACKET_RESERVE			12
 #define PACKET_TX_RING			13
 #define PACKET_LOSS			14
+#define PACKET_VNET_HDR			15
 
 struct tpacket_stats {
 	unsigned int	tp_packets;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 53633c5..8d8cec0 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -80,6 +80,7 @@
 #include <linux/init.h>
 #include <linux/mutex.h>
 #include <linux/if_vlan.h>
+#include <linux/virtio_net.h>
 
 #ifdef CONFIG_INET
 #include <net/inet_common.h>
@@ -193,7 +194,8 @@ struct packet_sock {
 	struct mutex		pg_vec_lock;
 	unsigned int		running:1,	/* prot_hook is attached*/
 				auxdata:1,
-				origdev:1;
+				origdev:1,
+				has_vnet_hdr:1;
 	int			ifindex;	/* bound device		*/
 	__be16			num;
 	struct packet_mclist	*mclist;
@@ -1056,6 +1058,30 @@ out:
 }
 #endif
 
+static inline struct sk_buff *packet_alloc_skb(struct sock *sk, size_t prepad,
+					       size_t reserve, size_t len,
+					       size_t linear, int noblock,
+					       int *err)
+{
+	struct sk_buff *skb;
+
+	/* Under a page?  Don't bother with paged skb. */
+	if (prepad + len < PAGE_SIZE || !linear)
+		linear = len;
+
+	skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock,
+				   err);
+	if (!skb)
+		return NULL;
+
+	skb_reserve(skb, reserve);
+	skb_put(skb, linear);
+	skb->data_len = len - linear;
+	skb->len += len - linear;
+
+	return skb;
+}
+
 static int packet_snd(struct socket *sock,
 			  struct msghdr *msg, size_t len)
 {
@@ -1066,14 +1092,17 @@ static int packet_snd(struct socket *sock,
 	__be16 proto;
 	unsigned char *addr;
 	int ifindex, err, reserve = 0;
+	struct virtio_net_hdr vnet_hdr = { 0 };
+	int offset = 0;
+	int vnet_hdr_len;
+	struct packet_sock *po = pkt_sk(sk);
+	unsigned short gso_type = 0;
 
 	/*
 	 *	Get and verify the address.
 	 */
 
 	if (saddr == NULL) {
-		struct packet_sock *po = pkt_sk(sk);
-
 		ifindex	= po->ifindex;
 		proto	= po->num;
 		addr	= NULL;
@@ -1100,25 +1129,74 @@ static int packet_snd(struct socket *sock,
 	if (!(dev->flags & IFF_UP))
 		goto out_unlock;
 
+	if (po->has_vnet_hdr) {
+		vnet_hdr_len = sizeof(vnet_hdr);
+
+		err = -EINVAL;
+		if (len < vnet_hdr_len)
+			goto out_unlock;
+
+		len -= vnet_hdr_len;
+
+		err = memcpy_fromiovec((void *)&vnet_hdr, msg->msg_iov,
+				       vnet_hdr_len);
+		if (err < 0)
+			goto out_unlock;
+	
+		if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
+		    (vnet_hdr.csum_start + vnet_hdr.csum_offset + 2 >
+		      vnet_hdr.hdr_len))
+			vnet_hdr.hdr_len = vnet_hdr.csum_start +
+						 vnet_hdr.csum_offset + 2;
+
+		err = -EINVAL;
+		if (vnet_hdr.hdr_len > len)
+			goto out_unlock;
+
+		if (vnet_hdr.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
+			switch (vnet_hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
+			case VIRTIO_NET_HDR_GSO_TCPV4:
+				gso_type = SKB_GSO_TCPV4;
+				break;
+			case VIRTIO_NET_HDR_GSO_TCPV6:
+				gso_type = SKB_GSO_TCPV6;
+				break;
+			case VIRTIO_NET_HDR_GSO_UDP:
+				gso_type = SKB_GSO_UDP;
+				break;
+			default:
+				goto out_unlock;
+			}
+
+			if (vnet_hdr.gso_type & VIRTIO_NET_HDR_GSO_ECN)
+				gso_type |= SKB_GSO_TCP_ECN;
+
+			if (vnet_hdr.gso_size == 0)
+				goto out_unlock;
+
+		}
+	}
+
 	err = -EMSGSIZE;
-	if (len > dev->mtu+reserve)
+	if (!gso_type && (len > dev->mtu+reserve))
 		goto out_unlock;
 
-	skb = sock_alloc_send_skb(sk, len + LL_ALLOCATED_SPACE(dev),
-				msg->msg_flags & MSG_DONTWAIT, &err);
+	err = -ENOBUFS;
+	skb = packet_alloc_skb(sk, LL_ALLOCATED_SPACE(dev),
+			       LL_RESERVED_SPACE(dev), len, vnet_hdr.hdr_len,
+			       msg->msg_flags & MSG_DONTWAIT, &err);
 	if (skb == NULL)
 		goto out_unlock;
 
-	skb_reserve(skb, LL_RESERVED_SPACE(dev));
-	skb_reset_network_header(skb);
+	skb_set_network_header(skb, reserve);
 
 	err = -EINVAL;
 	if (sock->type == SOCK_DGRAM &&
-	    dev_hard_header(skb, dev, ntohs(proto), addr, NULL, len) < 0)
+	    (offset = dev_hard_header(skb, dev, ntohs(proto), addr, NULL, len)) < 0)
 		goto out_free;
 
 	/* Returns -EFAULT on error */
-	err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
+	err = skb_copy_datagram_from_iovec(skb, offset, msg->msg_iov, 0, len);
 	if (err)
 		goto out_free;
 
@@ -1127,6 +1205,25 @@ static int packet_snd(struct socket *sock,
 	skb->priority = sk->sk_priority;
 	skb->mark = sk->sk_mark;
 
+	if (po->has_vnet_hdr) {
+		if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
+			if (!skb_partial_csum_set(skb, vnet_hdr.csum_start,
+						  vnet_hdr.csum_offset)) {
+				err = -EINVAL;
+				goto out_free;
+			}
+		}
+
+		skb_shinfo(skb)->gso_size = vnet_hdr.gso_size;
+		skb_shinfo(skb)->gso_type = gso_type;
+
+		/* Header must be checked, and gso_segs computed. */
+		skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
+		skb_shinfo(skb)->gso_segs = 0;
+
+		len += vnet_hdr_len;
+	}
+
 	/*
 	 *	Now send it
 	 */
@@ -1420,6 +1517,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
 	struct sk_buff *skb;
 	int copied, err;
 	struct sockaddr_ll *sll;
+	int vnet_hdr_len = 0;
 
 	err = -EINVAL;
 	if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT))
@@ -1451,6 +1549,48 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
 	if (skb == NULL)
 		goto out;
 
+	if (pkt_sk(sk)->has_vnet_hdr) {
+		struct virtio_net_hdr vnet_hdr = { 0 };
+
+		err = -EINVAL;
+		vnet_hdr_len = sizeof(vnet_hdr);
+		if ((len -= vnet_hdr_len) < 0)
+			goto out_free;
+
+		if (skb_is_gso(skb)) {
+			struct skb_shared_info *sinfo = skb_shinfo(skb);
+
+			/* This is a hint as to how much should be linear. */
+			vnet_hdr.hdr_len = skb_headlen(skb);
+			vnet_hdr.gso_size = sinfo->gso_size;
+			if (sinfo->gso_type & SKB_GSO_TCPV4)
+				vnet_hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
+			else if (sinfo->gso_type & SKB_GSO_TCPV6)
+				vnet_hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
+			else if (sinfo->gso_type & SKB_GSO_UDP)
+				vnet_hdr.gso_type = VIRTIO_NET_HDR_GSO_UDP;
+			else if (sinfo->gso_type & SKB_GSO_FCOE)
+				goto out_free;
+			else
+				BUG();
+			if (sinfo->gso_type & SKB_GSO_TCP_ECN)
+				vnet_hdr.gso_type |= VIRTIO_NET_HDR_GSO_ECN;
+		} else
+			vnet_hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE;
+
+		if (skb->ip_summed == CHECKSUM_PARTIAL) {
+			vnet_hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
+			vnet_hdr.csum_start = skb->csum_start -
+							skb_headroom(skb);
+			vnet_hdr.csum_offset = skb->csum_offset;
+		} /* else everything is zero */
+
+		err = memcpy_toiovec(msg->msg_iov, (void *)&vnet_hdr,
+				     vnet_hdr_len);
+		if (err < 0)
+			goto out_free;
+	}
+
 	/*
 	 *	If the address length field is there to be filled in, we fill
 	 *	it in now.
@@ -1502,7 +1642,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
 	 *	Free or return the buffer as appropriate. Again this
 	 *	hides all the races and re-entrancy issues from us.
 	 */
-	err = (flags&MSG_TRUNC) ? skb->len : copied;
+	err = vnet_hdr_len + ((flags&MSG_TRUNC) ? skb->len : copied);
 
 out_free:
 	skb_free_datagram(sk, skb);
@@ -1740,6 +1880,8 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
 
 		if (optlen < sizeof(req))
 			return -EINVAL;
+		if (pkt_sk(sk)->has_vnet_hdr)
+			return -EINVAL;
 		if (copy_from_user(&req, optval, sizeof(req)))
 			return -EFAULT;
 		return packet_set_ring(sk, &req, 0, optname == PACKET_TX_RING);
@@ -1826,6 +1968,22 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
 		po->origdev = !!val;
 		return 0;
 	}
+	case PACKET_VNET_HDR:
+	{
+		int val;
+
+		if (sock->type != SOCK_RAW)
+			return -EINVAL;
+		if (po->rx_ring.pg_vec || po->tx_ring.pg_vec)	
+			return -EBUSY;
+		if (optlen < sizeof(val))
+			return -EINVAL;
+		if (copy_from_user(&val, optval, sizeof(val)))
+			return -EFAULT;
+
+		po->has_vnet_hdr = !!val;
+		return 0;
+	}
 	default:
 		return -ENOPROTOOPT;
 	}
@@ -1876,6 +2034,13 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
 
 		data = &val;
 		break;
+	case PACKET_VNET_HDR:
+		if (len > sizeof(int))
+			len = sizeof(int);
+		val = po->has_vnet_hdr;
+
+		data = &val;
+		break;
 #ifdef CONFIG_PACKET_MMAP
 	case PACKET_VERSION:
 		if (len > sizeof(int))



^ permalink raw reply related

* [net-2.6 PATCH 2/2] ixgbe: Fix return of invalid txq
From: Jeff Kirsher @ 2010-02-03 23:13 UTC (permalink / raw)
  To: davem
  Cc: netdev, gospo, Krishna Kumar, Jesse Brandeburg,
	Peter P Waskiewicz Jr, Jeff Kirsher
In-Reply-To: <20100203231224.15352.27988.stgit@localhost.localdomain>

From: Krishna Kumar <krkumar2@in.ibm.com>

a developer had complained of getting lots of warnings:

"eth16 selects TX queue 98, but real number of TX queues is 64"

http://www.mail-archive.com/e1000-devel@lists.sourceforge.net/msg02200.html

As there was no follow up on that bug, I am submitting this
patch assuming that the other return points will not return
invalid txq's, and also that this fixes the bug (not tested).

Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Acked-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/ixgbe/ixgbe_main.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 37e2af0..7b7c848 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -5329,8 +5329,11 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
 	int txq = smp_processor_id();
 
-	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
+	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
+		while (unlikely(txq >= dev->real_num_tx_queues))
+			txq -= dev->real_num_tx_queues;
 		return txq;
+	}
 
 #ifdef IXGBE_FCOE
 	if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&


^ permalink raw reply related

* [net-2.6 PATCH 1/2] ixgbe: Fix ixgbe_tx_map error path
From: Jeff Kirsher @ 2010-02-03 23:12 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Anton Blanchard, Jeff Kirsher

From: Anton Blanchard <anton@samba.org>

Commit e5a43549f7a58509a91b299a51337d386697b92c (ixgbe: remove
skb_dma_map/unmap calls from driver) looks to have introduced a bug in
ixgbe_tx_map. If we get an error from a PCI DMA call, we loop backwards
through count until it becomes -1 and return that.

The caller of ixgbe_tx_map expects 0 on error, so return that instead.

Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/ixgbe/ixgbe_main.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index b5f64ad..37e2af0 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -5179,7 +5179,7 @@ dma_error:
 		ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info);
 	}
 
-	return count;
+	return 0;
 }
 
 static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,


^ permalink raw reply related

* Re: bad unlock balance detected during stress
From: David Miller @ 2010-02-03 22:49 UTC (permalink / raw)
  To: emil.s.tantilov; +Cc: netdev, paulmck
In-Reply-To: <EA929A9653AAE14F841771FB1DE5A1365FDD5CAF52@rrsmsx501.amr.corp.intel.com>

From: "Tantilov, Emil S" <emil.s.tantilov@intel.com>
Date: Wed, 3 Feb 2010 13:05:44 -0700

> I got this panic while running netperf stress test using recent pull from net-next:

Known bug, fixed yesterday by Patrick McHardy:

commit d1c9ae6d1e7b95cedc8e39e8949e795379a0669e
Author: Patrick McHardy <kaber@trash.net>
Date:   Tue Feb 2 11:46:50 2010 -0800

    ipv4: ip_fragment: fix unbalanced rcu_read_unlock()
    
    Signed-off-by: Patrick McHardy <kaber@trash.net>
    Signed-off-by: David S. Miller <davem@davemloft.net>

diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 9f41bd3..b59430b 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -234,10 +234,9 @@ static void ip_expire(unsigned long arg)
 
 		/* Send an ICMP "Fragment Reassembly Timeout" message. */
 		icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
-	}
-
 out_rcu_unlock:
-	rcu_read_unlock();
+		rcu_read_unlock();
+	}
 out:
 	spin_unlock(&qp->q.lock);
 	ipq_put(qp);

^ permalink raw reply related

* Re: [PATCH 02/25 v2] mlx4_core: add support for arbitrary bitmap sizes
From: Roland Dreier @ 2010-02-03 22:25 UTC (permalink / raw)
  To: Yevgeny Petrilin
  Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	liranl-VPRAkNaXOzVS1MOuV/RT9w, tziporet-VPRAkNaXOzVS1MOuV/RT9w
In-Reply-To: <4AF39314.5020004-VPRAkNaXOzVS1MOuV/RT9w@public.gmane.org>

 > +int mlx4_bitmap_init_no_mask(struct mlx4_bitmap *bitmap, u32 num,
 > +			     u32 reserved_bot, u32 reserved_top)
 > +{
 > +	u32 num_rounded = roundup_pow_of_two(num);
 > +	return mlx4_bitmap_init(bitmap, num_rounded, num_rounded - 1,
 > +				reserved_bot, num_rounded - num + reserved_top);
 > +}

I think I would really prefer things if we got rid of this wrapper.  The
mlx4_bitmap stuff is really there to handle the case where we want to
have a mask and have the non-used bits cycle to avoid reusing QPN etc.
If we have a bitmap with no mask that's no a power of 2 in size, there's
really no value in the mlx4 wrapper -- we might as well just allocate a
bitmap directly.

And since this is only used in one place (for the EQ tables) I think it
makes sense to just open-code everything in the EQ code.

 - R.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [net-next-2.6 PATCH 3/5] net: Add netdev ops for SR-IOV configuration
From: Ben Hutchings @ 2010-02-03 22:00 UTC (permalink / raw)
  To: Jeff Kirsher; +Cc: davem, netdev, gospo, Mitch Williams
In-Reply-To: <20100130104008.26633.93050.stgit@localhost.localdomain>

On Sat, 2010-01-30 at 02:40 -0800, Jeff Kirsher wrote:
> From: Williams, Mitch A <mitch.a.williams@intel.com>
> 
> Add netdev ops for configuring SR-IOV VF devices through the PF driver.
[...]

If this is going to be specific to SR-IOV then it doesn't belong in
net_device_ops.

Look again at Dave's comments in
<http://article.gmane.org/gmane.linux.network/147158> and my question in
<http://article.gmane.org/gmane.linux.network/147114>.

Ben.

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply

* Re: [RFC] NAPI as kobject proposal
From: David Daney @ 2010-02-03 21:38 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: Stephen Hemminger, David Miller, netdev
In-Reply-To: <1265232216.2116.46.camel@achroite.uk.solarflarecom.com>

Ben Hutchings wrote:
> On Fri, 2010-01-29 at 10:18 -0800, Stephen Hemminger wrote:
>> The NAPI interface structure in current kernels is managed by the driver.
>> As part of receive packet steering there is a requirement to add an
>> additional parameter to this for the CPU map. And this map needs to
>> have an API to set it.
>>
>> The right way to do this in the kernel model is to make NAPI into
>> a kobject and associate it back with the network device (parent).
>> This isn't wildly difficult but does change some of the API for
>> network device drivers because:
>>   1. They need to handle another possible error on setup
>>   2. NAPI object needs to be dynamically allocated
>>      separately (not as part of netdev_priv)
>>   3. Driver should pass index that can be uses as part of
>>      name (easier than scanning)
>>
>> Eventually, there will be:
>>   /sys/class/net/eth0/napi0/
>>                             weight
>>                             cpumap
> 
> I think the NAPI objects should be created as children of a bus device
> and then linked from the net device directories, e.g.
> 
> /sys/devices/.../ net/eth0/
>                            napi0 -> ../../napi/napi0
>                       eth1/
>                            napi0 -> ../../napi/napi0
>                   napi/napi0/
>                              weight
>                              cpumap
> 

This seems right.

Some drivers have a single napi object logically associated with 
multiple interfaces.  Although the current architecture forces us to 
associate the napi object with a single net_device, it would be nice to 
move towards something that allows sharing a napi object between 
multiple devices.

David Daney

^ permalink raw reply

* Re: [RFC] NAPI as kobject proposal
From: Stephen Hemminger @ 2010-02-03 21:41 UTC (permalink / raw)
  To: Al Viro; +Cc: Ben Hutchings, David Miller, netdev
In-Reply-To: <20100203212641.GB30031@ZenIV.linux.org.uk>

On Wed, 3 Feb 2010 21:26:41 +0000
Al Viro <viro@ZenIV.linux.org.uk> wrote:

> On Wed, Feb 03, 2010 at 09:23:36PM +0000, Ben Hutchings wrote:
> > On Fri, 2010-01-29 at 10:18 -0800, Stephen Hemminger wrote:
> > > The NAPI interface structure in current kernels is managed by the driver.
> > > As part of receive packet steering there is a requirement to add an
> > > additional parameter to this for the CPU map. And this map needs to
> > > have an API to set it.
> > > 
> > > The right way to do this in the kernel model is to make NAPI into
> > > a kobject and associate it back with the network device (parent).
> > > This isn't wildly difficult but does change some of the API for
> > > network device drivers because:
> > >   1. They need to handle another possible error on setup
> > >   2. NAPI object needs to be dynamically allocated
> > >      separately (not as part of netdev_priv)
> > >   3. Driver should pass index that can be uses as part of
> > >      name (easier than scanning)
> 
> 4. Lifetime rules become oh-so-fscking-interesting?

My original proposal doesn't go far enough. I am doing a bigger
version that changes API to:
   napi_alloc / napi_release

The lifetime problem isn't that bad because the napi is a child
of network device object.  Make it a child bus object is a bigger
problem because then network device can come and go.

-- 

^ permalink raw reply

* Re: [RFC] NAPI as kobject proposal
From: Al Viro @ 2010-02-03 21:26 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: Stephen Hemminger, David Miller, netdev
In-Reply-To: <1265232216.2116.46.camel@achroite.uk.solarflarecom.com>

On Wed, Feb 03, 2010 at 09:23:36PM +0000, Ben Hutchings wrote:
> On Fri, 2010-01-29 at 10:18 -0800, Stephen Hemminger wrote:
> > The NAPI interface structure in current kernels is managed by the driver.
> > As part of receive packet steering there is a requirement to add an
> > additional parameter to this for the CPU map. And this map needs to
> > have an API to set it.
> > 
> > The right way to do this in the kernel model is to make NAPI into
> > a kobject and associate it back with the network device (parent).
> > This isn't wildly difficult but does change some of the API for
> > network device drivers because:
> >   1. They need to handle another possible error on setup
> >   2. NAPI object needs to be dynamically allocated
> >      separately (not as part of netdev_priv)
> >   3. Driver should pass index that can be uses as part of
> >      name (easier than scanning)

4. Lifetime rules become oh-so-fscking-interesting?

^ permalink raw reply

* Re: [RFC] NAPI as kobject proposal
From: Ben Hutchings @ 2010-02-03 21:23 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David Miller, netdev
In-Reply-To: <20100129101839.36944ba5@nehalam>

On Fri, 2010-01-29 at 10:18 -0800, Stephen Hemminger wrote:
> The NAPI interface structure in current kernels is managed by the driver.
> As part of receive packet steering there is a requirement to add an
> additional parameter to this for the CPU map. And this map needs to
> have an API to set it.
> 
> The right way to do this in the kernel model is to make NAPI into
> a kobject and associate it back with the network device (parent).
> This isn't wildly difficult but does change some of the API for
> network device drivers because:
>   1. They need to handle another possible error on setup
>   2. NAPI object needs to be dynamically allocated
>      separately (not as part of netdev_priv)
>   3. Driver should pass index that can be uses as part of
>      name (easier than scanning)
> 
> Eventually, there will be:
>   /sys/class/net/eth0/napi0/
>                             weight
>                             cpumap

I think the NAPI objects should be created as children of a bus device
and then linked from the net device directories, e.g.

/sys/devices/.../ net/eth0/
                           napi0 -> ../../napi/napi0
                      eth1/
                           napi0 -> ../../napi/napi0
                  napi/napi0/
                             weight
                             cpumap

I also think it might be helpful to use a more descriptive name here
than 'napi', e.g. 'channel'.  But maybe that can be left to management
tools.

> So here is a starting point patch that shows how the API might look like.
> 
> 
> ---
>  include/linux/netdevice.h |   20 ++++++++++++++------
>  net/core/dev.c            |   28 ++++++++++++++++++++++++++--
>  2 files changed, 40 insertions(+), 8 deletions(-)
> 
> --- a/include/linux/netdevice.h	2010-01-29 10:00:55.820739116 -0800
> +++ b/include/linux/netdevice.h	2010-01-29 10:15:33.098863437 -0800
> @@ -378,6 +378,8 @@ struct napi_struct {
>  	struct list_head	dev_list;
>  	struct sk_buff		*gro_list;
>  	struct sk_buff		*skb;
> +
> +	struct kobject		kobj;
>  };
>  
>  enum {
> @@ -1037,25 +1039,31 @@ static inline void *netdev_priv(const st
>  #define SET_NETDEV_DEVTYPE(net, devtype)	((net)->dev.type = (devtype))
>  
>  /**
> - *	netif_napi_add - initialize a napi context
> + *	netif_napi_init - initialize a napi context
>   *	@dev:  network device
>   *	@napi: napi context
> + *	@index: queue number
>   *	@poll: polling function
>   *	@weight: default weight
>   *
> - * netif_napi_add() must be used to initialize a napi context prior to calling
> + * netif_napi_init() must be used to create a napi context prior to calling
>   * *any* of the other napi related functions.
> + *
> + * in case of error, the context is not left in napi_list so it can
> + * be cleaned up by free_netdev, but is not valid for use.
>   */
> -void netif_napi_add(struct net_device *dev, struct napi_struct *napi,
> -		    int (*poll)(struct napi_struct *, int), int weight);
> +extern int netif_napi_init(struct net_device *dev, struct napi_struct *napi,
> +			   unsigned index,
> +			   int (*poll)(struct napi_struct *, int), int weight);
[...
> --- a/net/core/dev.c	2010-01-29 10:00:55.810739850 -0800
> +++ b/net/core/dev.c	2010-01-29 10:14:53.388864572 -0800
> @@ -2926,9 +2926,24 @@ void napi_complete(struct napi_struct *n
>  }
>  EXPORT_SYMBOL(napi_complete);
>  
> -void netif_napi_add(struct net_device *dev, struct napi_struct *napi,
> +static void release_napi(struct kobject *kobj)
> +{
> +	struct napi_struct *napi
> +		= container_of(kobj, struct napi_struct, kobj);
> +	kfree(napi);
> +}
[...]

This means the napi_struct can no longer be embedded in a larger struct.
So I think netif_napi_init() should actually allocate the napi_struct
and be named netif_napi_create().

Ben.

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply

* pull request: wireless-next-2.6 2010-02-03
From: John W. Linville @ 2010-02-03 21:19 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA

Dave,

Another huge batch of updates intended for 2.6.34, mostly the usual bits
by the usual suspects.  This batch does contain a number of mac80211
fixes that (presumably) originated in OpenWRT and a number of steps
toward N-phy support in b43, along with the usual driver updates from
Intel, Atheros, and many others.  And, of course, Johannes makes his
usual strong showing. :-)

Please let me know if there are problems!

Thanks,

John

---

The following changes since commit 730dd70549e0ec755dd55615ba5cfc38a482a947:
  Rafał Miłecki (1):
        b43: N-PHY: drop unused definition, uncomment needed call

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6.git master

Abhijeet Kolekar (3):
      iwlwifi: disable tx on beacon update notification
      cfg80211: fix channel setting for wext
      iwlwifi: enable DC calibration

Andriy Tkachuk (3):
      mac80211: Account HT Control field in Data frame hdrlen according to 802.11n-2009
      lib80211: Cosmetics - make room for MIC/CRC near the actual calculation
      lib80211: Introduce TKIP_HDR_LEN define for code clarity

Benoit Papillault (3):
      mac80211: check that ieee80211_set_power_mgmt only handles STA interfaces.
      mac80211: removed useless code in IBSS management
      mac80211: Fixed a bug in IBSS merge

Bob Copeland (4):
      mac80211: fix sign error in pid controller
      mac80211: pid: replace open-coded msecs_to_jiffies
      ath5k: dont use external sleep clock in AP mode
      ath5k: fix setup for CAB queue

Christian Lamparter (4):
      p54pci: rx frame length check
      p54pci: handle dma mapping errors
      p54pci: move tx cleanup into tasklet
      p54pci: revise tx locking

Dan Carpenter (1):
      iwlwifi: silence buffer overflow warning

Daniel Halperin (2):
      iwlwifi: fix throughput degradation in aggregation mode
      iwlwifi: optimize power saving

Felix Fietkau (10):
      mac80211: add missing sanity checks for action frames
      mac80211: fix queue selection for data frames on monitor interfaces
      mac80211: fix WMM AC default for non-QoS data frames
      ath9k: fix RTS/CTS handling
      mac80211: fix rx data handling for non-data frames on multiple vifs
      ath9k: improve max rate retry handling
      mac80211: fix WARN_ON in the new work code
      mac80211: fix sta lookup for received action frames on an AP VLAN
      mac80211: fix monitor mode tx radiotap header handling
      mac80211: fix sta lookup with AP VLAN interfaces and injected frames

Hamish Guthrie (3):
      ps3_gelic_wireless: Remove PS3 gelic legacy wpa support
      ps3_gelic_wireless: fix directed ssid scan
      ps3_gelic_wireless: Remove superfluous debug info

Henry Zhangh (1):
      iwlwifi: Fix A band scanning when associated

Hin-Tak Leung (1):
      zd1211rw: adding 0409:0248 to supported device list

Johannes Berg (27):
      mac80211: fix endian error
      cfg80211: fix refcount imbalance when wext is disabled
      mac80211: move and rename misc tx handler
      mac80211: clear TX control on filtered frames
      mac80211: remove useless setting of IEEE80211_TX_INTFL_DONT_ENCRYPT
      mac80211: move control.hw_key assignment
      mac80211: re-enable re-transmission of filtered frames
      cfg80211: rcu-ify rdev and wdev
      mac80211: pass vif and station to update_tkip_key
      cfg80211: export multiple MAC addresses in sysfs
      mac80211: add missing key check
      iwlwifi: is no longer experimental
      iwlwifi: reorder device setup
      iwlwifi: clean up debugfs code
      iwlwifi: fix sparse warning
      iwlwifi: check endianness annotations by default
      mac80211: fix sw crypto
      mac80211: track work started through callbacks
      mac80211: fill jiffies/vif on filtered frames
      cfg80211: export cfg80211_find_ie
      mac80211: wait for beacon before enabling powersave
      iwlwifi: fix locking in iwl_mac_add_interface
      iwlwifi: no need to test iw_mode in power saving
      iwlagn: simplify ucode loading
      iwlwifi: remove bg_up work
      iwlwifi: remove unused work structs
      iwlwifi: fix typo in IWL_CCK_RATES_MASK

John W. Linville (7):
      Merge git://git.kernel.org/.../linville/wireless-2.6
      libertas/assoc.c: rearrange some strange line breaks
      mac80211: avoid NULL ptr deref when using WEP
      libertas: add comment re: v10 firmware key handling
      rtl8180: implement get_tsf op for mac80211
      cfg80211: fix wext-compat for setting rate to 'auto'
      ps3_gelic_wireless: fix format warning

Jouni Malinen (1):
      nl80211: Allow association to change channels during reassociation

Kalle Valo (2):
      mac80211: fix tx select key null pointer crash with hostapd
      mac80211: fix update_tkip_key() documentation about the context

Larry Finger (2):
      b43: N PHY: Fix compilation after removal of typdef b43_c32
      rtl8187: Add callback for get_tsf

Lennert Buytenhek (1):
      mac80211: fix queue selection for packets injected via monitor interface

Luca Verdesca (1):
      ath5k: adding LED support for AR5BXB63 cards

Luis R. Rodriguez (4):
      ath9k: make tx power config changes take effect immediatley
      cfg80211: avoid flushing the global workqueue for core reg hints
      cfg80211: add regulatory hint disconnect support
      ath9k: add support for 802.11n bonded out AR2427

Michael Buesch (1):
      b43: Workaround circular locking in hw-tkip key update callback

Pavel Roskin (5):
      ath: make gcc check format arguments of ath_print(), fix all misuses
      ath9k: allocate string buffer in read_file_dma() by kmalloc()
      mac80211: reduce stack usage in sta_ht_capa_read()
      mac80211: reduce stack usage in sta_agg_status_read()
      ath9k: fix access to freed data on unload

Rafał Miłecki (28):
      b43: N-PHY: implement RX PHY cleanup and setup
      b43: N-PHY: implement TX PHY cleanup and setup
      b43: N-PHY: implement MIMO config update
      b43: N-PHY: implement stopping playback
      b43: N-PHY: implement chain selection
      b43: N-PHY: move RF sequence declarations top, add missing calls
      b43: N-PHY: store seq mode for proper restoring (follow specs)
      b43: N-PHY: add writing one element tables
      b43: N-PHY: implement and add multi-dimensional table writing
      b43: N-PHY: implement and add reading one element tables
      b43: N-PHY: implement and add multi-dimensional table reading
      b43: N-PHY: silence warnings, add missing call
      b43: check band width
      b43: N-PHY: implement overriding RF control
      b43: N-PHY: add running samples
      b43: N-PHY: add setting power amplifier filters
      b43: N-PHY: add TX tone
      b43: N-PHY: fix one bit off in parsing RF Ctrl Override arguments
      b43: make cordic common (LP-PHY and N-PHY need it)
      b43: update cordic code to match current specs
      b43: N-PHY: use cordic to generate samples
      b43: N-PHY: update general workarounds
      b43: N-PHY: add workarounds for gain control
      b43: N-PHY: split RSSI selection into two per-PHY-revision functions
      b43: N-PHY: add RSSI selection for newer PHYs
      b43: N-PHY: fix Cal TX IQ LO for newer PHYs
      b43: N-PHY: add TX radio setup for newer PHYs
      b43: N-PHY: implement setting RF sequence

Reinette Chatre (6):
      iwlwifi: add license to tracing files
      iwlwifi: update copyright year to 2010
      iwlwifi: cleanup station adding code
      iwlwifi: make broadcast station addition generic
      iwlwifi: cleanup spectrum measurement command support
      iwlwifi: iwl_power_update_mode always hold mutex

Samuel Ortiz (2):
      iwmc3200wifi: Add UMAC wifi headers to the pmkid command
      libertas: Set/clear WPA keys before the WEP ones

Stanislaw Gruszka (1):
      airo: fix setting zero length WEP key

Trieu 'Andrew' Nguyen (1):
      iwlwifi: Tune radio to prevent unexpected behavior

Vasanthakumar (1):
      mac80211: Don't call rate control when HW handles it

Vasanthakumar Thiagarajan (1):
      ath9k: Fix wifi disconnection when collocated bt scan is active

Vivek Natarajan (1):
      ath9k: Handle full sleep in ps_restore.

Wey-Yi Guy (18):
      iwlwifi: Fix throughput stall issue in HT mode for 5000
      iwlwifi: fix clear statistics counter command
      iwlwifi: format and show statistics counter from uCode
      iwlwifi: add num_of_sos_stats to statistics counter
      iwlwifi: correct return code for log_event
      iwlwifi: set interrupt coalescing timer range and default
      iwlwifi: software w/a for h/w bug cause Rx bit get clear
      iwlwifi: display flowhandler register when sw error or on-demand
      iwlwifi: remove extra statistics request from debugfs
      iwlwifi: configure missed beacon threshold
      iwlwifi: add function to reset/tune radio if needed
      iwlwifi: Logic to control how frequent radio should be reset if needed
      iwlwifi: bit field description for BT Config command
      iwlwifi: module parameter to enable/disable bt co-exist
      iwlwifi: sysassert identifier change
      iwlwifi: update sensitivity calibration data for 6x00 series
      iwlwifi: update sensitivity calibration data for 5x00 series
      iwlwifi: update sensitivity calibration data for 1000 series

Zhu Yi (1):
      iwlwifi: fix iwl_queue_used bug when read_ptr == write_ptr

 arch/powerpc/configs/ppc64_defconfig         |    1 -
 arch/powerpc/configs/ps3_defconfig           |    1 -
 drivers/net/Kconfig                          |   14 -
 drivers/net/ps3_gelic_wireless.c             |  149 +---
 drivers/net/wireless/airo.c                  |   34 +-
 drivers/net/wireless/ath/ath.h               |    1 -
 drivers/net/wireless/ath/ath5k/ath5k.h       |    2 +-
 drivers/net/wireless/ath/ath5k/base.c        |   22 +-
 drivers/net/wireless/ath/ath5k/led.c         |    2 +
 drivers/net/wireless/ath/ath5k/qcu.c         |    5 +-
 drivers/net/wireless/ath/ath5k/reset.c       |    5 +-
 drivers/net/wireless/ath/ath9k/ahb.c         |   12 +-
 drivers/net/wireless/ath/ath9k/ath9k.h       |    8 +-
 drivers/net/wireless/ath/ath9k/btcoex.h      |    2 +
 drivers/net/wireless/ath/ath9k/debug.c       |   43 +-
 drivers/net/wireless/ath/ath9k/gpio.c        |   30 +-
 drivers/net/wireless/ath/ath9k/hw.c          |    7 +-
 drivers/net/wireless/ath/ath9k/hw.h          |    1 +
 drivers/net/wireless/ath/ath9k/init.c        |    7 +-
 drivers/net/wireless/ath/ath9k/main.c        |   18 +-
 drivers/net/wireless/ath/ath9k/pci.c         |   19 +-
 drivers/net/wireless/ath/ath9k/rc.c          |   12 +-
 drivers/net/wireless/ath/ath9k/recv.c        |    2 +-
 drivers/net/wireless/ath/ath9k/reg.h         |    6 +-
 drivers/net/wireless/ath/ath9k/xmit.c        |   39 +-
 drivers/net/wireless/ath/debug.h             |    8 +-
 drivers/net/wireless/b43/main.c              |   28 +-
 drivers/net/wireless/b43/phy_common.c        |   45 +
 drivers/net/wireless/b43/phy_common.h        |   10 +
 drivers/net/wireless/b43/phy_lp.c            |   52 +-
 drivers/net/wireless/b43/phy_n.c             | 1264 +++++++++++++++++++++-----
 drivers/net/wireless/b43/phy_n.h             |    7 +
 drivers/net/wireless/b43/tables_nphy.c       |  167 ++++
 drivers/net/wireless/b43/tables_nphy.h       |   27 +
 drivers/net/wireless/iwlwifi/Kconfig         |   14 +-
 drivers/net/wireless/iwlwifi/Makefile        |    3 +-
 drivers/net/wireless/iwlwifi/iwl-1000.c      |   78 ++-
 drivers/net/wireless/iwlwifi/iwl-3945-fh.h   |    4 +-
 drivers/net/wireless/iwlwifi/iwl-3945-hw.h   |    4 +-
 drivers/net/wireless/iwlwifi/iwl-3945-led.c  |    2 +-
 drivers/net/wireless/iwlwifi/iwl-3945-led.h  |    2 +-
 drivers/net/wireless/iwlwifi/iwl-3945-rs.c   |    2 +-
 drivers/net/wireless/iwlwifi/iwl-3945.c      |   11 +-
 drivers/net/wireless/iwlwifi/iwl-3945.h      |    2 +-
 drivers/net/wireless/iwlwifi/iwl-4965-hw.h   |    4 +-
 drivers/net/wireless/iwlwifi/iwl-4965.c      |    6 +-
 drivers/net/wireless/iwlwifi/iwl-5000-hw.h   |    4 +-
 drivers/net/wireless/iwlwifi/iwl-5000.c      |   84 +-
 drivers/net/wireless/iwlwifi/iwl-6000-hw.h   |    4 +-
 drivers/net/wireless/iwlwifi/iwl-6000.c      |   28 +-
 drivers/net/wireless/iwlwifi/iwl-agn-led.c   |    2 +-
 drivers/net/wireless/iwlwifi/iwl-agn-led.h   |    2 +-
 drivers/net/wireless/iwlwifi/iwl-agn-rs.c    |    2 +-
 drivers/net/wireless/iwlwifi/iwl-agn-rs.h    |    4 +-
 drivers/net/wireless/iwlwifi/iwl-agn.c       |   86 +-
 drivers/net/wireless/iwlwifi/iwl-calib.c     |    4 +-
 drivers/net/wireless/iwlwifi/iwl-calib.h     |    4 +-
 drivers/net/wireless/iwlwifi/iwl-commands.h  |   54 +-
 drivers/net/wireless/iwlwifi/iwl-core.c      |  194 ++++-
 drivers/net/wireless/iwlwifi/iwl-core.h      |   25 +-
 drivers/net/wireless/iwlwifi/iwl-csr.h       |    4 +-
 drivers/net/wireless/iwlwifi/iwl-debug.h     |   62 +--
 drivers/net/wireless/iwlwifi/iwl-debugfs.c   | 1267 +++++++++++++++-----------
 drivers/net/wireless/iwlwifi/iwl-dev.h       |   48 +-
 drivers/net/wireless/iwlwifi/iwl-devtrace.c  |   26 +
 drivers/net/wireless/iwlwifi/iwl-devtrace.h  |   26 +
 drivers/net/wireless/iwlwifi/iwl-eeprom.c    |    4 +-
 drivers/net/wireless/iwlwifi/iwl-eeprom.h    |    4 +-
 drivers/net/wireless/iwlwifi/iwl-fh.h        |   23 +-
 drivers/net/wireless/iwlwifi/iwl-hcmd.c      |    2 +-
 drivers/net/wireless/iwlwifi/iwl-helpers.h   |    2 +-
 drivers/net/wireless/iwlwifi/iwl-io.h        |    2 +-
 drivers/net/wireless/iwlwifi/iwl-led.c       |    2 +-
 drivers/net/wireless/iwlwifi/iwl-led.h       |    2 +-
 drivers/net/wireless/iwlwifi/iwl-power.c     |    9 +-
 drivers/net/wireless/iwlwifi/iwl-power.h     |    2 +-
 drivers/net/wireless/iwlwifi/iwl-prph.h      |    4 +-
 drivers/net/wireless/iwlwifi/iwl-rx.c        |  104 ++-
 drivers/net/wireless/iwlwifi/iwl-scan.c      |  192 ++++-
 drivers/net/wireless/iwlwifi/iwl-spectrum.c  |  198 ----
 drivers/net/wireless/iwlwifi/iwl-spectrum.h  |    2 +-
 drivers/net/wireless/iwlwifi/iwl-sta.c       |  150 ++-
 drivers/net/wireless/iwlwifi/iwl-sta.h       |    3 +-
 drivers/net/wireless/iwlwifi/iwl-tx.c        |    2 +-
 drivers/net/wireless/iwlwifi/iwl3945-base.c  |   57 +-
 drivers/net/wireless/iwmc3200wifi/commands.c |    4 +
 drivers/net/wireless/iwmc3200wifi/commands.h |    1 +
 drivers/net/wireless/libertas/assoc.c        |   78 +-
 drivers/net/wireless/mac80211_hwsim.c        |    8 +-
 drivers/net/wireless/mwl8k.c                 |   14 +-
 drivers/net/wireless/p54/p54pci.c            |   82 +-
 drivers/net/wireless/p54/p54pci.h            |    6 +-
 drivers/net/wireless/rtl818x/rtl8180_dev.c   |    9 +
 drivers/net/wireless/rtl818x/rtl8187_dev.c   |   11 +-
 drivers/net/wireless/wl12xx/wl1251.h         |    3 -
 drivers/net/wireless/wl12xx/wl1251_main.c    |   25 +-
 drivers/net/wireless/zd1211rw/zd_usb.c       |    1 +
 include/linux/ieee80211.h                    |    2 +
 include/net/cfg80211.h                       |   38 +-
 include/net/mac80211.h                       |   22 +-
 include/net/regulatory.h                     |    1 +
 net/mac80211/cfg.c                           |    3 +
 net/mac80211/debugfs_sta.c                   |   26 +-
 net/mac80211/driver-ops.h                    |   14 +-
 net/mac80211/driver-trace.h                  |   15 +-
 net/mac80211/ibss.c                          |   22 +-
 net/mac80211/ieee80211_i.h                   |    1 -
 net/mac80211/iface.c                         |   12 +-
 net/mac80211/mlme.c                          |   31 +-
 net/mac80211/rate.h                          |    4 +
 net/mac80211/rc80211_pid_algo.c              |   10 +-
 net/mac80211/rx.c                            |   49 +-
 net/mac80211/scan.c                          |    4 -
 net/mac80211/status.c                        |   35 +-
 net/mac80211/tkip.c                          |   23 +-
 net/mac80211/tx.c                            |   50 +-
 net/mac80211/wep.c                           |   17 +-
 net/mac80211/work.c                          |   19 +-
 net/mac80211/wpa.c                           |   57 +-
 net/wireless/core.c                          |   42 +-
 net/wireless/core.h                          |    3 +-
 net/wireless/lib80211_crypt_ccmp.c           |    2 +-
 net/wireless/lib80211_crypt_tkip.c           |   23 +-
 net/wireless/nl80211.c                       |    4 +-
 net/wireless/reg.c                           |  161 ++++-
 net/wireless/reg.h                           |   18 +
 net/wireless/scan.c                          |   38 +-
 net/wireless/sme.c                           |   41 +
 net/wireless/sysfs.c                         |   20 +
 net/wireless/util.c                          |    5 +-
 net/wireless/wext-compat.c                   |    2 +-
 131 files changed, 3887 insertions(+), 2045 deletions(-)
 delete mode 100644 drivers/net/wireless/iwlwifi/iwl-spectrum.c

Omnibus patch available here:

	http://www.kernel.org/pub/linux/kernel/people/linville/wireless-next-2.6-2010-02-03.patch.bz2

-- 
John W. Linville		Someday the world will need a hero, and you
linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org			might be all we have.  Be ready.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH for 2.6.33] conntrack: restrict runtime hashsize modifications
From: Jon Masters @ 2010-02-03 20:50 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: davem, kaber, eric.dumazet, netdev, netfilter-devel
In-Reply-To: <20100203203929.GA6168@x200>

On Wed, 2010-02-03 at 22:39 +0200, Alexey Dobriyan wrote:
> Jon Masters correctly points out that conntrack hash sizes
> (nf_conntrack_htable_size) are global (not per-netns) and
> modifiable at runtime via /sys/module/nf_conntrack/hashsize .

Thanks.

Jon.



^ permalink raw reply

* [PATCH for 2.6.33] conntrack: restrict runtime hashsize modifications
From: Alexey Dobriyan @ 2010-02-03 20:39 UTC (permalink / raw)
  To: davem, kaber; +Cc: jonathan, eric.dumazet, netdev, netfilter-devel

Jon Masters correctly points out that conntrack hash sizes
(nf_conntrack_htable_size) are global (not per-netns) and
modifiable at runtime via /sys/module/nf_conntrack/hashsize .

Steps to reproduce:
	clone(CLONE_NEWNET)
	[grow /sys/module/nf_conntrack/hashsize]
	exit()

At netns exit we are going to scan random memory for conntracks to be killed.

Apparently there is a code which deals with hashtable resize for
init_net (and it was there befode netns conntrack code), so prohibit
hashsize modification if there is more than one netns exists.

To change hashtable sizes, you need to reload module.

Expectation hashtable size was simply glued to a variable with no code
to rehash expectations, so it was a bug to allow writing to it.
Make "expect_hashsize" readonly.

This is temporarily until we figure out what to do.

Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Cc: stable@kernel.org
---

 net/netfilter/nf_conntrack_core.c   |   15 +++++++++++++++
 net/netfilter/nf_conntrack_expect.c |    2 +-
 2 files changed, 16 insertions(+), 1 deletion(-)

--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -21,6 +21,7 @@
 #include <linux/stddef.h>
 #include <linux/slab.h>
 #include <linux/random.h>
+#include <linux/rtnetlink.h>
 #include <linux/jhash.h>
 #include <linux/err.h>
 #include <linux/percpu.h>
@@ -1198,6 +1199,20 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
 	if (!nf_conntrack_htable_size)
 		return param_set_uint(val, kp);
 
+	{
+		struct net *net;
+		unsigned int nr;
+
+		nr = 0;
+		rtnl_lock();
+		for_each_net(net)
+			nr++;
+		rtnl_unlock();
+		/* init_net always exists */
+		if (nr != 1)
+			return -EINVAL;
+	}
+
 	hashsize = simple_strtoul(val, NULL, 0);
 	if (!hashsize)
 		return -EINVAL;
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -569,7 +569,7 @@ static void exp_proc_remove(struct net *net)
 #endif /* CONFIG_PROC_FS */
 }
 
-module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0600);
+module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0400);
 
 int nf_conntrack_expect_init(struct net *net)
 {

^ permalink raw reply

* [PATCH] ssb: fix interrupt assignment
From: Jochen Friedrich @ 2010-02-03 20:28 UTC (permalink / raw)
  To: Michael Buesch; +Cc: netdev, openwrt-devel

Explicitely enable shared interrupt 2 for any core that didn't get a dedicated IRQ
anymore (fallthrough case) and for EXTIF cores to make gpio interrupts work.
Also remove a bogus comment.

Signed-off-by: Jochen Friedrich <jochen@scram.de>
---
 drivers/ssb/driver_mipscore.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
index 3c6feed..97efce1 100644
--- a/drivers/ssb/driver_mipscore.c
+++ b/drivers/ssb/driver_mipscore.c
@@ -270,7 +270,6 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
 				set_irq(dev, irq++);
 			}
 			break;
-			/* fallthrough */
 		case SSB_DEV_PCI:
 		case SSB_DEV_ETHERNET:
 		case SSB_DEV_ETHERNET_GBIT:
@@ -281,6 +280,10 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
 				set_irq(dev, irq++);
 				break;
 			}
+			/* fallthrough */
+		case SSB_DEV_EXTIF:
+			set_irq(dev, 0);
+			break;
 		}
 	}
 	ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n");
-- 
1.6.6

^ permalink raw reply related

* Re: [PATCHv2 08/11] fec: fix uninitialized rx buffer usage
From: Grant Likely @ 2010-02-03 20:23 UTC (permalink / raw)
  To: Amit Kucheria
  Cc: List Linux Kernel, Rob Herring, David S. Miller, netdev,
	linux-arm-kernel, linux, s.hauer, valentin.longchamp, daniel,
	Dinh.Nguyen, bryan.wu
In-Reply-To: <fa686aa41002031038i6b058c92g39bcf948cc9cb3ce@mail.gmail.com>

On Wed, Feb 3, 2010 at 11:38 AM, Grant Likely <grant.likely@secretlab.ca> wrote:
> On Wed, Feb 3, 2010 at 11:33 AM, Amit Kucheria
> <amit.kucheria@canonical.com> wrote:
>> On Wed, Feb 3, 2010 at 8:46 AM, Grant Likely <grant.likely@secretlab.ca> wrote:
>>>
>>> fec related patches 8 & 9 look okay to me.
>>>
>>> g.
>>
>> Can I take that as an Acked-by?
>
> of course.

BTW, since these 2 patches are essentially independent, you may find
it easier to get all the patches merged if you post the FEC changes in
a separate patch series.

g.

^ permalink raw reply

* Re: [PATCH] netfilter: per netns nf_conntrack_cachep
From: Jon Masters @ 2010-02-03 20:21 UTC (permalink / raw)
  To: Patrick McHardy
  Cc: Alexey Dobriyan, Eric Dumazet, linux-kernel, netdev,
	netfilter-devel, Paul E. McKenney
In-Reply-To: <4B6967BC.600@trash.net>

On Wed, 2010-02-03 at 13:10 +0100, Patrick McHardy wrote:

> Jon, could you give this patch a try please?
> plain text document attachment (x)
> commit 056ff3e3bd1563969a311697323ff929df94415c
> Author: Patrick McHardy <kaber@trash.net>
> Date:   Wed Feb 3 12:58:06 2010 +0100

Patrick, can I regard this as the official fix for 2.6.33?

Jon.



^ permalink raw reply

* Re: [PATCH net-next-2.6 v3] can: mcp251x: Move to threaded interrupts instead of workqueues.
From: Wolfgang Grandegger @ 2010-02-03 20:14 UTC (permalink / raw)
  To: Christian Pellegrin
  Cc: socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1265218794-25808-1-git-send-email-chripell-VaTbYqLCNhc@public.gmane.org>

Christian Pellegrin wrote:
> This patch addresses concerns about efficiency of handling incoming
> packets. Handling of interrupts is done in a threaded interrupt handler
> which has a smaller latency than workqueues. This change needed a rework
> of the locking scheme that was much simplified. Some other (more or less
> longstanding) bugs are fixed: utilization of just half of the RX
> buffers, useless wait for interrupt on open, more reliable reset
> sequence. The MERR interrupt is not used anymore: it overloads the CPU
> in error-passive state without any additional information. One shot mode
> is disabled because it's not clear if it can be handled efficiently on
> this CAN controller.
> 
> Signed-off-by: Christian Pellegrin <chripell-VaTbYqLCNhc@public.gmane.org>

Acked-by: Wolfgang Grandegger <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>

Thanks.

Wolfgang

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox