Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] virtif: initial interface extensions
From: Scott Feldman @ 2010-05-11  0:25 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Stefan Berger, netdev
In-Reply-To: <201005102346.38229.arnd@arndb.de>

On 5/10/10 2:46 PM, "Arnd Bergmann" <arnd@arndb.de> wrote:

> On Monday 10 May 2010 20:56:39 Scott Feldman wrote:
>> With Arnd's latest additions, we have a single netlink msg, but the
>> parameter sets are disjoint between VDP/CDCP and what we need for the kernel
>> driver.  So that means the sender (libvirt in this case) needs to know about
>> both setups to send a single netlink msg.  An alternative is a have two
>> netlink msgs, one for each setup.  That still requires the sender to know
>> about two setups.
> 
> There are two separate issues here. The first one is whether we're doing
> the association in the device driver or in user space. The assumption here
> is that if it's in the device driver, there will be a VF number to identify
> the channel, while in user space that is not needed.
> 
> The other question is which protocol we're using. There are as far as I
> can tell five options:
> 
> 1. enic device driver
> 2. VDP
> 3. CDCP
> 4. CDCP + VDP
> 5. enic + VDP
> 
> The first two ones are the most interesting for now, since Linux cannot do
> S-VLANs yet, and they are required for CDCP. However, each of these options
> could theoreticall be done in the kernel (plus firmware) or in user space.
> 
> If it's done in user space, the VF number is meaningless, because the setup
> of the software device is also done from software, but instead you need to
> take care of creating the software device with the correct parameters, e.g.
> a macvtap device connected to a VLAN interface using the numbers you pass
> in the VDP protocol.
> 
> Right now, we're not planning to do the protocol that enic uses in LLDPAD,
> because it's not publically released. Similarly, there are no adapters that
> do VDP in firmware, but both these cases should be covered by the protocol
> and it would be good if libvirt could handle them.
> 
> Stefan, can you just define the XML in a way that matches the netlink
> definition? What you need is something like
> 
> 1. VF number (optional, signifies that 2/3 are done in firmware)
> 2. Lower-level protocol
>   2.1. CDCP
>      2.1.1 SVID
>      2.1.2 SCID
>   2.2. enic
>      2.2.1 port profile name
>      2.2.2 ...
> 3. VDP
>   3.1 VSI type/version/provider
>   3.2 UUID
>   3.3 MAC/VLAN
> 
> You need to have 2. or 3. or both, and 2.1/2.2 are mutually exclusive.

I'm don't think this is going in the right direction.  We're talking a
pretty simple concept of a port-profile used to configure the virtual port
backing a VM i/f to something that's trying to munge disjoint protocols
based on pre-standard work into a single API.  It's forcing all those
pre-standard protocol details into the API, into the XML, and into the mgmt
software (libvirt), and into the admin's lap.

I want the API to pass a port-profile name plus other information associated
with the VM i/f to some mgmt object which can setup the virtual port backing
the VM i/f.  (And unset it).  Using netlink for API let's that object be in
user- or kernel-space software, hardware or firmware.  How the object sets
up the virtual port based on the passed port-profile is beyond the scope of
the API.

My last port-profile patch is this API.  It gives us this:

    1) single netlink msg for kernel- and user-space
    2) single parameter set from sender's perspective (libvirt)
    3) single XML representation of parameters
    4) single code path in kernel and libvirt
    5) (potential) cross-vendor-switch VM migration
    6) admin-friendly port-profile names
    7) allows pre-standard (802.1Qbg/bh) details to change
       without bogging down the API

What I proposed on the libvirt list is to maintain a mapping database from
port-profile to vendor-specific or protocol-specific parameters.  Using VDP
as an example, a port-profile would resolve the VDP tuple:

     port-profile: "joes-garage"   --->  VSI Manager ID: 15
                                         VSI Type ID: 12345
                                         VSI Type ID Ver: 1
                                         other VSI settings (preassociate)

How the mapping database is maintained is beyond the scope of the API.

The port-profile string is the unifying concept.  This is the common ground
and the only way to be protocol-independent in the API.

-scott


^ permalink raw reply

* [PATCH net-next-2.6 1/2] bonding: add keep_all parameter
From: Andy Gospodarek @ 2010-05-11  0:29 UTC (permalink / raw)
  To: netdev


In an effort to suppress duplicate frames on certain bonding modes
(specifically the modes that do not require additional configuration on
the switch or switches connected to the host), code was added in the
generic receive patch in 2.6.16.  The current behavior works quite well
for most users, but there are some times it would be nice to restore old
functionality and allow all frames to make their way up the stack.

This patch adds support for a new module option and sysfs file called
'keep_all' that will restore pre-2.6.16 functionality if the user
desires.  The default value is '0' and retains existing behavior, but
the user can set it to '1' and allow all frames up if desired.

Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
---
 Documentation/networking/bonding.txt |   15 ++++++++++++
 drivers/net/bonding/bond_main.c      |   15 ++++++++++++
 drivers/net/bonding/bond_sysfs.c     |   43 +++++++++++++++++++++++++++++++++-
 drivers/net/bonding/bonding.h        |    1 +
 include/linux/if.h                   |    1 +
 net/core/dev.c                       |   26 +++++++++++---------
 6 files changed, 88 insertions(+), 13 deletions(-)

diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index 61f516b..d64fd2f 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -399,6 +399,21 @@ fail_over_mac
 	This option was added in bonding version 3.2.0.  The "follow"
 	policy was added in bonding version 3.3.0.
 
+keep_all
+
+	Option to specify whether or not you will keep all frames
+	received on an interface that is a member of a bond.  Right
+	now checking is done to ensure that most frames ultimately
+	classified as duplicates are dropped to keep noise to a
+	minimum.  The feature to drop duplicates was added in kernel
+	version 2.6.16 (bonding driver version 3.0.2) and this will
+	allow that original behavior to be restored if desired.
+
+	A value of 0 (default) will preserve the current behavior and
+	will drop all duplicate frames the bond may receive.  A value
+	of 1 will not attempt to avoid duplicate frames and pass all
+	of them up the stack.
+
 lacp_rate
 
 	Option specifying the rate in which we'll ask our link partner
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 5e12462..eb86363 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -106,6 +106,7 @@ static int arp_interval = BOND_LINK_ARP_INTERV;
 static char *arp_ip_target[BOND_MAX_ARP_TARGETS];
 static char *arp_validate;
 static char *fail_over_mac;
+static int keep_all	= 0;
 static struct bond_params bonding_defaults;
 
 module_param(max_bonds, int, 0);
@@ -155,6 +156,9 @@ module_param(arp_validate, charp, 0);
 MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all");
 module_param(fail_over_mac, charp, 0);
 MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to the same MAC.  none (default), active or follow");
+module_param(keep_all, int, 0);
+MODULE_PARM_DESC(keep_all, "Keep all frames received on an interface"
+			   "0 for never (default), 1 for always.");
 
 /*----------------------------- Global variables ----------------------------*/
 
@@ -4542,6 +4546,9 @@ static void bond_setup(struct net_device *bond_dev)
 	if (bond->params.arp_interval)
 		bond_dev->priv_flags |= IFF_MASTER_ARPMON;
 
+	if (bond->params.keep_all)
+		bond_dev->priv_flags |= IFF_BONDING_KEEP_ALL;
+
 	/* At first, we block adding VLANs. That's the only way to
 	 * prevent problems that occur when adding VLANs over an
 	 * empty bond. The block will be removed once non-challenged
@@ -4756,6 +4763,13 @@ static int bond_check_params(struct bond_params *params)
 		}
 	}
 
+	if ((keep_all != 0) && (keep_all != 1)) {
+		pr_warning("Warning: keep_all module parameter (%d), "
+			   "not of valid value (0/1), so it was set to "
+			   "0\n", keep_all);
+		keep_all = 0;
+	}
+
 	/* reset values for TLB/ALB */
 	if ((bond_mode == BOND_MODE_TLB) ||
 	    (bond_mode == BOND_MODE_ALB)) {
@@ -4926,6 +4940,7 @@ static int bond_check_params(struct bond_params *params)
 	params->primary[0] = 0;
 	params->primary_reselect = primary_reselect_value;
 	params->fail_over_mac = fail_over_mac_value;
+	params->keep_all = keep_all;
 
 	if (primary) {
 		strncpy(params->primary, primary, IFNAMSIZ);
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index b8bec08..44651ce 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -339,7 +339,6 @@ out:
 
 static DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves,
 		   bonding_store_slaves);
-
 /*
  * Show and set the bonding mode.  The bond interface must be down to
  * change the mode.
@@ -1472,6 +1471,47 @@ static ssize_t bonding_show_ad_partner_mac(struct device *d,
 }
 static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
 
+/*
+ * Show and set the keep_all flag.
+ */
+static ssize_t bonding_show_keep(struct device *d,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct bonding *bond = to_bond(d);
+
+	return sprintf(buf, "%d\n", bond->params.keep_all);
+}
+
+static ssize_t bonding_store_keep(struct device *d,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	int new_value, ret = count;
+	struct bonding *bond = to_bond(d);
+
+	if (sscanf(buf, "%d", &new_value) != 1) {
+		pr_err("%s: no keep_all value specified.\n",
+		       bond->dev->name);
+		ret = -EINVAL;
+		goto out;
+	}
+	if ((new_value == 0) || (new_value == 1)) {
+		bond->params.keep_all = new_value;
+		if (bond->params.keep_all)
+			bond->dev->priv_flags |= IFF_BONDING_KEEP_ALL;
+		else
+			bond->dev->priv_flags &= ~IFF_BONDING_KEEP_ALL;
+	} else {
+		pr_info("%s: Ignoring invalid keep_all value %d.\n",
+			bond->dev->name, new_value);
+	}
+out:
+	return count;
+}
+static DEVICE_ATTR(keep_all, S_IRUGO | S_IWUSR,
+		   bonding_show_keep, bonding_store_keep);
+
 
 
 static struct attribute *per_bond_attrs[] = {
@@ -1499,6 +1539,7 @@ static struct attribute *per_bond_attrs[] = {
 	&dev_attr_ad_actor_key.attr,
 	&dev_attr_ad_partner_key.attr,
 	&dev_attr_ad_partner_mac.attr,
+	&dev_attr_keep_all.attr,
 	NULL,
 };
 
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 2aa3367..3b7532f 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -131,6 +131,7 @@ struct bond_params {
 	char primary[IFNAMSIZ];
 	int primary_reselect;
 	__be32 arp_targets[BOND_MAX_ARP_TARGETS];
+	int keep_all;
 };
 
 struct bond_parm_tbl {
diff --git a/include/linux/if.h b/include/linux/if.h
index be350e6..e9f6040 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -73,6 +73,7 @@
 #define IFF_DONT_BRIDGE 0x800		/* disallow bridging this ether dev */
 #define IFF_IN_NETPOLL	0x1000		/* whether we are processing netpoll */
 #define IFF_DISABLE_NETPOLL	0x2000	/* disable netpoll at run-time */
+#define IFF_BONDING_KEEP_ALL	0x4000	/* do not drop possible dup frames */
 
 #define IF_GET_IFACE	0x0001		/* for querying only */
 #define IF_GET_PROTO	0x0002
diff --git a/net/core/dev.c b/net/core/dev.c
index 32611c8..9a9c01d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2758,21 +2758,23 @@ int __skb_bond_should_drop(struct sk_buff *skb, struct net_device *master)
 		skb_bond_set_mac_by_master(skb, master);
 	}
 
-	if (dev->priv_flags & IFF_SLAVE_INACTIVE) {
-		if ((dev->priv_flags & IFF_SLAVE_NEEDARP) &&
-		    skb->protocol == __cpu_to_be16(ETH_P_ARP))
-			return 0;
+	if (unlikely(!(master->priv_flags & IFF_BONDING_KEEP_ALL))) {
+		if (dev->priv_flags & IFF_SLAVE_INACTIVE) {
+			if ((dev->priv_flags & IFF_SLAVE_NEEDARP) &&
+			    skb->protocol == __cpu_to_be16(ETH_P_ARP))
+				return 0;
 
-		if (master->priv_flags & IFF_MASTER_ALB) {
-			if (skb->pkt_type != PACKET_BROADCAST &&
-			    skb->pkt_type != PACKET_MULTICAST)
+			if (master->priv_flags & IFF_MASTER_ALB) {
+				if (skb->pkt_type != PACKET_BROADCAST &&
+				    skb->pkt_type != PACKET_MULTICAST)
+					return 0;
+			}
+			if (master->priv_flags & IFF_MASTER_8023AD &&
+			    skb->protocol == __cpu_to_be16(ETH_P_SLOW))
 				return 0;
-		}
-		if (master->priv_flags & IFF_MASTER_8023AD &&
-		    skb->protocol == __cpu_to_be16(ETH_P_SLOW))
-			return 0;
 
-		return 1;
+			return 1;
+		}
 	}
 	return 0;
 }
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH net-next-2.6 2/2] bonding: allow user-controlled output slave selection
From: Andy Gospodarek @ 2010-05-11  0:32 UTC (permalink / raw)
  To: netdev


This patch give the user the ability to control the output slave for
round-robin and active-backup bonding.  Similar functionality was
discussed in the past, but Jay Vosburgh indicated he would rather see a
feature like this added to existing modes rather than creating a
completely new mode.  Jay's thoughts as well as Neil's input surrounding
some of the issues with the first implementation pushed us toward a
design that relied on the queue_mapping rather than skb marks.
Round-robin and active-backup modes were chosen as the first users of
this slave selection as they seemed like the most logical choices when
considering a multi-switch environment.

Round-robin mode works without any modification, but active-backup does
require inclusion of the first patch in this series and setting
the 'keep_all' flag.  This will allow reception of unicast traffic on
any of the backup interfaces.

This was tested with IPv4-based filters as well as VLAN-based filters
with good results.

More information as well as a configuration example is available in the
patch to Documentation/networking/bonding.txt.

Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
---
 Documentation/networking/bonding.txt |   76 +++++++++++++++++++++-
 drivers/net/bonding/bond_main.c      |   77 +++++++++++++++++++++-
 drivers/net/bonding/bond_sysfs.c     |  117 +++++++++++++++++++++++++++++++++-
 drivers/net/bonding/bonding.h        |    5 ++
 include/linux/if_bonding.h           |    1 +
 5 files changed, 270 insertions(+), 6 deletions(-)

diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index d64fd2f..fd277c1 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -49,6 +49,7 @@ Table of Contents
 3.3	Configuring Bonding Manually with Ifenslave
 3.3.1		Configuring Multiple Bonds Manually
 3.4	Configuring Bonding Manually via Sysfs
+3.5	Overriding Configuration for Special Cases
 
 4. Querying Bonding Configuration
 4.1	Bonding Configuration
@@ -1333,8 +1334,79 @@ echo 2000 > /sys/class/net/bond1/bonding/arp_interval
 echo +eth2 > /sys/class/net/bond1/bonding/slaves
 echo +eth3 > /sys/class/net/bond1/bonding/slaves
 
-
-4. Querying Bonding Configuration 
+3.5 Overriding Configuration for Special Cases
+----------------------------------------------
+Nominally, when using the bonding driver, the physical port which transmits a
+frame is selected by the bonding driver, and is not relevant to the user or
+system administrator.  The output port is simply selected using the policies of
+the selected bonding mode.  On occasion however, it is helpful to direct certain
+classes of traffic to certain physical interfaces on output to implement
+slightly more complex policies.  For example, to reach a web server over a
+bonded interface in which eth0 connects to a private network, while eth1
+connects via a public network, it may be desirous to bias the bond to send said
+traffic over eth0 first, using eth1 only as a fall back, while all other traffic
+can safely be sent over either interface.  Such configurations may be achieved
+using the traffic control utilities inherent in linux.
+
+By default the bonding driver is multiqueue aware and 16 queues are created
+when the driver initializes (see Documentation/networking/multiqueue.txt
+for details).  If more or less queues are desired the module parameter
+tx_queues can be used to change this value.  There is no sysfs parameter
+available as the allocation is done at module init time.
+
+The output of the file /proc/net/bonding/bondX has changed so the output Queue
+ID is now printed for each slave:
+
+Bonding Mode: fault-tolerance (active-backup)
+Primary Slave: None
+Currently Active Slave: eth0
+MII Status: up
+MII Polling Interval (ms): 0
+Up Delay (ms): 0
+Down Delay (ms): 0
+
+Slave Interface: eth0
+MII Status: up
+Link Failure Count: 0
+Permanent HW addr: 00:1a:a0:12:8f:cb
+Slave queue ID: 0
+
+Slave Interface: eth1
+MII Status: up
+Link Failure Count: 0
+Permanent HW addr: 00:1a:a0:12:8f:cc
+Slave queue ID: 2
+
+The queue_id for a slave can be set using the command:
+
+# echo "eth1:2" > /sys/class/net/bond0/bonding/queue_id
+
+Any interface that needs a queue_id set should set it with multiple calls
+like the one above until proper priorities are set for all interfaces.  On
+distributions that allow configuration via initscripts, multiple 'queue_id'
+arguments can be added to BONDING_OPTS to set all needed slave queues.
+
+These queue id's can be used in conjunction with the tc utility to configure
+a multiqueue qdisc and filters to bias certain traffic to transmit on certain
+slave devices.  For instance, say we wanted, in the above configuration to
+force all traffic bound to 192.168.1.100 to use eth1 in the bond as its output
+device. The following commands would accomplish this:
+
+# tc qdisc add dev bond0 handle 1 root multiq
+
+# tc filter add dev bond0 protocol ip parent 1: prio 1 u32 match ip dst \
+	192.168.1.100 action skbedit queue_mapping 2
+
+These commands tell the kernel to attach a multiqueue queue discipline to the
+bond0 interface and filter traffic enqueued to it, such that packets with a dst
+ip of 192.168.1.100 have their output queue mapping value overwritten to 2.
+This value is then passed into the driver, causing the normal output path
+selection policy to be overridden, selecting instead qid 2, which maps to eth1.
+
+Note that qid values begin at 1.  qid 0 is reserved to initiate to the driver
+that normal output policy selection should take place.
+
+4 Querying Bonding Configuration
 =================================
 
 4.1 Bonding Configuration
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index eb86363..aa6a79a 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -90,6 +90,7 @@
 #define BOND_LINK_ARP_INTERV	0
 
 static int max_bonds	= BOND_DEFAULT_MAX_BONDS;
+static int tx_queues	= BOND_DEFAULT_TX_QUEUES;
 static int num_grat_arp = 1;
 static int num_unsol_na = 1;
 static int miimon	= BOND_LINK_MON_INTERV;
@@ -111,6 +112,8 @@ static struct bond_params bonding_defaults;
 
 module_param(max_bonds, int, 0);
 MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
+module_param(tx_queues, int, 0);
+MODULE_PARM_DESC(tx_queues, "Max number of transmit queues (default = 16)");
 module_param(num_grat_arp, int, 0644);
 MODULE_PARM_DESC(num_grat_arp, "Number of gratuitous ARP packets to send on failover event");
 module_param(num_unsol_na, int, 0644);
@@ -1532,6 +1535,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 		goto err_undo_flags;
 	}
 
+	/*
+	 * Set the new_slave's queue_id to be zero.  Queue ID mapping
+	 * is set via sysfs or module option if desired.
+	 */
+	new_slave->queue_id = 0;
+
 	/* save slave's original flags before calling
 	 * netdev_set_master and dev_open
 	 */
@@ -1790,6 +1799,7 @@ err_restore_mac:
 	}
 
 err_free:
+	new_slave->queue_id = 0;
 	kfree(new_slave);
 
 err_undo_flags:
@@ -1977,6 +1987,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
 				   IFF_SLAVE_INACTIVE | IFF_BONDING |
 				   IFF_SLAVE_NEEDARP);
 
+	slave->queue_id = 0;
 	kfree(slave);
 
 	return 0;  /* deletion OK */
@@ -3269,6 +3280,7 @@ static void bond_info_show_slave(struct seq_file *seq,
 		else
 			seq_puts(seq, "Aggregator ID: N/A\n");
 	}
+	seq_printf(seq, "Slave queue ID: %d\n", slave->queue_id);
 }
 
 static int bond_info_seq_show(struct seq_file *seq, void *v)
@@ -4405,9 +4417,59 @@ static void bond_set_xmit_hash_policy(struct bonding *bond)
 	}
 }
 
+/*
+ * Lookup the slave that corresponds to a qid
+ */
+static inline int bond_slave_override(struct bonding *bond,
+				      struct sk_buff *skb)
+{
+	int i, res = 1;
+	struct slave *slave = NULL;
+	struct slave *check_slave;
+
+	read_lock(&bond->lock);
+
+	if (!BOND_IS_OK(bond) || !skb->queue_mapping)
+		goto out;
+
+	/* Find out if any slaves have the same mapping as this skb. */
+	bond_for_each_slave(bond, check_slave, i) {
+		if (check_slave->queue_id == skb->queue_mapping) {
+			slave = check_slave;
+			break;
+		}
+	}
+
+	/* If the slave isn't UP, use default transmit policy. */
+	if (slave && slave->queue_id && IS_UP(slave->dev) &&
+	    (slave->link == BOND_LINK_UP)) {
+		res = bond_dev_queue_xmit(bond, skb, slave->dev);
+	}
+
+out:
+	read_unlock(&bond->lock);
+	return res;
+}
+
+static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+	/*
+	 * This helper function exists to help dev_pick_tx get the correct
+	 * destination queue.  Using a helper function skips the a call to
+	 * skb_tx_hash and will put the skbs in the queue we expect on their
+	 * way down to the bonding driver.
+	 */
+	return skb->queue_mapping;
+}
+
 static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	const struct bonding *bond = netdev_priv(dev);
+	struct bonding *bond = netdev_priv(dev);
+
+	if (TX_QUEUE_OVERRIDE(bond->params.mode)) {
+		if (!bond_slave_override(bond, skb))
+			return NETDEV_TX_OK;
+	}
 
 	switch (bond->params.mode) {
 	case BOND_MODE_ROUNDROBIN:
@@ -4492,6 +4554,7 @@ static const struct net_device_ops bond_netdev_ops = {
 	.ndo_open		= bond_open,
 	.ndo_stop		= bond_close,
 	.ndo_start_xmit		= bond_start_xmit,
+	.ndo_select_queue	= bond_select_queue,
 	.ndo_get_stats		= bond_get_stats,
 	.ndo_do_ioctl		= bond_do_ioctl,
 	.ndo_set_multicast_list	= bond_set_multicast_list,
@@ -4763,6 +4826,13 @@ static int bond_check_params(struct bond_params *params)
 		}
 	}
 
+	if (tx_queues < 1 || tx_queues > 255) {
+		pr_warning("Warning: tx_queues (%d) should be between "
+			   "1 and 255, resetting to %d\n",
+			   tx_queues, BOND_DEFAULT_TX_QUEUES);
+		tx_queues = BOND_DEFAULT_TX_QUEUES;
+	}
+
 	if ((keep_all != 0) && (keep_all != 1)) {
 		pr_warning("Warning: keep_all module parameter (%d), "
 			   "not of valid value (0/1), so it was set to "
@@ -4940,6 +5010,7 @@ static int bond_check_params(struct bond_params *params)
 	params->primary[0] = 0;
 	params->primary_reselect = primary_reselect_value;
 	params->fail_over_mac = fail_over_mac_value;
+	params->tx_queues = tx_queues;
 	params->keep_all = keep_all;
 
 	if (primary) {
@@ -5027,8 +5098,8 @@ int bond_create(struct net *net, const char *name)
 
 	rtnl_lock();
 
-	bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "",
-				bond_setup);
+	bond_dev = alloc_netdev_mq(sizeof(struct bonding), name ? name : "",
+				bond_setup, tx_queues);
 	if (!bond_dev) {
 		pr_err("%s: eek! can't alloc netdev!\n", name);
 		rtnl_unlock();
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 44651ce..87bfcf1 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -1472,6 +1472,121 @@ static ssize_t bonding_show_ad_partner_mac(struct device *d,
 static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
 
 /*
+ * Show the queue_ids of the slaves in the current bond.
+ */
+static ssize_t bonding_show_queue_id(struct device *d,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct slave *slave;
+	int i, res = 0;
+	struct bonding *bond = to_bond(d);
+
+	if (!rtnl_trylock())
+		return restart_syscall();
+
+	read_lock(&bond->lock);
+	bond_for_each_slave(bond, slave, i) {
+		if (res > (PAGE_SIZE - 6)) {
+			/* not enough space for another interface name */
+			if ((PAGE_SIZE - res) > 10)
+				res = PAGE_SIZE - 10;
+			res += sprintf(buf + res, "++more++ ");
+			break;
+		}
+		res += sprintf(buf + res, "%s:%d ",
+			       slave->dev->name, slave->queue_id);
+	}
+	read_unlock(&bond->lock);
+	if (res)
+		buf[res-1] = '\n'; /* eat the leftover space */
+	rtnl_unlock();
+	return res;
+}
+
+/*
+ * Set the queue_ids of the  slaves in the current bond.  The bond
+ * interface must be enslaved for this to work.
+ */
+static ssize_t bonding_store_queue_id(struct device *d,
+				      struct device_attribute *attr,
+				      const char *buffer, size_t count)
+{
+	struct slave *slave, *update_slave;
+	struct bonding *bond = to_bond(d);
+	u16 qid;
+	int i, ret = count;
+	char *delim;
+	struct net_device *sdev = NULL;
+
+	if (!rtnl_trylock())
+		return restart_syscall();
+
+	/* delim will point to queue id if successful */
+	delim = strchr(buffer, ':');
+	if (!delim)
+		goto err_no_cmd;
+
+	/*
+	 * Terminate string that points to device name and bump it
+	 * up one, so we can read the queue id there.
+	 */
+	*delim = '\0';
+	if (sscanf(++delim, "%hd\n", &qid) != 1)
+		goto err_no_cmd;
+
+	/* Check buffer length, valid ifname and queue id */
+	if (strlen(buffer) > IFNAMSIZ ||
+	    !dev_valid_name(buffer) ||
+	    qid > bond->params.tx_queues)
+		goto err_no_cmd;
+
+	/* Get the pointer to that interface if it exists */
+	sdev = __dev_get_by_name(dev_net(bond->dev), buffer);
+	if (!sdev)
+		goto err_no_cmd;
+
+	read_lock(&bond->lock);
+
+	/* Search for thes slave and check for duplicate qids */
+	update_slave = NULL;
+	bond_for_each_slave(bond, slave, i) {
+		if (sdev == slave->dev)
+			/*
+			 * We don't need to check the matching
+			 * slave for dups, since we're overwriting it
+			 */
+			update_slave = slave;
+		else if (qid && qid == slave->queue_id) {
+			goto err_no_cmd_unlock;
+		}
+	}
+
+	if (!update_slave)
+		goto err_no_cmd_unlock;
+
+	/* Actually set the qids for the slave */
+	update_slave->queue_id = qid;
+
+	read_unlock(&bond->lock);
+out:
+	rtnl_unlock();
+	return ret;
+
+err_no_cmd_unlock:
+	read_unlock(&bond->lock);
+err_no_cmd:
+	pr_info("invalid input for queue_id set for %s.\n",
+		bond->dev->name);
+	ret = -EPERM;
+	goto out;
+}
+
+static DEVICE_ATTR(queue_id, S_IRUGO | S_IWUSR, bonding_show_queue_id,
+		   bonding_store_queue_id);
+
+
+/*
  * Show and set the keep_all flag.
  */
 static ssize_t bonding_show_keep(struct device *d,
@@ -1513,7 +1628,6 @@ static DEVICE_ATTR(keep_all, S_IRUGO | S_IWUSR,
 		   bonding_show_keep, bonding_store_keep);
 
 
-
 static struct attribute *per_bond_attrs[] = {
 	&dev_attr_slaves.attr,
 	&dev_attr_mode.attr,
@@ -1539,6 +1653,7 @@ static struct attribute *per_bond_attrs[] = {
 	&dev_attr_ad_actor_key.attr,
 	&dev_attr_ad_partner_key.attr,
 	&dev_attr_ad_partner_mac.attr,
+	&dev_attr_queue_id.attr,
 	&dev_attr_keep_all.attr,
 	NULL,
 };
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 3b7532f..274a3a1 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -60,6 +60,9 @@
 		 ((mode) == BOND_MODE_TLB)          ||	\
 		 ((mode) == BOND_MODE_ALB))
 
+#define TX_QUEUE_OVERRIDE(mode)				\
+			(((mode) == BOND_MODE_ACTIVEBACKUP) ||	\
+			 ((mode) == BOND_MODE_ROUNDROBIN))
 /*
  * Less bad way to call ioctl from within the kernel; this needs to be
  * done some other way to get the call out of interrupt context.
@@ -131,6 +134,7 @@ struct bond_params {
 	char primary[IFNAMSIZ];
 	int primary_reselect;
 	__be32 arp_targets[BOND_MAX_ARP_TARGETS];
+	int tx_queues;
 	int keep_all;
 };
 
@@ -166,6 +170,7 @@ struct slave {
 	u8     perm_hwaddr[ETH_ALEN];
 	u16    speed;
 	u8     duplex;
+	u16    queue_id;
 	struct ad_slave_info ad_info; /* HUGE - better to dynamically alloc */
 	struct tlb_slave_info tlb_info;
 };
diff --git a/include/linux/if_bonding.h b/include/linux/if_bonding.h
index cd525fa..2c79943 100644
--- a/include/linux/if_bonding.h
+++ b/include/linux/if_bonding.h
@@ -83,6 +83,7 @@
 
 #define BOND_DEFAULT_MAX_BONDS  1   /* Default maximum number of devices to support */
 
+#define BOND_DEFAULT_TX_QUEUES 16   /* Default number of tx queues per device */
 /* hashing types */
 #define BOND_XMIT_POLICY_LAYER2		0 /* layer 2 (MAC only), default */
 #define BOND_XMIT_POLICY_LAYER34	1 /* layer 3+4 (IP ^ (TCP || UDP)) */
-- 
1.6.2.5


^ permalink raw reply related

* [stable-2.6.32 PATCH] ixgbe: backport bug fix for tx panic
From: Jeff Kirsher @ 2010-05-11  0:46 UTC (permalink / raw)
  To: stable, greg; +Cc: netdev, linux-kernel, davem, Brandon, Jesse Brandeburg

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

backporting this commit:

commit fdd3d631cddad20ad9d3e1eb7dbf26825a8a121f
Author: Krishna Kumar <krkumar2@in.ibm.com>
Date:   Wed Feb 3 13:13:10 2010 +0000

    ixgbe: Fix return of invalid txq

    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>
    Signed-off-by: David S. Miller <davem@davemloft.net>

CC: Brandon <brandon@ifup.org>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
---

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

diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 6339d65..a873c5d 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -5241,9 +5241,13 @@ static int ixgbe_maybe_stop_tx(struct net_device *netdev,
 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)
-		return smp_processor_id();
+	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
+		while (unlikely(txq >= dev->real_num_tx_queues))
+			txq -= dev->real_num_tx_queues;
+		return txq;
+	}
 
 	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
 		return (skb->vlan_tci & IXGBE_TX_FLAGS_VLAN_PRIO_MASK) >> 13;

^ permalink raw reply related

* e1000e fails probe
From: Pete Zaitcev @ 2010-05-11  0:50 UTC (permalink / raw)
  To: netdev; +Cc: zaitcev

Dear All:

I have a box where e1000e would refuse to probe the onboard interface
with the following in dmesg:

e1000e: Intel(R) PRO/1000 Network Driver - 1.0.2-k2
e1000e: Copyright (c) 1999 - 2009 Intel Corporation.
e1000e 0000:00:19.0: PCI INT A -> GSI 20 (level, low) -> IRQ 20
e1000e 0000:00:19.0: setting latency timer to 64
e1000e 0000:00:19.0: irq 34 for MSI/MSI-X
0000:00:19.0: 0000:00:19.0: MDI Error
e1000e 0000:00:19.0: PCI INT A disabled
e1000e: probe of 0000:00:19.0 failed with error -2

The "MDI Error" seems to indicate a hardware failure, so I paid it no
mind until I noticed that RHEL 5 works. So, I diffed the drivers
between Linus' 2.6.34-rc5 and RHEL's 2.6.18-180.el5, with the following
minimal patch working for me:

diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index 8b5e157..b97cd9f 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -276,19 +276,21 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
 
 	phy->id = e1000_phy_unknown;
 	ret_val = e1000e_get_phy_id(hw);
-	if (ret_val)
-		goto out;
-	if ((phy->id == 0) || (phy->id == PHY_REVISION_MASK)) {
+/* P3 */ printk("get_phy_id.fast ret %d id %d\n", ret_val, phy->id);
+	if (ret_val || (phy->id == 0) || (phy->id == PHY_REVISION_MASK)) {
 		/*
 		 * In case the PHY needs to be in mdio slow mode (eg. 82577),
 		 * set slow mode and try to get the PHY id again.
 		 */
 		ret_val = e1000_set_mdio_slow_mode_hv(hw);
-		if (ret_val)
-			goto out;
-		ret_val = e1000e_get_phy_id(hw);
-		if (ret_val)
-			goto out;
+		if (ret_val) {
+/* P3 */ printk("failed to set mdio slow mode %d\n", ret_val);
+			phy->id = e1000_phy_unknown;
+		} else {
+			ret_val = e1000e_get_phy_id(hw);
+/* P3 */ printk("get_phy_id.slow ret %d id %d\n", ret_val, phy->id);
+		}
+		ret_val = 0; /* P3 */
 	}
 	phy->type = e1000e_get_phy_type_from_id(phy->id);
 
@@ -307,11 +309,10 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
 		phy->ops.get_info = e1000e_get_phy_info_m88;
 		break;
 	default:
-		ret_val = -E1000_ERR_PHY;
+/* P3 */ printk("not doing anything for phy type %d\n", phy->type);
 		break;
 	}
 
-out:
 	return ret_val;
 }
 
@@ -354,7 +355,10 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
 		msleep(1);
 		ret_val = e1000e_get_phy_id(hw);
 		if (ret_val)
+{
+/* P3 */ printk("get_phy_id for params ret %d id %d\n", ret_val, phy->id);
 			return ret_val;
+}
 	}
 
 	/* Verify phy id */
@@ -777,6 +781,77 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
 }
 
 /**
+ *  e1000_phy_force_speed_duplex_ich8lan - Force PHY speed & duplex
+ *  @hw: pointer to the HW structure
+ *
+ *  Forces the speed and duplex settings of the PHY.
+ *  This is a function pointer entry point only called by
+ *  PHY setup routines.
+ **/
+static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 data;
+	bool link;
+
+	if (phy->type != e1000_phy_ife) {
+		ret_val = e1000e_phy_force_speed_duplex_igp(hw);
+		return ret_val;
+	}
+
+	ret_val = e1e_rphy(hw, PHY_CONTROL, &data);
+	if (ret_val)
+		return ret_val;
+
+	e1000e_phy_force_speed_duplex_setup(hw, &data);
+
+	ret_val = e1e_wphy(hw, PHY_CONTROL, data);
+	if (ret_val)
+		return ret_val;
+
+	/* Disable MDI-X support for 10/100 */
+	ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data);
+	if (ret_val)
+		return ret_val;
+
+	data &= ~IFE_PMC_AUTO_MDIX;
+	data &= ~IFE_PMC_FORCE_MDIX;
+
+	ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, data);
+	if (ret_val)
+		return ret_val;
+
+	e_dbg("IFE PMC: %X\n", data);
+
+	udelay(1);
+
+	if (phy->autoneg_wait_to_complete) {
+		e_dbg("Waiting for forced speed/duplex link on IFE phy.\n");
+
+		ret_val = e1000e_phy_has_link_generic(hw,
+						     PHY_FORCE_LIMIT,
+						     100000,
+						     &link);
+		if (ret_val)
+			return ret_val;
+
+		if (!link)
+			e_dbg("Link taking longer than expected.\n");
+
+		/* Try once more */
+		ret_val = e1000e_phy_has_link_generic(hw,
+						     PHY_FORCE_LIMIT,
+						     100000,
+						     &link);
+		if (ret_val)
+			return ret_val;
+	}
+
+	return 0;
+}
+
+/**
  *  e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration
  *  @hw:   pointer to the HW structure
  *
@@ -1273,6 +1348,87 @@ out:
 }
 
 /**
+ *  e1000_get_phy_info_ife_ich8lan - Retrieves various IFE PHY states
+ *  @hw: pointer to the HW structure
+ *
+ *  Populates "phy" structure with various feature states.
+ *  This function is only called by other family-specific
+ *  routines.
+ **/
+static s32 e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 data;
+	bool link;
+
+	ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
+	if (ret_val)
+		return ret_val;
+
+	if (!link) {
+		e_dbg("Phy info is only valid if link is up\n");
+		return -E1000_ERR_CONFIG;
+	}
+
+	ret_val = e1e_rphy(hw, IFE_PHY_SPECIAL_CONTROL, &data);
+	if (ret_val)
+		return ret_val;
+	phy->polarity_correction = (!(data & IFE_PSC_AUTO_POLARITY_DISABLE));
+
+	if (phy->polarity_correction) {
+		ret_val = phy->ops.check_polarity(hw);
+		if (ret_val)
+			return ret_val;
+	} else {
+		/* Polarity is forced */
+		phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY)
+				      ? e1000_rev_polarity_reversed
+				      : e1000_rev_polarity_normal;
+	}
+
+	ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data);
+	if (ret_val)
+		return ret_val;
+
+	phy->is_mdix = (data & IFE_PMC_MDIX_STATUS);
+
+	/* The following parameters are undefined for 10/100 operation. */
+	phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
+	phy->local_rx = e1000_1000t_rx_status_undefined;
+	phy->remote_rx = e1000_1000t_rx_status_undefined;
+
+	return 0;
+}
+
+/**
+ *  e1000_get_phy_info_ich8lan - Calls appropriate PHY type get_info
+ *  @hw: pointer to the HW structure
+ *
+ *  Wrapper for calling the get_info routines for the appropriate phy type.
+ *  This is a function pointer entry point called by drivers
+ *  or other shared routines.
+ **/
+static s32 e1000_get_phy_info_ich8lan(struct e1000_hw *hw)
+{
+	switch (hw->phy.type) {
+	case e1000_phy_ife:
+		return e1000_get_phy_info_ife_ich8lan(hw);
+		break;
+	case e1000_phy_igp_3:
+	case e1000_phy_bm:
+	case e1000_phy_82578:
+	case e1000_phy_82577:
+		return e1000e_get_phy_info_igp(hw);
+		break;
+	default:
+		break;
+	}
+
+	return -E1000_ERR_PHY_TYPE;
+}
+
+/**
  *  e1000_set_lplu_state_pchlan - Set Low Power Link Up state
  *  @hw: pointer to the HW structure
  *  @active: true to enable LPLU, false to disable
@@ -3394,8 +3550,10 @@ static struct e1000_phy_operations ich8_phy_ops = {
 	.acquire		= e1000_acquire_swflag_ich8lan,
 	.check_reset_block	= e1000_check_reset_block_ich8lan,
 	.commit			= NULL,
+	.force_speed_duplex	= e1000_phy_force_speed_duplex_ich8lan,
 	.get_cfg_done		= e1000_get_cfg_done_ich8lan,
 	.get_cable_length	= e1000e_get_cable_length_igp_2,
+	.get_info		= e1000_get_phy_info_ich8lan,
 	.read_reg		= e1000e_read_phy_reg_igp,
 	.release		= e1000_release_swflag_ich8lan,
 	.reset			= e1000_phy_hw_reset_ich8lan,

What seems to be happening here is a persistent failure of
e1000e_get_phy_id, in both "slow" and "fast" MDI modes. However,
in RHEL 5, this failure triggers a chain of workaround and adjustments
that bring up the interface with some default parameters... which
appear to work with my 1Gbit/s Netgear switch. So the hardware is
not dead, or not completely dead.

Could someone come up with a fix here, please? I have no clue where
to start even.

Greetings,
-- Pete

^ permalink raw reply related

* [net-next-2.6 PATCH 01/12] e1000e: use static params to save stack space (part 2)
From: Jeff Kirsher @ 2010-05-11  0:59 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Bruce Allan, Jesse Brandeburg, Jeff Kirsher

From: Bruce Allan <bruce.w.allan@intel.com>

A couple stack cleanups missed in an earlier patch from Jesse.

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Cc: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/param.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c
index 0f4077c..a150e48 100644
--- a/drivers/net/e1000e/param.c
+++ b/drivers/net/e1000e/param.c
@@ -286,7 +286,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
 		}
 	}
 	{ /* Receive Interrupt Delay */
-		struct e1000_option opt = {
+		static struct e1000_option opt = {
 			.type = range_option,
 			.name = "Receive Interrupt Delay",
 			.err  = "using default of "
@@ -386,7 +386,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
 		}
 	}
 	{ /* Interrupt Mode */
-		struct e1000_option opt = {
+		static struct e1000_option opt = {
 			.type = range_option,
 			.name = "Interrupt Mode",
 			.err  = "defaulting to 2 (MSI-X)",


^ permalink raw reply related

* [net-next-2.6 PATCH 02/12] e1000e: bad state after running ethtool diagnostics with AMT enabled
From: Jeff Kirsher @ 2010-05-11  0:59 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Bruce Allan, Jeff Kirsher
In-Reply-To: <20100511005801.30827.50808.stgit@localhost.localdomain>

From: Bruce Allan <bruce.w.allan@intel.com>

When running ethtool online diagnostics with no open interface, there is a
short period of time where the driver relinquishes control of the adapter
during which time AMT (manageability firmware) can put the adapter into an
unknown state resulting in such things as link test failure, hardware hang,
reporting an incorrect link speed, etc.  Resetting the adapter during an
open() resolves this by putting the adapter into a quiescent state.

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/ethtool.c |    9 +++++++++
 drivers/net/e1000e/netdev.c  |   16 +++++++++-------
 2 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 6ff376c..2c52121 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -1737,6 +1737,12 @@ static void e1000_diag_test(struct net_device *netdev,
 		if (if_running)
 			dev_open(netdev);
 	} else {
+		if (!if_running && (adapter->flags & FLAG_HAS_AMT)) {
+			clear_bit(__E1000_TESTING, &adapter->state);
+			dev_open(netdev);
+			set_bit(__E1000_TESTING, &adapter->state);
+		}
+
 		e_info("online testing starting\n");
 		/* Online tests */
 		if (e1000_link_test(adapter, &data[4]))
@@ -1748,6 +1754,9 @@ static void e1000_diag_test(struct net_device *netdev,
 		data[2] = 0;
 		data[3] = 0;
 
+		if (!if_running && (adapter->flags & FLAG_HAS_AMT))
+			dev_close(netdev);
+
 		clear_bit(__E1000_TESTING, &adapter->state);
 	}
 	msleep_interruptible(4 * 1000);
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index c5f65a2..ab79bec 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -3444,6 +3444,15 @@ static int e1000_open(struct net_device *netdev)
 	if (err)
 		goto err_setup_rx;
 
+	/*
+	 * If AMT is enabled, let the firmware know that the network
+	 * interface is now open and reset the part to a known state.
+	 */
+	if (adapter->flags & FLAG_HAS_AMT) {
+		e1000_get_hw_control(adapter);
+		e1000e_reset(adapter);
+	}
+
 	e1000e_power_up_phy(adapter);
 
 	adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
@@ -3452,13 +3461,6 @@ static int e1000_open(struct net_device *netdev)
 		e1000_update_mng_vlan(adapter);
 
 	/*
-	 * If AMT is enabled, let the firmware know that the network
-	 * interface is now open
-	 */
-	if (adapter->flags & FLAG_HAS_AMT)
-		e1000_get_hw_control(adapter);
-
-	/*
 	 * before we allocate an interrupt, we must be ready to handle it.
 	 * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
 	 * as soon as we call pci_request_irq, so we have to setup our


^ permalink raw reply related

* [net-next-2.6 PATCH 03/12] e1000e: initialize manageability (IPMI) pass-through in 82574/82583
From: Jeff Kirsher @ 2010-05-11  0:59 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Bruce Allan, Jeff Kirsher
In-Reply-To: <20100511005801.30827.50808.stgit@localhost.localdomain>

From: Bruce Allan <bruce.w.allan@intel.com>

82574/82583 uses different registers/bits to setup manageability filters
than all other parts supported by e1000e; set them accordingly for IPMI
pass-through.  Rename the function to better reflect what it does.

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/defines.h |    5 ++++
 drivers/net/e1000e/hw.h      |    2 +
 drivers/net/e1000e/netdev.c  |   57 +++++++++++++++++++++++++++++++++++-------
 3 files changed, 55 insertions(+), 9 deletions(-)

diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h
index 7f760aa..227147f 100644
--- a/drivers/net/e1000e/defines.h
+++ b/drivers/net/e1000e/defines.h
@@ -138,6 +138,11 @@
 /* Enable MNG packets to host memory */
 #define E1000_MANC_EN_MNG2HOST   0x00200000
 
+#define E1000_MANC2H_PORT_623    0x00000020 /* Port 0x26f */
+#define E1000_MANC2H_PORT_664    0x00000040 /* Port 0x298 */
+#define E1000_MDEF_PORT_623      0x00000800 /* Port 0x26f */
+#define E1000_MDEF_PORT_664      0x00000400 /* Port 0x298 */
+
 /* Receive Control */
 #define E1000_RCTL_EN             0x00000002    /* enable */
 #define E1000_RCTL_SBP            0x00000004    /* store bad packet */
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index 8bdcd5f..6f66c37 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -208,6 +208,8 @@ enum e1e_registers {
 
 	E1000_KMRNCTRLSTA = 0x00034, /* MAC-PHY interface - RW */
 	E1000_MANC2H    = 0x05860, /* Management Control To Host - RW */
+	E1000_MDEF_BASE = 0x05890, /* Management Decision Filters */
+#define E1000_MDEF(_n)   (E1000_MDEF_BASE + ((_n) * 4))
 	E1000_SW_FW_SYNC = 0x05B5C, /* Software-Firmware Synchronization - RW */
 	E1000_GCR	= 0x05B00, /* PCI-Ex Control */
 	E1000_GCR2      = 0x05B64, /* PCI-Ex Control #2 */
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index ab79bec..36473e6 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -2526,10 +2526,10 @@ static void e1000_restore_vlan(struct e1000_adapter *adapter)
 	}
 }
 
-static void e1000_init_manageability(struct e1000_adapter *adapter)
+static void e1000_init_manageability_pt(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
-	u32 manc, manc2h;
+	u32 manc, manc2h, mdef, i, j;
 
 	if (!(adapter->flags & FLAG_MNG_PT_ENABLED))
 		return;
@@ -2543,10 +2543,49 @@ static void e1000_init_manageability(struct e1000_adapter *adapter)
 	 */
 	manc |= E1000_MANC_EN_MNG2HOST;
 	manc2h = er32(MANC2H);
-#define E1000_MNG2HOST_PORT_623 (1 << 5)
-#define E1000_MNG2HOST_PORT_664 (1 << 6)
-	manc2h |= E1000_MNG2HOST_PORT_623;
-	manc2h |= E1000_MNG2HOST_PORT_664;
+
+	switch (hw->mac.type) {
+	default:
+		manc2h |= (E1000_MANC2H_PORT_623 | E1000_MANC2H_PORT_664);
+		break;
+	case e1000_82574:
+	case e1000_82583:
+		/*
+		 * Check if IPMI pass-through decision filter already exists;
+		 * if so, enable it.
+		 */
+		for (i = 0, j = 0; i < 8; i++) {
+			mdef = er32(MDEF(i));
+
+			/* Ignore filters with anything other than IPMI ports */
+			if (mdef & !(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
+				continue;
+
+			/* Enable this decision filter in MANC2H */
+			if (mdef)
+				manc2h |= (1 << i);
+
+			j |= mdef;
+		}
+
+		if (j == (E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
+			break;
+
+		/* Create new decision filter in an empty filter */
+		for (i = 0, j = 0; i < 8; i++)
+			if (er32(MDEF(i)) == 0) {
+				ew32(MDEF(i), (E1000_MDEF_PORT_623 |
+					       E1000_MDEF_PORT_664));
+				manc2h |= (1 << 1);
+				j++;
+				break;
+			}
+
+		if (!j)
+			e_warn("Unable to create IPMI pass-through filter\n");
+		break;
+	}
+
 	ew32(MANC2H, manc2h);
 	ew32(MANC, manc);
 }
@@ -2961,7 +3000,7 @@ static void e1000_configure(struct e1000_adapter *adapter)
 	e1000_set_multi(adapter->netdev);
 
 	e1000_restore_vlan(adapter);
-	e1000_init_manageability(adapter);
+	e1000_init_manageability_pt(adapter);
 
 	e1000_configure_tx(adapter);
 	e1000_setup_rctl(adapter);
@@ -5104,7 +5143,7 @@ static int __e1000_resume(struct pci_dev *pdev)
 
 	e1000e_reset(adapter);
 
-	e1000_init_manageability(adapter);
+	e1000_init_manageability_pt(adapter);
 
 	if (netif_running(netdev))
 		e1000e_up(adapter);
@@ -5305,7 +5344,7 @@ static void e1000_io_resume(struct pci_dev *pdev)
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
-	e1000_init_manageability(adapter);
+	e1000_init_manageability_pt(adapter);
 
 	if (netif_running(netdev)) {
 		if (e1000e_up(adapter)) {


^ permalink raw reply related

* [net-next-2.6 PATCH 04/12] e1000e: s/w initiated LSC MSI-X interrupts not generated; no transmit
From: Jeff Kirsher @ 2010-05-11  1:00 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Bruce Allan, Jeff Kirsher
In-Reply-To: <20100511005801.30827.50808.stgit@localhost.localdomain>

From: Bruce Allan <bruce.w.allan@intel.com>

In MSI-X mode when an IMPI SoL session was active (i.e. the PHY reset was
blocked), the LSC interrupt generated by s/w to start the watchdog which
started the transmitter was not getting fired by the hardware because bit
24 (the 'other' cause bit) also needed to be set.  Without an active SoL
session, the PHY was reset which caused the h/w to fire the LSC interrupt.

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/netdev.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 36473e6..16a03c5 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -3220,7 +3220,11 @@ int e1000e_up(struct e1000_adapter *adapter)
 	netif_wake_queue(adapter->netdev);
 
 	/* fire a link change interrupt to start the watchdog */
-	ew32(ICS, E1000_ICS_LSC);
+	if (adapter->msix_entries)
+		ew32(ICS, E1000_ICS_LSC | E1000_ICR_OTHER);
+	else
+		ew32(ICS, E1000_ICS_LSC);
+
 	return 0;
 }
 
@@ -3537,7 +3541,10 @@ static int e1000_open(struct net_device *netdev)
 	pm_runtime_put(&pdev->dev);
 
 	/* fire a link status change interrupt to start the watchdog */
-	ew32(ICS, E1000_ICS_LSC);
+	if (adapter->msix_entries)
+		ew32(ICS, E1000_ICS_LSC | E1000_ICR_OTHER);
+	else
+		ew32(ICS, E1000_ICS_LSC);
 
 	return 0;
 


^ permalink raw reply related

* [net-next-2.6 PATCH 05/12] e1000e: cleanup multiple common exit points
From: Jeff Kirsher @ 2010-05-11  1:00 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Bruce Allan, Jeff Kirsher
In-Reply-To: <20100511005801.30827.50808.stgit@localhost.localdomain>

From: Bruce Allan <bruce.w.allan@intel.com>

...in e1000_update_nvm_checksum_ich8lan().

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/ich8lan.c |   41 +++++++++++++++++------------------------
 1 files changed, 17 insertions(+), 24 deletions(-)

diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index b8c4dce..448e123 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -1938,18 +1938,14 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
 		new_bank_offset = nvm->flash_bank_size;
 		old_bank_offset = 0;
 		ret_val = e1000_erase_flash_bank_ich8lan(hw, 1);
-		if (ret_val) {
-			nvm->ops.release(hw);
-			goto out;
-		}
+		if (ret_val)
+			goto release;
 	} else {
 		old_bank_offset = nvm->flash_bank_size;
 		new_bank_offset = 0;
 		ret_val = e1000_erase_flash_bank_ich8lan(hw, 0);
-		if (ret_val) {
-			nvm->ops.release(hw);
-			goto out;
-		}
+		if (ret_val)
+			goto release;
 	}
 
 	for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
@@ -2005,8 +2001,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
 	if (ret_val) {
 		/* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */
 		e_dbg("Flash commit failed.\n");
-		nvm->ops.release(hw);
-		goto out;
+		goto release;
 	}
 
 	/*
@@ -2017,18 +2012,15 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
 	 */
 	act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
 	ret_val = e1000_read_flash_word_ich8lan(hw, act_offset, &data);
-	if (ret_val) {
-		nvm->ops.release(hw);
-		goto out;
-	}
+	if (ret_val)
+		goto release;
+
 	data &= 0xBFFF;
 	ret_val = e1000_retry_write_flash_byte_ich8lan(hw,
 						       act_offset * 2 + 1,
 						       (u8)(data >> 8));
-	if (ret_val) {
-		nvm->ops.release(hw);
-		goto out;
-	}
+	if (ret_val)
+		goto release;
 
 	/*
 	 * And invalidate the previously valid segment by setting
@@ -2038,10 +2030,8 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
 	 */
 	act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1;
 	ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0);
-	if (ret_val) {
-		nvm->ops.release(hw);
-		goto out;
-	}
+	if (ret_val)
+		goto release;
 
 	/* Great!  Everything worked, we can now clear the cached entries. */
 	for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
@@ -2049,14 +2039,17 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
 		dev_spec->shadow_ram[i].value = 0xFFFF;
 	}
 
+release:
 	nvm->ops.release(hw);
 
 	/*
 	 * Reload the EEPROM, or else modifications will not appear
 	 * until after the next adapter reset.
 	 */
-	e1000e_reload_nvm(hw);
-	msleep(10);
+	if (!ret_val) {
+		e1000e_reload_nvm(hw);
+		msleep(10);
+	}
 
 out:
 	if (ret_val)


^ permalink raw reply related

* [net-next-2.6 PATCH 06/12] e1000e: Remove EN_MAC_ADDR_FILTER check from enable_mng_pass_thru check
From: Jeff Kirsher @ 2010-05-11  1:00 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Bruce Allan, Jeff Kirsher
In-Reply-To: <20100511005801.30827.50808.stgit@localhost.localdomain>

From: Bruce Allan <bruce.w.allan@intel.com>

Patch addresses issues when manageability passthrough is enabled, but the
MAC_ADDR_FILTER bit is not set in the MANC register.

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/lib.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
index b0d2a60..b32361d 100644
--- a/drivers/net/e1000e/lib.c
+++ b/drivers/net/e1000e/lib.c
@@ -2515,10 +2515,11 @@ s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length)
 }
 
 /**
- *  e1000e_enable_mng_pass_thru - Enable processing of ARP's
+ *  e1000e_enable_mng_pass_thru - Check if management passthrough is needed
  *  @hw: pointer to the HW structure
  *
- *  Verifies the hardware needs to allow ARPs to be processed by the host.
+ *  Verifies the hardware needs to leave interface enabled so that frames can
+ *  be directed to and from the management interface.
  **/
 bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
 {
@@ -2528,8 +2529,7 @@ bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
 
 	manc = er32(MANC);
 
-	if (!(manc & E1000_MANC_RCV_TCO_EN) ||
-	    !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
+	if (!(manc & E1000_MANC_RCV_TCO_EN))
 		return ret_val;
 
 	if (hw->mac.arc_subsystem_valid) {


^ permalink raw reply related

* [net-next-2.6 PATCH 07/12] e1000e: Cleanup e1000_sw_lcd_config_ich8lan()
From: Jeff Kirsher @ 2010-05-11  1:01 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Bruce Allan, Jeff Kirsher
In-Reply-To: <20100511005801.30827.50808.stgit@localhost.localdomain>

From: Bruce Allan <bruce.w.allan@intel.com>

After every reset all ICH/PCH parts call this function which acquires the
swflag, performs a workaround on applicable parts and releases the swflag.
There is no reason for parts for which this workaround is not applicable
to acquire and release the swflag so the function should just return
without doing anything for these parts.  This also provides for the
indentation of most of the function contents to be shifted left cleaning up
the code.

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/ich8lan.c |  152 +++++++++++++++++++++---------------------
 1 files changed, 75 insertions(+), 77 deletions(-)

diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index 448e123..61f8927 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -815,11 +815,16 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
  **/
 static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
 {
+	struct e1000_adapter *adapter = hw->adapter;
 	struct e1000_phy_info *phy = &hw->phy;
 	u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask;
-	s32 ret_val;
+	s32 ret_val = 0;
 	u16 word_addr, reg_data, reg_addr, phy_page = 0;
 
+	if (!(hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) &&
+		!(hw->mac.type == e1000_pchlan))
+		return ret_val;
+
 	ret_val = hw->phy.ops.acquire(hw);
 	if (ret_val)
 		return ret_val;
@@ -831,97 +836,90 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
 	 * Therefore, after each PHY reset, we will load the
 	 * configuration data out of the NVM manually.
 	 */
-	if ((hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) ||
-		(hw->mac.type == e1000_pchlan)) {
-		struct e1000_adapter *adapter = hw->adapter;
-
-		/* Check if SW needs to configure the PHY */
-		if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) ||
-		    (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M) ||
-		    (hw->mac.type == e1000_pchlan))
-			sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
-		else
-			sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
+	if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) ||
+	    (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M) ||
+	    (hw->mac.type == e1000_pchlan))
+		sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
+	else
+		sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
 
-		data = er32(FEXTNVM);
-		if (!(data & sw_cfg_mask))
-			goto out;
+	data = er32(FEXTNVM);
+	if (!(data & sw_cfg_mask))
+		goto out;
 
-		/* Wait for basic configuration completes before proceeding */
-		e1000_lan_init_done_ich8lan(hw);
+	/* Wait for basic configuration completes before proceeding */
+	e1000_lan_init_done_ich8lan(hw);
 
+	/*
+	 * Make sure HW does not configure LCD from PHY
+	 * extended configuration before SW configuration
+	 */
+	data = er32(EXTCNF_CTRL);
+	if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
+		goto out;
+
+	cnf_size = er32(EXTCNF_SIZE);
+	cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
+	cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;
+	if (!cnf_size)
+		goto out;
+
+	cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
+	cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
+
+	if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
+	    (hw->mac.type == e1000_pchlan)) {
 		/*
-		 * Make sure HW does not configure LCD from PHY
-		 * extended configuration before SW configuration
+		 * HW configures the SMBus address and LEDs when the
+		 * OEM and LCD Write Enable bits are set in the NVM.
+		 * When both NVM bits are cleared, SW will configure
+		 * them instead.
 		 */
-		data = er32(EXTCNF_CTRL);
-		if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
+		data = er32(STRAP);
+		data &= E1000_STRAP_SMBUS_ADDRESS_MASK;
+		reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT;
+		reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
+		ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR,
+							reg_data);
+		if (ret_val)
 			goto out;
 
-		cnf_size = er32(EXTCNF_SIZE);
-		cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
-		cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;
-		if (!cnf_size)
+		data = er32(LEDCTL);
+		ret_val = e1000_write_phy_reg_hv_locked(hw, HV_LED_CONFIG,
+							(u16)data);
+		if (ret_val)
 			goto out;
+	}
 
-		cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
-		cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
-
-		if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
-		    (hw->mac.type == e1000_pchlan)) {
-			/*
-			 * HW configures the SMBus address and LEDs when the
-			 * OEM and LCD Write Enable bits are set in the NVM.
-			 * When both NVM bits are cleared, SW will configure
-			 * them instead.
-			 */
-			data = er32(STRAP);
-			data &= E1000_STRAP_SMBUS_ADDRESS_MASK;
-			reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT;
-			reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
-			ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR,
-			                                        reg_data);
-			if (ret_val)
-				goto out;
-
-			data = er32(LEDCTL);
-			ret_val = e1000_write_phy_reg_hv_locked(hw,
-			                                        HV_LED_CONFIG,
-			                                        (u16)data);
-			if (ret_val)
-				goto out;
-		}
-		/* Configure LCD from extended configuration region. */
+	/* Configure LCD from extended configuration region. */
 
-		/* cnf_base_addr is in DWORD */
-		word_addr = (u16)(cnf_base_addr << 1);
+	/* cnf_base_addr is in DWORD */
+	word_addr = (u16)(cnf_base_addr << 1);
 
-		for (i = 0; i < cnf_size; i++) {
-			ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1,
-			                           &reg_data);
-			if (ret_val)
-				goto out;
+	for (i = 0; i < cnf_size; i++) {
+		ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1,
+					 &reg_data);
+		if (ret_val)
+			goto out;
 
-			ret_val = e1000_read_nvm(hw, (word_addr + i * 2 + 1),
-			                           1, &reg_addr);
-			if (ret_val)
-				goto out;
+		ret_val = e1000_read_nvm(hw, (word_addr + i * 2 + 1),
+					 1, &reg_addr);
+		if (ret_val)
+			goto out;
 
-			/* Save off the PHY page for future writes. */
-			if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {
-				phy_page = reg_data;
-				continue;
-			}
+		/* Save off the PHY page for future writes. */
+		if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {
+			phy_page = reg_data;
+			continue;
+		}
 
-			reg_addr &= PHY_REG_MASK;
-			reg_addr |= phy_page;
+		reg_addr &= PHY_REG_MASK;
+		reg_addr |= phy_page;
 
-			ret_val = phy->ops.write_reg_locked(hw,
-			                                    (u32)reg_addr,
-			                                    reg_data);
-			if (ret_val)
-				goto out;
-		}
+		ret_val = phy->ops.write_reg_locked(hw, (u32)reg_addr,
+						    reg_data);
+		if (ret_val)
+			goto out;
 	}
 
 out:


^ permalink raw reply related

* [net-next-2.6 PATCH 08/12] e1000e: Incorrect function pointer set for force_speed_duplex on 82577
From: Jeff Kirsher @ 2010-05-11  1:01 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Bruce Allan, Jeff Kirsher
In-Reply-To: <20100511005801.30827.50808.stgit@localhost.localdomain>

From: Bruce Allan <bruce.w.allan@intel.com>

The force_speed_duplex function pointer was incorrectly set.  Instead of
calling the 82577-specific version it was calling the m88 version which,
among other incorrect things, reset the PHY causing autonegotiation to be
re-enabled in the PHY resulting in the link defaulting to half-duplex.
The 82577-specific force_speed_duplex function also had an issue where
it disabled Auto-MDI-X which caused the link to not come up.

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/ich8lan.c |    1 +
 drivers/net/e1000e/phy.c     |   21 +--------------------
 2 files changed, 2 insertions(+), 20 deletions(-)

diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index 61f8927..e1f244a 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -330,6 +330,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
 		phy->ops.get_cable_length = e1000_get_cable_length_82577;
 		phy->ops.get_info = e1000_get_phy_info_82577;
 		phy->ops.commit = e1000e_phy_sw_reset;
+		break;
 	case e1000_phy_82578:
 		phy->ops.check_polarity = e1000_check_polarity_m88;
 		phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_m88;
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c
index 7f3ceb9..b4ac82d 100644
--- a/drivers/net/e1000e/phy.c
+++ b/drivers/net/e1000e/phy.c
@@ -3116,9 +3116,7 @@ s32 e1000_check_polarity_82577(struct e1000_hw *hw)
  *  e1000_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY
  *  @hw: pointer to the HW structure
  *
- *  Calls the PHY setup function to force speed and duplex.  Clears the
- *  auto-crossover to force MDI manually.  Waits for link and returns
- *  successful if link up is successful, else -E1000_ERR_PHY (-2).
+ *  Calls the PHY setup function to force speed and duplex.
  **/
 s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
 {
@@ -3137,23 +3135,6 @@ s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
 	if (ret_val)
 		goto out;
 
-	/*
-	 * Clear Auto-Crossover to force MDI manually.  82577 requires MDI
-	 * forced whenever speed and duplex are forced.
-	 */
-	ret_val = phy->ops.read_reg(hw, I82577_PHY_CTRL_2, &phy_data);
-	if (ret_val)
-		goto out;
-
-	phy_data &= ~I82577_PHY_CTRL2_AUTO_MDIX;
-	phy_data &= ~I82577_PHY_CTRL2_FORCE_MDI_MDIX;
-
-	ret_val = phy->ops.write_reg(hw, I82577_PHY_CTRL_2, phy_data);
-	if (ret_val)
-		goto out;
-
-	e_dbg("I82577_PHY_CTRL_2: %X\n", phy_data);
-
 	udelay(1);
 
 	if (phy->autoneg_wait_to_complete) {


^ permalink raw reply related

* [net-next-2.6 PATCH 09/12] e1000e: fix checks for manageability enabled and management pass-through
From: Jeff Kirsher @ 2010-05-11  1:01 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Bruce Allan, Jeff Kirsher
In-Reply-To: <20100511005801.30827.50808.stgit@localhost.localdomain>

From: Bruce Allan <bruce.w.allan@intel.com>

The mac->arc_subsystem was being incorrectly used to flag whether or not
manageability was enabled when it should only be used to state whether the
ARC (Host interface) subsystem is available on a particular MAC _and_ only
valid when any manageability is enabled. The ARC subsystem is currently
only available on 80003es2lan and 82573 parts supported by the driver.

A new flag, has_fwsm, is introduced to be used when checking if
manageability is enabled but only on parts that acutally have an FWSM
register. While the above parts have an FWSM register, there are other
parts that have FWSM but do not have support for the ARC subsystem,
namely 82571/2 and ICHx/PCH.

And then there are parts that have manageability, but do not have either
FWSM register or support for the ARC subsystem - these are 82574 and 82583.

For 80003es2lan, 82571/2/3 and ICH/PCH parts, this patch makes no
functional changes, it only corrects the usage of the manageability flags.
For 82574 and 82583, it fixes the incorrect accesses of the non-existent
FWSM register and ARC subsystem as well as corrects the check for
management pass-through.

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/82571.c   |   19 +++++++++++++++----
 drivers/net/e1000e/defines.h |    2 ++
 drivers/net/e1000e/es2lan.c  |    9 ++++++---
 drivers/net/e1000e/hw.h      |    1 +
 drivers/net/e1000e/ich8lan.c |    6 ++++--
 drivers/net/e1000e/lib.c     |   31 ++++++++++++++++++++++++-------
 6 files changed, 52 insertions(+), 16 deletions(-)

diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index 1e73edd..8bad24d 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -234,9 +234,6 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
 	mac->mta_reg_count = 128;
 	/* Set rar entry count */
 	mac->rar_entry_count = E1000_RAR_ENTRIES;
-	/* Set if manageability features are enabled. */
-	mac->arc_subsystem_valid = (er32(FWSM) & E1000_FWSM_MODE_MASK)
-	                ? true : false;
 	/* Adaptive IFS supported */
 	mac->adaptive_ifs = true;
 
@@ -271,6 +268,16 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
 		func->set_lan_id = e1000_set_lan_id_single_port;
 		func->check_mng_mode = e1000e_check_mng_mode_generic;
 		func->led_on = e1000e_led_on_generic;
+
+		/* FWSM register */
+		mac->has_fwsm = true;
+		/*
+		 * ARC supported; valid only if manageability features are
+		 * enabled.
+		 */
+		mac->arc_subsystem_valid =
+			(er32(FWSM) & E1000_FWSM_MODE_MASK)
+			? true : false;
 		break;
 	case e1000_82574:
 	case e1000_82583:
@@ -281,6 +288,9 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
 	default:
 		func->check_mng_mode = e1000e_check_mng_mode_generic;
 		func->led_on = e1000e_led_on_generic;
+
+		/* FWSM register */
+		mac->has_fwsm = true;
 		break;
 	}
 
@@ -993,9 +1003,10 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
 	/* ...for both queues. */
 	switch (mac->type) {
 	case e1000_82573:
+		e1000e_enable_tx_pkt_filtering(hw);
+		/* fall through */
 	case e1000_82574:
 	case e1000_82583:
-		e1000e_enable_tx_pkt_filtering(hw);
 		reg_data = er32(GCR);
 		reg_data |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
 		ew32(GCR, reg_data);
diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h
index 227147f..4dc02c7 100644
--- a/drivers/net/e1000e/defines.h
+++ b/drivers/net/e1000e/defines.h
@@ -629,6 +629,8 @@
 #define NVM_ALT_MAC_ADDR_PTR       0x0037
 #define NVM_CHECKSUM_REG           0x003F
 
+#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask */
+
 #define E1000_NVM_CFG_DONE_PORT_0  0x40000 /* MNG config cycle done */
 #define E1000_NVM_CFG_DONE_PORT_1  0x80000 /* ...for second port */
 
diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c
index 27d2158..7fcac78 100644
--- a/drivers/net/e1000e/es2lan.c
+++ b/drivers/net/e1000e/es2lan.c
@@ -221,9 +221,12 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter)
 	mac->mta_reg_count = 128;
 	/* Set rar entry count */
 	mac->rar_entry_count = E1000_RAR_ENTRIES;
-	/* Set if manageability features are enabled. */
-	mac->arc_subsystem_valid = (er32(FWSM) & E1000_FWSM_MODE_MASK)
-                        ? true : false;
+	/* FWSM register */
+	mac->has_fwsm = true;
+	/* ARC supported; valid only if manageability features are enabled. */
+	mac->arc_subsystem_valid =
+	        (er32(FWSM) & E1000_FWSM_MODE_MASK)
+	                ? true : false;
 	/* Adaptive IFS not supported */
 	mac->adaptive_ifs = false;
 
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index 6f66c37..287ee95 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -830,6 +830,7 @@ struct e1000_mac_info {
 	u8  forced_speed_duplex;
 
 	bool adaptive_ifs;
+	bool has_fwsm;
 	bool arc_subsystem_valid;
 	bool autoneg;
 	bool autoneg_failed;
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index e1f244a..8efe9a7 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -503,8 +503,10 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
 	mac->rar_entry_count = E1000_ICH_RAR_ENTRIES;
 	if (mac->type == e1000_ich8lan)
 		mac->rar_entry_count--;
-	/* Set if manageability features are enabled. */
-	mac->arc_subsystem_valid = true;
+	/* FWSM register */
+	mac->has_fwsm = true;
+	/* ARC subsystem not supported */
+	mac->arc_subsystem_valid = false;
 	/* Adaptive IFS supported */
 	mac->adaptive_ifs = true;
 
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
index b32361d..a968e3a 100644
--- a/drivers/net/e1000e/lib.c
+++ b/drivers/net/e1000e/lib.c
@@ -2272,6 +2272,11 @@ static s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
 	u32 hicr;
 	u8 i;
 
+	if (!(hw->mac.arc_subsystem_valid)) {
+		e_dbg("ARC subsystem not valid.\n");
+		return -E1000_ERR_HOST_INTERFACE_COMMAND;
+	}
+
 	/* Check that the host interface is enabled. */
 	hicr = er32(HICR);
 	if ((hicr & E1000_HICR_EN) == 0) {
@@ -2530,9 +2535,9 @@ bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
 	manc = er32(MANC);
 
 	if (!(manc & E1000_MANC_RCV_TCO_EN))
-		return ret_val;
+		goto out;
 
-	if (hw->mac.arc_subsystem_valid) {
+	if (hw->mac.has_fwsm) {
 		fwsm = er32(FWSM);
 		factps = er32(FACTPS);
 
@@ -2540,16 +2545,28 @@ bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
 		    ((fwsm & E1000_FWSM_MODE_MASK) ==
 		     (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
 			ret_val = true;
-			return ret_val;
+			goto out;
 		}
-	} else {
-		if ((manc & E1000_MANC_SMBUS_EN) &&
-		    !(manc & E1000_MANC_ASF_EN)) {
+	} else if ((hw->mac.type == e1000_82574) ||
+		   (hw->mac.type == e1000_82583)) {
+		u16 data;
+
+		factps = er32(FACTPS);
+		e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
+
+		if (!(factps & E1000_FACTPS_MNGCG) &&
+		    ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
+		     (e1000_mng_mode_pt << 13))) {
 			ret_val = true;
-			return ret_val;
+			goto out;
 		}
+	} else if ((manc & E1000_MANC_SMBUS_EN) &&
+		    !(manc & E1000_MANC_ASF_EN)) {
+			ret_val = true;
+			goto out;
 	}
 
+out:
 	return ret_val;
 }
 


^ permalink raw reply related

* [net-next-2.6 PATCH 10/12] e1000e: move settting of flow control refresh timer to link setup code
From: Jeff Kirsher @ 2010-05-11  1:02 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Bruce Allan, Jeff Kirsher
In-Reply-To: <20100511005801.30827.50808.stgit@localhost.localdomain>

From: Bruce Allan <bruce.w.allan@intel.com>

The flow control refresh timer value needs to be saved off so that it can
be programmed into the approrpiate register when applicable but without a
reset, e.g. when changing flow control parameters via ethtool.

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/hw.h      |    1 +
 drivers/net/e1000e/ich8lan.c |    2 ++
 drivers/net/e1000e/netdev.c  |    5 +----
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index 287ee95..fa314b4 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -901,6 +901,7 @@ struct e1000_fc_info {
 	u32 high_water;          /* Flow control high-water mark */
 	u32 low_water;           /* Flow control low-water mark */
 	u16 pause_time;          /* Flow control pause timer */
+	u16 refresh_time;        /* Flow control refresh timer */
 	bool send_xon;           /* Flow control send XON */
 	bool strict_ieee;        /* Strict IEEE mode */
 	enum e1000_fc_mode current_mode; /* FC mode in effect */
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index 8efe9a7..2b2cffc 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -2823,6 +2823,8 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
 	ew32(FCTTV, hw->fc.pause_time);
 	if ((hw->phy.type == e1000_phy_82578) ||
 	    (hw->phy.type == e1000_phy_82577)) {
+		ew32(FCRTV_PCH, hw->fc.refresh_time);
+
 		ret_val = hw->phy.ops.write_reg(hw,
 		                             PHY_REG(BM_PORT_CTRL_PAGE, 27),
 		                             hw->fc.pause_time);
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 16a03c5..d1f60c5 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -3134,6 +3134,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
 			fc->high_water = 0x5000;
 			fc->low_water  = 0x3000;
 		}
+		fc->refresh_time = 0x1000;
 	} else {
 		if ((adapter->flags & FLAG_HAS_ERT) &&
 		    (adapter->netdev->mtu > ETH_DATA_LEN))
@@ -3171,10 +3172,6 @@ void e1000e_reset(struct e1000_adapter *adapter)
 	if (mac->ops.init_hw(hw))
 		e_err("Hardware Error\n");
 
-	/* additional part of the flow-control workaround above */
-	if (hw->mac.type == e1000_pchlan)
-		ew32(FCRTV_PCH, 0x1000);
-
 	e1000_update_mng_vlan(adapter);
 
 	/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */


^ permalink raw reply related

* [net-next-2.6 PATCH 11/12] e1000e: Fix/cleanup PHY reset code for ICHx/PCHx
From: Jeff Kirsher @ 2010-05-11  1:02 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Bruce Allan, Jeff Kirsher
In-Reply-To: <20100511005801.30827.50808.stgit@localhost.localdomain>

From: Bruce Allan <bruce.w.allan@intel.com>

i) Fixes a bug where e1000_sw_lcd_config_ich8lan() was calling
e1000_lan_init_done_ich8lan() to poll the STATUS.LAN_INIT_DONE bit to
make sure the MAC had completed the PHY configuration.  However,
e1000_lan_init_done_ich8lan() had already been called in one of the two
places where PHY reset occurs for ICHx/PCHx parts, which caused the second
call to busy-wait for 150 msec because the LAN_INIT_DONE bit had already
been checked and cleared.

ii) Cleanup the two separate PHY reset code paths, i.e. the full-chip reset
in e1000_reset_hw_ich8lan() and the PHY-only reset in
e1000_phy_hw_reset_ich8lan().  There was duplicate code in both paths to be
performed post-reset that are now combined into one new function -
e1000_post_phy_reset_ich8lan().  This cleanup also included moving the
clearing of the PHY Reset Asserted bit in the STATUS register (now done for
all ICH/PCH parts) and the check for the indication from h/w that basic
configuration has completed back to where it previously was in
e1000_get_cfg_done_ich8lan().

iii) Corrected a few comments

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/ich8lan.c |  149 +++++++++++++++++++++---------------------
 1 files changed, 75 insertions(+), 74 deletions(-)

diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index 2b2cffc..10360fb 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -850,9 +850,6 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
 	if (!(data & sw_cfg_mask))
 		goto out;
 
-	/* Wait for basic configuration completes before proceeding */
-	e1000_lan_init_done_ich8lan(hw);
-
 	/*
 	 * Make sure HW does not configure LCD from PHY
 	 * extended configuration before SW configuration
@@ -1260,30 +1257,26 @@ static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw)
 }
 
 /**
- *  e1000_phy_hw_reset_ich8lan - Performs a PHY reset
+ *  e1000_post_phy_reset_ich8lan - Perform steps required after a PHY reset
  *  @hw: pointer to the HW structure
- *
- *  Resets the PHY
- *  This is a function pointer entry point called by drivers
- *  or other shared routines.
  **/
-static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
+static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
 {
 	s32 ret_val = 0;
 	u16 reg;
 
-	ret_val = e1000e_phy_hw_reset_generic(hw);
-	if (ret_val)
-		return ret_val;
-
-	/* Allow time for h/w to get to a quiescent state after reset */
-	mdelay(10);
+	if (e1000_check_reset_block(hw))
+		goto out;
 
 	/* Perform any necessary post-reset workarounds */
-	if (hw->mac.type == e1000_pchlan) {
+	switch (hw->mac.type) {
+	case e1000_pchlan:
 		ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
 		if (ret_val)
-			return ret_val;
+			goto out;
+		break;
+	default:
+		break;
 	}
 
 	/* Dummy read to clear the phy wakeup bit after lcd reset */
@@ -1296,11 +1289,32 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
 		goto out;
 
 	/* Configure the LCD with the OEM bits in NVM */
-	if (hw->mac.type == e1000_pchlan)
-		ret_val = e1000_oem_bits_config_ich8lan(hw, true);
+	ret_val = e1000_oem_bits_config_ich8lan(hw, true);
 
 out:
-	return 0;
+	return ret_val;
+}
+
+/**
+ *  e1000_phy_hw_reset_ich8lan - Performs a PHY reset
+ *  @hw: pointer to the HW structure
+ *
+ *  Resets the PHY
+ *  This is a function pointer entry point called by drivers
+ *  or other shared routines.
+ **/
+static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
+{
+	s32 ret_val = 0;
+
+	ret_val = e1000e_phy_hw_reset_generic(hw);
+	if (ret_val)
+		goto out;
+
+	ret_val = e1000_post_phy_reset_ich8lan(hw);
+
+out:
+	return ret_val;
 }
 
 /**
@@ -2511,9 +2525,8 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
 	 * on the last TLP read/write transaction when MAC is reset.
 	 */
 	ret_val = e1000e_disable_pcie_master(hw);
-	if (ret_val) {
+	if (ret_val)
 		e_dbg("PCI-E Master disable polling has failed.\n");
-	}
 
 	e_dbg("Masking off all interrupts\n");
 	ew32(IMC, 0xffffffff);
@@ -2552,14 +2565,8 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
 	ctrl = er32(CTRL);
 
 	if (!e1000_check_reset_block(hw)) {
-		/* Clear PHY Reset Asserted bit */
-		if (hw->mac.type >= e1000_pchlan) {
-			u32 status = er32(STATUS);
-			ew32(STATUS, status & ~E1000_STATUS_PHYRA);
-		}
-
 		/*
-		 * PHY HW reset requires MAC CORE reset at the same
+		 * Full-chip reset requires MAC and PHY reset at the same
 		 * time to make sure the interface between MAC and the
 		 * external PHY is reset.
 		 */
@@ -2573,39 +2580,16 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
 	if (!ret_val)
 		e1000_release_swflag_ich8lan(hw);
 
-	/* Perform any necessary post-reset workarounds */
-	if (hw->mac.type == e1000_pchlan)
-		ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
-
-	if (ctrl & E1000_CTRL_PHY_RST)
+	if (ctrl & E1000_CTRL_PHY_RST) {
 		ret_val = hw->phy.ops.get_cfg_done(hw);
+		if (ret_val)
+			goto out;
 
-	if (hw->mac.type >= e1000_ich10lan) {
-		e1000_lan_init_done_ich8lan(hw);
-	} else {
-		ret_val = e1000e_get_auto_rd_done(hw);
-		if (ret_val) {
-			/*
-			 * When auto config read does not complete, do not
-			 * return with an error. This can happen in situations
-			 * where there is no eeprom and prevents getting link.
-			 */
-			e_dbg("Auto Read Done did not complete\n");
-		}
-	}
-	/* Dummy read to clear the phy wakeup bit after lcd reset */
-	if (hw->mac.type == e1000_pchlan)
-		e1e_rphy(hw, BM_WUC, &reg);
-
-	ret_val = e1000_sw_lcd_config_ich8lan(hw);
-	if (ret_val)
-		goto out;
-
-	if (hw->mac.type == e1000_pchlan) {
-		ret_val = e1000_oem_bits_config_ich8lan(hw, true);
+		ret_val = e1000_post_phy_reset_ich8lan(hw);
 		if (ret_val)
 			goto out;
 	}
+
 	/*
 	 * For PCH, this write will make sure that any noise
 	 * will be detected as a CRC error and be dropped rather than show up
@@ -3291,33 +3275,50 @@ static s32 e1000_led_off_pchlan(struct e1000_hw *hw)
 }
 
 /**
- *  e1000_get_cfg_done_ich8lan - Read config done bit
+ *  e1000_get_cfg_done_ich8lan - Read config done bit after Full or PHY reset
  *  @hw: pointer to the HW structure
  *
- *  Read the management control register for the config done bit for
- *  completion status.  NOTE: silicon which is EEPROM-less will fail trying
- *  to read the config done bit, so an error is *ONLY* logged and returns
- *  0.  If we were to return with error, EEPROM-less silicon
- *  would not be able to be reset or change link.
+ *  Read appropriate register for the config done bit for completion status
+ *  and configure the PHY through s/w for EEPROM-less parts.
+ *
+ *  NOTE: some silicon which is EEPROM-less will fail trying to read the
+ *  config done bit, so only an error is logged and continues.  If we were
+ *  to return with error, EEPROM-less silicon would not be able to be reset
+ *  or change link.
  **/
 static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
 {
+	s32 ret_val = 0;
 	u32 bank = 0;
+	u32 status;
 
-	if (hw->mac.type >= e1000_pchlan) {
-		u32 status = er32(STATUS);
+	e1000e_get_cfg_done(hw);
 
-		if (status & E1000_STATUS_PHYRA)
-			ew32(STATUS, status & ~E1000_STATUS_PHYRA);
-		else
-			e_dbg("PHY Reset Asserted not set - needs delay\n");
+	/* Wait for indication from h/w that it has completed basic config */
+	if (hw->mac.type >= e1000_ich10lan) {
+		e1000_lan_init_done_ich8lan(hw);
+	} else {
+		ret_val = e1000e_get_auto_rd_done(hw);
+		if (ret_val) {
+			/*
+			 * When auto config read does not complete, do not
+			 * return with an error. This can happen in situations
+			 * where there is no eeprom and prevents getting link.
+			 */
+			e_dbg("Auto Read Done did not complete\n");
+			ret_val = 0;
+		}
 	}
 
-	e1000e_get_cfg_done(hw);
+	/* Clear PHY Reset Asserted bit */
+	status = er32(STATUS);
+	if (status & E1000_STATUS_PHYRA)
+		ew32(STATUS, status & ~E1000_STATUS_PHYRA);
+	else
+		e_dbg("PHY Reset Asserted not set - needs delay\n");
 
 	/* If EEPROM is not marked present, init the IGP 3 PHY manually */
-	if ((hw->mac.type != e1000_ich10lan) &&
-	    (hw->mac.type != e1000_pchlan)) {
+	if (hw->mac.type <= e1000_ich9lan) {
 		if (((er32(EECD) & E1000_EECD_PRES) == 0) &&
 		    (hw->phy.type == e1000_phy_igp_3)) {
 			e1000e_phy_init_script_igp3(hw);
@@ -3326,11 +3327,11 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
 		if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) {
 			/* Maybe we should do a basic PHY config */
 			e_dbg("EEPROM not present\n");
-			return -E1000_ERR_CONFIG;
+			ret_val = -E1000_ERR_CONFIG;
 		}
 	}
 
-	return 0;
+	return ret_val;
 }
 
 /**


^ permalink raw reply related

* [net-next-2.6 PATCH 12/12] e1000e: add PCI device id to enable support for 82567V-4
From: Jeff Kirsher @ 2010-05-11  1:02 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Bruce Allan, Jeff Kirsher
In-Reply-To: <20100511005801.30827.50808.stgit@localhost.localdomain>

From: Bruce Allan <bruce.w.allan@intel.com>

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000e/hw.h     |    1 +
 drivers/net/e1000e/netdev.c |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index fa314b4..5d1220d 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -382,6 +382,7 @@ enum e1e_registers {
 #define E1000_DEV_ID_ICH10_R_BM_V		0x10CE
 #define E1000_DEV_ID_ICH10_D_BM_LM		0x10DE
 #define E1000_DEV_ID_ICH10_D_BM_LF		0x10DF
+#define E1000_DEV_ID_ICH10_D_BM_V		0x1525
 #define E1000_DEV_ID_PCH_M_HV_LM		0x10EA
 #define E1000_DEV_ID_PCH_M_HV_LC		0x10EB
 #define E1000_DEV_ID_PCH_D_HV_DM		0x10EF
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index d1f60c5..1ad29d9 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -5894,6 +5894,7 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
 
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LM), board_ich10lan },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LF), board_ich10lan },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_V), board_ich10lan },
 
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LM), board_pchlan },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LC), board_pchlan },


^ permalink raw reply related

* drivers/net/ RFC: Remove return; before void function end-of-functions close brace
From: Joe Perches @ 2010-05-11  1:14 UTC (permalink / raw)
  To: netdev

Many functions are declared void but use a return at end-of-function.

void function(void args...)
{
	[perform some calcs]
	...

	return;
}

Removing the unnecessary return; statements would save ~675 lines.
 
$ grep -rP --include=*.[ch] -l "return;\n}" drivers/net | \
  xargs perl -i -e 'local $/ ; while (<>) { s/\n[ \t\n]+return;\n}/\n}/g; print; }
$ git diff --shortstat drivers/net
 186 files changed, 0 insertions(+), 675 deletions(-)

Anyone think such patches acceptable/useful?


^ permalink raw reply

* Re: [PATCH 2/4 v2] ks8851: Low level functions for read/write to companion eeprom
From: Ben Dooks @ 2010-05-11  1:16 UTC (permalink / raw)
  To: Sebastien Jan; +Cc: netdev, linux-omap, Abraham Arce, Ben Dooks, Tristram.Ha
In-Reply-To: <1273085155-1260-3-git-send-email-s-jan@ti.com>

On Wed, May 05, 2010 at 08:45:53PM +0200, Sebastien Jan wrote:
> Low-level functions provide 16bits words read and write capability
> to ks8851 companion eeprom.

Please use the eeprom interface that was added already
 
> Signed-off-by: Sebastien Jan <s-jan@ti.com>
> ---
>  drivers/net/ks8851.c |  228 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/ks8851.h |   14 +++-
>  2 files changed, 241 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c
> index a84e500..787f9df 100644
> --- a/drivers/net/ks8851.c
> +++ b/drivers/net/ks8851.c
> @@ -1044,6 +1044,234 @@ static const struct net_device_ops ks8851_netdev_ops = {
>  	.ndo_validate_addr	= eth_validate_addr,
>  };
>  
> +/* Companion eeprom access */
> +
> +enum {	/* EEPROM programming states */
> +	EEPROM_CONTROL,
> +	EEPROM_ADDRESS,
> +	EEPROM_DATA,
> +	EEPROM_COMPLETE
> +};
> +
> +/**
> + * ks8851_eeprom_read - read a 16bits word in ks8851 companion EEPROM
> + * @dev: The network device the PHY is on.
> + * @addr: EEPROM address to read
> + *
> + * eeprom_size: used to define the data coding length. Can be changed
> + * through debug-fs.
> + *
> + * Programs a read on the EEPROM using ks8851 EEPROM SW access feature.
> + * Warning: The READ feature is not supported on ks8851 revision 0.
> + *
> + * Rough programming model:
> + *  - on period start: set clock high and read value on bus
> + *  - on period / 2: set clock low and program value on bus
> + *  - start on period / 2
> + */
> +unsigned int ks8851_eeprom_read(struct net_device *dev, unsigned int addr)
> +{
> +	struct ks8851_net *ks = netdev_priv(dev);
> +	int eepcr;
> +	int ctrl = EEPROM_OP_READ;
> +	int state = EEPROM_CONTROL;
> +	int bit_count = EEPROM_OP_LEN - 1;
> +	unsigned int data = 0;
> +	int dummy;
> +	unsigned int addr_len;
> +
> +	addr_len = (ks->eeprom_size == 128) ? 6 : 8;
> +
> +	/* start transaction: chip select high, authorize write */
> +	mutex_lock(&ks->lock);
> +	eepcr = EEPCR_EESA | EEPCR_EESRWA;
> +	ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> +	eepcr |= EEPCR_EECS;
> +	ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> +	mutex_unlock(&ks->lock);
> +
> +	while (state != EEPROM_COMPLETE) {
> +		/* falling clock period starts... */
> +		/* set EED_IO pin for control and address */
> +		eepcr &= ~EEPCR_EEDO;
> +		switch (state) {
> +		case EEPROM_CONTROL:
> +			eepcr |= ((ctrl >> bit_count) & 1) << 2;
> +			if (bit_count-- <= 0) {
> +				bit_count = addr_len - 1;
> +				state = EEPROM_ADDRESS;
> +			}
> +			break;
> +		case EEPROM_ADDRESS:
> +			eepcr |= ((addr >> bit_count) & 1) << 2;
> +			bit_count--;
> +			break;
> +		case EEPROM_DATA:
> +			/* Change to receive mode */
> +			eepcr &= ~EEPCR_EESRWA;
> +			break;
> +		}
> +
> +		/* lower clock  */
> +		eepcr &= ~EEPCR_EESCK;
> +
> +		mutex_lock(&ks->lock);
> +		ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> +		mutex_unlock(&ks->lock);
> +
> +		/* waitread period / 2 */
> +		udelay(EEPROM_SK_PERIOD / 2);
> +
> +		/* rising clock period starts... */
> +
> +		/* raise clock */
> +		mutex_lock(&ks->lock);
> +		eepcr |= EEPCR_EESCK;
> +		ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> +		mutex_unlock(&ks->lock);
> +
> +		/* Manage read */
> +		switch (state) {
> +		case EEPROM_ADDRESS:
> +			if (bit_count < 0) {
> +				bit_count = EEPROM_DATA_LEN - 1;
> +				state = EEPROM_DATA;
> +			}
> +			break;
> +		case EEPROM_DATA:
> +			mutex_lock(&ks->lock);
> +			dummy = ks8851_rdreg16(ks, KS_EEPCR);
> +			mutex_unlock(&ks->lock);
> +			data |= ((dummy >> EEPCR_EESB_OFFSET) & 1) << bit_count;
> +			if (bit_count-- <= 0)
> +				state = EEPROM_COMPLETE;
> +			break;
> +		}
> +
> +		/* wait period / 2 */
> +		udelay(EEPROM_SK_PERIOD / 2);
> +	}
> +
> +	/* close transaction */
> +	mutex_lock(&ks->lock);
> +	eepcr &= ~EEPCR_EECS;
> +	ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> +	eepcr = 0;
> +	ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> +	mutex_unlock(&ks->lock);
> +
> +	return data;
> +}
> +
> +/**
> + * ks8851_eeprom_write - write a 16bits word in ks8851 companion EEPROM
> + * @dev: The network device the PHY is on.
> + * @op: operand (can be WRITE, EWEN, EWDS)
> + * @addr: EEPROM address to write
> + * @data: data to write
> + *
> + * eeprom_size: used to define the data coding length. Can be changed
> + * through debug-fs.
> + *
> + * Programs a write on the EEPROM using ks8851 EEPROM SW access feature.
> + *
> + * Note that a write enable is required before writing data.
> + *
> + * Rough programming model:
> + *  - on period start: set clock high
> + *  - on period / 2: set clock low and program value on bus
> + *  - start on period / 2
> + */
> +void ks8851_eeprom_write(struct net_device *dev, unsigned int op,
> +					unsigned int addr, unsigned int data)
> +{
> +	struct ks8851_net *ks = netdev_priv(dev);
> +	int eepcr;
> +	int state = EEPROM_CONTROL;
> +	int bit_count = EEPROM_OP_LEN - 1;
> +	unsigned int addr_len;
> +
> +	addr_len = (ks->eeprom_size == 128) ? 6 : 8;
> +
> +	switch (op) {
> +	case EEPROM_OP_EWEN:
> +		addr = 0x30;
> +	break;
> +	case EEPROM_OP_EWDS:
> +		addr = 0;
> +		break;
> +	}
> +
> +	/* start transaction: chip select high, authorize write */
> +	mutex_lock(&ks->lock);
> +	eepcr = EEPCR_EESA | EEPCR_EESRWA;
> +	ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> +	eepcr |= EEPCR_EECS;
> +	ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> +	mutex_unlock(&ks->lock);
> +
> +	while (state != EEPROM_COMPLETE) {
> +		/* falling clock period starts... */
> +		/* set EED_IO pin for control and address */
> +		eepcr &= ~EEPCR_EEDO;
> +		switch (state) {
> +		case EEPROM_CONTROL:
> +			eepcr |= ((op >> bit_count) & 1) << 2;
> +			if (bit_count-- <= 0) {
> +				bit_count = addr_len - 1;
> +				state = EEPROM_ADDRESS;
> +			}
> +			break;
> +		case EEPROM_ADDRESS:
> +			eepcr |= ((addr >> bit_count) & 1) << 2;
> +			if (bit_count-- <= 0) {
> +				if (op == EEPROM_OP_WRITE) {
> +					bit_count = EEPROM_DATA_LEN - 1;
> +					state = EEPROM_DATA;
> +				} else {
> +					state = EEPROM_COMPLETE;
> +				}
> +			}
> +			break;
> +		case EEPROM_DATA:
> +			eepcr |= ((data >> bit_count) & 1) << 2;
> +			if (bit_count-- <= 0)
> +				state = EEPROM_COMPLETE;
> +			break;
> +		}
> +
> +		/* lower clock  */
> +		eepcr &= ~EEPCR_EESCK;
> +
> +		mutex_lock(&ks->lock);
> +		ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> +		mutex_unlock(&ks->lock);
> +
> +		/* wait period / 2 */
> +		udelay(EEPROM_SK_PERIOD / 2);
> +
> +		/* rising clock period starts... */
> +
> +		/* raise clock */
> +		eepcr |= EEPCR_EESCK;
> +		mutex_lock(&ks->lock);
> +		ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> +		mutex_unlock(&ks->lock);
> +
> +		/* wait period / 2 */
> +		udelay(EEPROM_SK_PERIOD / 2);
> +	}
> +
> +	/* close transaction */
> +	mutex_lock(&ks->lock);
> +	eepcr &= ~EEPCR_EECS;
> +	ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> +	eepcr = 0;
> +	ks8851_wrreg16(ks, KS_EEPCR, eepcr);
> +	mutex_unlock(&ks->lock);
> +
> +}
> +
>  /* ethtool support */
>  
>  static void ks8851_get_drvinfo(struct net_device *dev,
> diff --git a/drivers/net/ks8851.h b/drivers/net/ks8851.h
> index f52c312..537fb06 100644
> --- a/drivers/net/ks8851.h
> +++ b/drivers/net/ks8851.h
> @@ -25,12 +25,24 @@
>  #define OBCR_ODS_16mA				(1 << 6)
>  
>  #define KS_EEPCR				0x22
> +#define EEPCR_EESRWA				(1 << 5)
>  #define EEPCR_EESA				(1 << 4)
> -#define EEPCR_EESB				(1 << 3)
> +#define EEPCR_EESB_OFFSET			3
> +#define EEPCR_EESB				(1 << EEPCR_EESB_OFFSET)
>  #define EEPCR_EEDO				(1 << 2)
>  #define EEPCR_EESCK				(1 << 1)
>  #define EEPCR_EECS				(1 << 0)
>  
> +#define EEPROM_OP_LEN				3	/* bits:*/
> +#define EEPROM_OP_READ				0x06
> +#define EEPROM_OP_EWEN				0x04
> +#define EEPROM_OP_WRITE				0x05
> +#define EEPROM_OP_EWDS				0x14
> +
> +#define EEPROM_DATA_LEN				16	/* 16 bits EEPROM */
> +#define EEPROM_WRITE_TIME			4	/* wrt ack time in ms */
> +#define EEPROM_SK_PERIOD			400	/* in us */
> +
>  #define KS_MBIR					0x24
>  #define MBIR_TXMBF				(1 << 12)
>  #define MBIR_TXMBFA				(1 << 11)
> -- 
> 1.6.3.3
> 

-- 
-- 
Ben

Q:      What's a light-year?
A:      One-third less calories than a regular year.


^ permalink raw reply

* Re: [PATCH 2/4 v2] ks8851: Low level functions for read/write to companion eeprom
From: Ben Dooks @ 2010-05-11  1:23 UTC (permalink / raw)
  To: David Miller; +Cc: s-jan, netdev, linux-omap, x0066660, ben-linux, Tristram.Ha
In-Reply-To: <20100506.002012.27799102.davem@davemloft.net>

On Thu, May 06, 2010 at 12:20:12AM -0700, David Miller wrote:
> From: Sebastien Jan <s-jan@ti.com>
> Date: Wed,  5 May 2010 20:45:53 +0200
> 
> > Low-level functions provide 16bits words read and write capability
> > to ks8851 companion eeprom.
> > 
> > Signed-off-by: Sebastien Jan <s-jan@ti.com>
> 
> Applied.

So I take it the patches that used the drivers/misc/eeprom/eeprom_93cx6.c
are not going to be merged?

-- 
Ben

Q:      What's a light-year?
A:      One-third less calories than a regular year.


^ permalink raw reply

* RE: e1000e fails probe
From: Allan, Bruce W @ 2010-05-11  1:33 UTC (permalink / raw)
  To: Pete Zaitcev, netdev@vger.kernel.org
In-Reply-To: <20100510185018.3478bcae@redhat.com>

On Monday, May 10, 2010 5:50 PM, Pete Zaitcev wrote:
> Dear All:
> 
> I have a box where e1000e would refuse to probe the onboard interface
> with the following in dmesg:
> 
> e1000e: Intel(R) PRO/1000 Network Driver - 1.0.2-k2
> e1000e: Copyright (c) 1999 - 2009 Intel Corporation.
> e1000e 0000:00:19.0: PCI INT A -> GSI 20 (level, low) -> IRQ 20
> e1000e 0000:00:19.0: setting latency timer to 64
> e1000e 0000:00:19.0: irq 34 for MSI/MSI-X
> 0000:00:19.0: 0000:00:19.0: MDI Error
> e1000e 0000:00:19.0: PCI INT A disabled
> e1000e: probe of 0000:00:19.0 failed with error -2
> 
> The "MDI Error" seems to indicate a hardware failure, so I paid it no
> mind until I noticed that RHEL 5 works. So, I diffed the drivers
> between Linus' 2.6.34-rc5 and RHEL's 2.6.18-180.el5, with the
> following 
> minimal patch working for me:

Hi Pete,

Sorry you are having problems with e1000e.  You didn't mention which LOM device was on this system - is the PCI device id 0x10ea, 0x10eb, 0x10ef or 0x10f0?

What BIOS version is on the system?

Would you be able to try a patch that is already in DaveM's net-next-2.6 tree?  If so, it is http://git.kernel.org/?p=linux/kernel/git/davem/net-next-2.6.git;a=commitdiff;h=627c8a041f7aaaea93c766f69bd61d952a277586

Thanks,
Bruce.

^ permalink raw reply

* [PATCH net-next 2/3] cxgb4: report the PCIe link speed
From: Dimitris Michailidis @ 2010-05-11  1:58 UTC (permalink / raw)
  To: netdev; +Cc: Dimitris Michailidis
In-Reply-To: <1273543089-10938-1-git-send-email-dm@chelsio.com>

Report the PCIe link speed (2.5 or 5 Gbps).

Signed-off-by: Dimitris Michailidis <dm@chelsio.com>
---
 drivers/net/cxgb4/cxgb4_main.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
index a73cda9..80c3fc5 100644
--- a/drivers/net/cxgb4/cxgb4_main.c
+++ b/drivers/net/cxgb4/cxgb4_main.c
@@ -3080,6 +3080,12 @@ static void __devinit print_port_info(struct adapter *adap)
 
 	int i;
 	char buf[80];
+	const char *spd = "";
+
+	if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_2_5GB)
+		spd = " 2.5 GT/s";
+	else if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_5_0GB)
+		spd = " 5 GT/s";
 
 	for_each_port(adap, i) {
 		struct net_device *dev = adap->port[i];
@@ -3099,10 +3105,10 @@ static void __devinit print_port_info(struct adapter *adap)
 			--bufp;
 		sprintf(bufp, "BASE-%s", base[pi->port_type]);
 
-		netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s\n",
+		netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s%s\n",
 			    adap->params.vpd.id, adap->params.rev,
 			    buf, is_offload(adap) ? "R" : "",
-			    adap->params.pci.width,
+			    adap->params.pci.width, spd,
 			    (adap->flags & USING_MSIX) ? " MSI-X" :
 			    (adap->flags & USING_MSI) ? " MSI" : "");
 		if (adap->name == dev->name)
-- 
1.5.4


^ permalink raw reply related

* [PATCH net-next 3/3] cxgb4: report GRO stats with ethtool -S
From: Dimitris Michailidis @ 2010-05-11  1:58 UTC (permalink / raw)
  To: netdev; +Cc: Dimitris Michailidis
In-Reply-To: <1273543089-10938-2-git-send-email-dm@chelsio.com>

Signed-off-by: Dimitris Michailidis <dm@chelsio.com>
---
 drivers/net/cxgb4/cxgb4_main.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
index 80c3fc5..90d375b 100644
--- a/drivers/net/cxgb4/cxgb4_main.c
+++ b/drivers/net/cxgb4/cxgb4_main.c
@@ -859,6 +859,8 @@ static char stats_strings[][ETH_GSTRING_LEN] = {
 	"RxCsumGood         ",
 	"VLANextractions    ",
 	"VLANinsertions     ",
+	"GROpackets         ",
+	"GROmerged          ",
 };
 
 static int get_sset_count(struct net_device *dev, int sset)
@@ -922,6 +924,8 @@ struct queue_port_stats {
 	u64 rx_csum;
 	u64 vlan_ex;
 	u64 vlan_ins;
+	u64 gro_pkts;
+	u64 gro_merged;
 };
 
 static void collect_sge_port_stats(const struct adapter *adap,
@@ -938,6 +942,8 @@ static void collect_sge_port_stats(const struct adapter *adap,
 		s->rx_csum += rx->stats.rx_cso;
 		s->vlan_ex += rx->stats.vlan_ex;
 		s->vlan_ins += tx->vlan_ins;
+		s->gro_pkts += rx->stats.lro_pkts;
+		s->gro_merged += rx->stats.lro_merged;
 	}
 }
 
-- 
1.5.4


^ permalink raw reply related

* [PATCH net-next 1/3] cxgb4: configure HW VLAN extraction through FW
From: Dimitris Michailidis @ 2010-05-11  1:58 UTC (permalink / raw)
  To: netdev; +Cc: Dimitris Michailidis

HW VLAN extraction needs to be configured through FW to work correctly in
virtualization environments.  Remove the direct register manipulation and
rely on FW.

Signed-off-by: Dimitris Michailidis <dm@chelsio.com>
---
 drivers/net/cxgb4/cxgb4.h      |    4 ++--
 drivers/net/cxgb4/cxgb4_main.c |    9 +++++----
 drivers/net/cxgb4/t4_hw.c      |   31 ++++++++++---------------------
 drivers/net/cxgb4/t4fw_api.h   |    4 +++-
 4 files changed, 20 insertions(+), 28 deletions(-)

diff --git a/drivers/net/cxgb4/cxgb4.h b/drivers/net/cxgb4/cxgb4.h
index 8856a75..d3a5c34 100644
--- a/drivers/net/cxgb4/cxgb4.h
+++ b/drivers/net/cxgb4/cxgb4.h
@@ -656,7 +656,6 @@ int t4_check_fw_version(struct adapter *adapter);
 int t4_prep_adapter(struct adapter *adapter);
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
 void t4_fatal_err(struct adapter *adapter);
-void t4_set_vlan_accel(struct adapter *adapter, unsigned int ports, int on);
 int t4_set_trace_filter(struct adapter *adapter, const struct trace_params *tp,
 			int filter_index, int enable);
 void t4_get_trace_filter(struct adapter *adapter, struct trace_params *tp,
@@ -707,7 +706,8 @@ int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port,
 int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf,
 	       unsigned int vf, unsigned int viid);
 int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid,
-		int mtu, int promisc, int all_multi, int bcast, bool sleep_ok);
+		int mtu, int promisc, int all_multi, int bcast, int vlanex,
+		bool sleep_ok);
 int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
 		      unsigned int viid, bool free, unsigned int naddr,
 		      const u8 **addr, u16 *idx, u64 *hash, bool sleep_ok);
diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
index 1bad500..a73cda9 100644
--- a/drivers/net/cxgb4/cxgb4_main.c
+++ b/drivers/net/cxgb4/cxgb4_main.c
@@ -290,7 +290,7 @@ static int set_rxmode(struct net_device *dev, int mtu, bool sleep_ok)
 	if (ret == 0)
 		ret = t4_set_rxmode(pi->adapter, 0, pi->viid, mtu,
 				    (dev->flags & IFF_PROMISC) ? 1 : 0,
-				    (dev->flags & IFF_ALLMULTI) ? 1 : 0, 1,
+				    (dev->flags & IFF_ALLMULTI) ? 1 : 0, 1, -1,
 				    sleep_ok);
 	return ret;
 }
@@ -311,7 +311,7 @@ static int link_start(struct net_device *dev)
 	 * that step explicitly.
 	 */
 	ret = t4_set_rxmode(pi->adapter, 0, pi->viid, dev->mtu, -1, -1, -1,
-			    true);
+			    pi->vlan_grp != NULL, true);
 	if (ret == 0) {
 		ret = t4_change_mac(pi->adapter, 0, pi->viid,
 				    pi->xact_addr_filt, dev->dev_addr, true,
@@ -2614,7 +2614,7 @@ static int cxgb_change_mtu(struct net_device *dev, int new_mtu)
 
 	if (new_mtu < 81 || new_mtu > MAX_MTU)         /* accommodate SACK */
 		return -EINVAL;
-	ret = t4_set_rxmode(pi->adapter, 0, pi->viid, new_mtu, -1, -1, -1,
+	ret = t4_set_rxmode(pi->adapter, 0, pi->viid, new_mtu, -1, -1, -1, -1,
 			    true);
 	if (!ret)
 		dev->mtu = new_mtu;
@@ -2645,7 +2645,8 @@ static void vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
 	struct port_info *pi = netdev_priv(dev);
 
 	pi->vlan_grp = grp;
-	t4_set_vlan_accel(pi->adapter, 1 << pi->tx_chan, grp != NULL);
+	t4_set_rxmode(pi->adapter, 0, pi->viid, -1, -1, -1, -1, grp != NULL,
+		      true);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/cxgb4/t4_hw.c b/drivers/net/cxgb4/t4_hw.c
index 2923dd4..da272a9 100644
--- a/drivers/net/cxgb4/t4_hw.c
+++ b/drivers/net/cxgb4/t4_hw.c
@@ -886,22 +886,6 @@ int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port)
 	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
 }
 
-/**
- *	t4_set_vlan_accel - configure HW VLAN extraction
- *	@adap: the adapter
- *	@ports: bitmap of adapter ports to operate on
- *	@on: enable (1) or disable (0) HW VLAN extraction
- *
- *	Enables or disables HW extraction of VLAN tags for the ports specified
- *	by @ports.  @ports is a bitmap with the ith bit designating the port
- *	associated with the ith adapter channel.
- */
-void t4_set_vlan_accel(struct adapter *adap, unsigned int ports, int on)
-{
-	ports <<= VLANEXTENABLE_SHIFT;
-	t4_set_reg_field(adap, TP_OUT_CONFIG, ports, on ? ports : 0);
-}
-
 struct intr_info {
 	unsigned int mask;       /* bits to check in interrupt status */
 	const char *msg;         /* message to print or NULL */
@@ -2624,12 +2608,14 @@ int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf,
  *	@promisc: 1 to enable promiscuous mode, 0 to disable it, -1 no change
  *	@all_multi: 1 to enable all-multi mode, 0 to disable it, -1 no change
  *	@bcast: 1 to enable broadcast Rx, 0 to disable it, -1 no change
+ *	@vlanex: 1 to enable HW VLAN extraction, 0 to disable it, -1 no change
  *	@sleep_ok: if true we may sleep while awaiting command completion
  *
  *	Sets Rx properties of a virtual interface.
  */
 int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid,
-		  int mtu, int promisc, int all_multi, int bcast, bool sleep_ok)
+		  int mtu, int promisc, int all_multi, int bcast, int vlanex,
+		  bool sleep_ok)
 {
 	struct fw_vi_rxmode_cmd c;
 
@@ -2642,15 +2628,18 @@ int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid,
 		all_multi = FW_VI_RXMODE_CMD_ALLMULTIEN_MASK;
 	if (bcast < 0)
 		bcast = FW_VI_RXMODE_CMD_BROADCASTEN_MASK;
+	if (vlanex < 0)
+		vlanex = FW_VI_RXMODE_CMD_VLANEXEN_MASK;
 
 	memset(&c, 0, sizeof(c));
 	c.op_to_viid = htonl(FW_CMD_OP(FW_VI_RXMODE_CMD) | FW_CMD_REQUEST |
 			     FW_CMD_WRITE | FW_VI_RXMODE_CMD_VIID(viid));
 	c.retval_len16 = htonl(FW_LEN16(c));
-	c.mtu_to_broadcasten = htonl(FW_VI_RXMODE_CMD_MTU(mtu) |
-				     FW_VI_RXMODE_CMD_PROMISCEN(promisc) |
-				     FW_VI_RXMODE_CMD_ALLMULTIEN(all_multi) |
-				     FW_VI_RXMODE_CMD_BROADCASTEN(bcast));
+	c.mtu_to_vlanexen = htonl(FW_VI_RXMODE_CMD_MTU(mtu) |
+				  FW_VI_RXMODE_CMD_PROMISCEN(promisc) |
+				  FW_VI_RXMODE_CMD_ALLMULTIEN(all_multi) |
+				  FW_VI_RXMODE_CMD_BROADCASTEN(bcast) |
+				  FW_VI_RXMODE_CMD_VLANEXEN(vlanex));
 	return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok);
 }
 
diff --git a/drivers/net/cxgb4/t4fw_api.h b/drivers/net/cxgb4/t4fw_api.h
index 3393d05..63991d6 100644
--- a/drivers/net/cxgb4/t4fw_api.h
+++ b/drivers/net/cxgb4/t4fw_api.h
@@ -876,7 +876,7 @@ struct fw_vi_mac_cmd {
 struct fw_vi_rxmode_cmd {
 	__be32 op_to_viid;
 	__be32 retval_len16;
-	__be32 mtu_to_broadcasten;
+	__be32 mtu_to_vlanexen;
 	__be32 r4_lo;
 };
 
@@ -888,6 +888,8 @@ struct fw_vi_rxmode_cmd {
 #define FW_VI_RXMODE_CMD_ALLMULTIEN(x) ((x) << 12)
 #define FW_VI_RXMODE_CMD_BROADCASTEN_MASK 0x3
 #define FW_VI_RXMODE_CMD_BROADCASTEN(x) ((x) << 10)
+#define FW_VI_RXMODE_CMD_VLANEXEN_MASK 0x3
+#define FW_VI_RXMODE_CMD_VLANEXEN(x) ((x) << 8)
 
 struct fw_vi_enable_cmd {
 	__be32 op_to_viid;
-- 
1.5.4


^ permalink raw reply related

* Re: [PATCH net-next 3/3] cxgb4: report GRO stats with ethtool -S
From: Ben Greear @ 2010-05-11  3:02 UTC (permalink / raw)
  To: Dimitris Michailidis; +Cc: netdev
In-Reply-To: <1273543089-10938-3-git-send-email-dm@chelsio.com>

On 05/10/2010 06:58 PM, Dimitris Michailidis wrote:
> Signed-off-by: Dimitris Michailidis<dm@chelsio.com>

One of these is on-wire packets?  If so, maybe use the same
string as Intel ixgbe uses:

rx_pkts_nic  # Pkts received by NIC from wire.
rx_bytes_nic # Bytes received by NIC from wire.
tx_pkts_nic  # Pkts transmitted to wire by NIC.
tx_bytes_nic # Bytes transmitted to wire by NIC.

Thanks,
Ben



> ---
>   drivers/net/cxgb4/cxgb4_main.c |    6 ++++++
>   1 files changed, 6 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
> index 80c3fc5..90d375b 100644
> --- a/drivers/net/cxgb4/cxgb4_main.c
> +++ b/drivers/net/cxgb4/cxgb4_main.c
> @@ -859,6 +859,8 @@ static char stats_strings[][ETH_GSTRING_LEN] = {
>   	"RxCsumGood         ",
>   	"VLANextractions    ",
>   	"VLANinsertions     ",
> +	"GROpackets         ",
> +	"GROmerged          ",
>   };
>
>   static int get_sset_count(struct net_device *dev, int sset)
> @@ -922,6 +924,8 @@ struct queue_port_stats {
>   	u64 rx_csum;
>   	u64 vlan_ex;
>   	u64 vlan_ins;
> +	u64 gro_pkts;
> +	u64 gro_merged;
>   };
>
>   static void collect_sge_port_stats(const struct adapter *adap,
> @@ -938,6 +942,8 @@ static void collect_sge_port_stats(const struct adapter *adap,
>   		s->rx_csum += rx->stats.rx_cso;
>   		s->vlan_ex += rx->stats.vlan_ex;
>   		s->vlan_ins += tx->vlan_ins;
> +		s->gro_pkts += rx->stats.lro_pkts;
> +		s->gro_merged += rx->stats.lro_merged;
>   	}
>   }
>


-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com

^ 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