* [PATCH 4/4] forcedeth: add transmit timestamping support
From: Willem de Bruijn @ 2012-04-27 19:04 UTC (permalink / raw)
To: davem, netdev, jeffrey.t.kirscher, eilong, aabdulla; +Cc: Willem de Bruijn
In-Reply-To: <1335553447-11964-1-git-send-email-willemb@google.com>
Insert an skb_tx_timestamp call in both ndo_start_xmit routines
Tested to work for the nv_start_xmit_optimized case
Signed-off-by: Willem de Bruijn <willemb@google.com>
---
drivers/net/ethernet/nvidia/forcedeth.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index d93a088..928913c 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -2279,6 +2279,8 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_sent_queue(np->dev, skb->len);
+ skb_tx_timestamp(skb);
+
np->put_tx.orig = put_tx;
spin_unlock_irqrestore(&np->lock, flags);
@@ -2426,6 +2428,8 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb,
netdev_sent_queue(np->dev, skb->len);
+ skb_tx_timestamp(skb);
+
np->put_tx.ex = put_tx;
spin_unlock_irqrestore(&np->lock, flags);
--
1.7.7.3
^ permalink raw reply related
* Technical Support
From: WEB ADMINISTRATOR @ 2012-04-27 18:52 UTC (permalink / raw)
Your webmail quota system has exceeded the storage limit,Due To hidden
files On your mailbox,Your Are Currently Running On 23GB to Validate your
mailbox and increase your quota.
In addition, You are advice to fill in your
appropriate email login information in order to boost your webmail quota
and to enhance the security of your email account.
Email: ...............
Username:................
password:................
Confirm password .............
If your mailbox remains de-activated for an extended period of time, it
may result in further limitations or eventual closure
Technical Support
192.168.0.1
----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.
--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
^ permalink raw reply
* Re: [PATCH 3/4] bnx2x: add transmit timestamping support
From: Eilon Greenstein @ 2012-04-27 19:30 UTC (permalink / raw)
To: Willem de Bruijn; +Cc: davem, netdev, jeffrey.t.kirscher, aabdulla, meravs
In-Reply-To: <1335553447-11964-4-git-send-email-willemb@google.com>
On Fri, 2012-04-27 at 15:04 -0400, Willem de Bruijn wrote:
> Signed-off-by: Willem de Bruijn <willemb@google.com>
Acked-by: Eilon Greenstein <eilong@broadcom.com>
Thanks Willem - Merav was just testing exactly the same change, so far
it seems to be working on our side as well :)
^ permalink raw reply
* 72012-4-28
From: 保真优惠发票13928472421张 @ 2012-04-27 19:43 UTC (permalink / raw)
To: nelhage
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="GB2312", Size: 12 bytes --]
éaj\a¤²bqç(
[-- Attachment #2: Ycglpu_9894.gif --]
[-- Type: image/gif, Size: 5 bytes --]
^ permalink raw reply
* Re: [PATCH] e1000e: MSI interrupt test failed, using legacy interrupt
From: Prasanna Panchamukhi @ 2012-04-27 19:52 UTC (permalink / raw)
To: Ben Hutchings
Cc: netdev, bruce.w.allan, jesse.brandeburg, e1000-devel, gospo,
sassmann
In-Reply-To: <1335490840.4056.137.camel@deadeye>
On 04/26/2012 06:40 PM, Ben Hutchings wrote:
> On Thu, 2012-04-26 at 17:05 -0700, prasanna.panchamukhi@riverbed.com
> wrote:
>> From: Prasanna S. Panchamukhi<ppanchamukhi@riverbed.com>
>>
>> Following logs where seen on Systems with multiple NICs& ports,
>> while using MSI interrupts as shown below:
> [...]
>> This patch changes the IRQ tests to use polling loops starting with a
>> delay of 1 tick and doubling that if necessary up to a maximum total
>> delay of approximately 1 second.
> [...]
>
> I don't think you entirely understood my point. This exponential
> back-off was the best I could come up with for a self-test
> (ethtool -t) where we have to answer the question 'are interrupts
> working' in a reasonable time, and the user can decide for themselves
> whether this was a false negative.
>
> If you want a definite answer in order to make an automatic decision
> about interrupt modes, there really is no valid time limit. I think the
This issue is not able interrupt mode selection.
-Prasanna
> proper way to do interrupt mode selection in an in-tree driver is to
> rely on no-MSI quirks for chipsets and devices in the PCI core.
>
> Ben.
>
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit http://communities.intel.com/community/wired
^ permalink raw reply
* [PATCH v2 0/2] drop_monitor: misc fixes for some recently reported bugs
From: Neil Horman @ 2012-04-27 20:11 UTC (permalink / raw)
To: netdev; +Cc: Neil Horman, Eric Dumazet, David Miller
In-Reply-To: <1335466022-32661-1-git-send-email-nhorman@tuxdriver.com>
Hey-
Eric was using dropwatch recently and reported a few bugs to me that he
had noted. This short series should fix them all up.
Change Notes:
V2)
renamed trace_state_lock to trace_state_mutex
cleaned up rcu write side access to use rcu_dereference_protected
handled some NULL allocation failure cases
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Eric Dumazet <eric.dumazet@gmail.com>
CC: David Miller <davem@davemloft.net>
^ permalink raw reply
* [PATCH v2 1/2] drop_monitor: fix sleeping in invalid context warning
From: Neil Horman @ 2012-04-27 20:11 UTC (permalink / raw)
To: netdev; +Cc: Neil Horman, David Miller
In-Reply-To: <1335557509-32726-1-git-send-email-nhorman@tuxdriver.com>
Eric Dumazet pointed out this warning in the drop_monitor protocol to me:
[ 38.352571] BUG: sleeping function called from invalid context at kernel/mutex.c:85
[ 38.352576] in_atomic(): 1, irqs_disabled(): 0, pid: 4415, name: dropwatch
[ 38.352580] Pid: 4415, comm: dropwatch Not tainted 3.4.0-rc2+ #71
[ 38.352582] Call Trace:
[ 38.352592] [<ffffffff8153aaf0>] ? trace_napi_poll_hit+0xd0/0xd0
[ 38.352599] [<ffffffff81063f2a>] __might_sleep+0xca/0xf0
[ 38.352606] [<ffffffff81655b16>] mutex_lock+0x26/0x50
[ 38.352610] [<ffffffff8153aaf0>] ? trace_napi_poll_hit+0xd0/0xd0
[ 38.352616] [<ffffffff810b72d9>] tracepoint_probe_register+0x29/0x90
[ 38.352621] [<ffffffff8153a585>] set_all_monitor_traces+0x105/0x170
[ 38.352625] [<ffffffff8153a8ca>] net_dm_cmd_trace+0x2a/0x40
[ 38.352630] [<ffffffff8154a81a>] genl_rcv_msg+0x21a/0x2b0
[ 38.352636] [<ffffffff810f8029>] ? zone_statistics+0x99/0xc0
[ 38.352640] [<ffffffff8154a600>] ? genl_rcv+0x30/0x30
[ 38.352645] [<ffffffff8154a059>] netlink_rcv_skb+0xa9/0xd0
[ 38.352649] [<ffffffff8154a5f0>] genl_rcv+0x20/0x30
[ 38.352653] [<ffffffff81549a7e>] netlink_unicast+0x1ae/0x1f0
[ 38.352658] [<ffffffff81549d76>] netlink_sendmsg+0x2b6/0x310
[ 38.352663] [<ffffffff8150824f>] sock_sendmsg+0x10f/0x130
[ 38.352668] [<ffffffff8150abe0>] ? move_addr_to_kernel+0x60/0xb0
[ 38.352673] [<ffffffff81515f04>] ? verify_iovec+0x64/0xe0
[ 38.352677] [<ffffffff81509c46>] __sys_sendmsg+0x386/0x390
[ 38.352682] [<ffffffff810ffaf9>] ? handle_mm_fault+0x139/0x210
[ 38.352687] [<ffffffff8165b5bc>] ? do_page_fault+0x1ec/0x4f0
[ 38.352693] [<ffffffff8106ba4d>] ? set_next_entity+0x9d/0xb0
[ 38.352699] [<ffffffff81310b49>] ? tty_ldisc_deref+0x9/0x10
[ 38.352703] [<ffffffff8106d363>] ? pick_next_task_fair+0x63/0x140
[ 38.352708] [<ffffffff8150b8d4>] sys_sendmsg+0x44/0x80
[ 38.352713] [<ffffffff8165f8e2>] system_call_fastpath+0x16/0x1b
It stems from holding a spinlock (trace_state_lock) while attempting to register
or unregister tracepoint hooks, making in_atomic() true in this context, leading
to the warning when the tracepoint calls might_sleep() while its taking a mutex.
Since we only use the trace_state_lock to prevent trace protocol state races, as
well as hardware stat list updates on an rcu write side, we can just convert the
spinlock to a mutex to avoid this problem.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: David Miller <davem@davemloft.net>
---
net/core/drop_monitor.c | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index 5c3c81a..a221a5b 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -42,7 +42,7 @@ static void send_dm_alert(struct work_struct *unused);
* netlink alerts
*/
static int trace_state = TRACE_OFF;
-static DEFINE_SPINLOCK(trace_state_lock);
+static DEFINE_MUTEX(trace_state_mutex);
struct per_cpu_dm_data {
struct work_struct dm_alert_work;
@@ -214,7 +214,7 @@ static int set_all_monitor_traces(int state)
struct dm_hw_stat_delta *new_stat = NULL;
struct dm_hw_stat_delta *temp;
- spin_lock(&trace_state_lock);
+ mutex_lock(&trace_state_mutex);
if (state == trace_state) {
rc = -EAGAIN;
@@ -253,7 +253,7 @@ static int set_all_monitor_traces(int state)
rc = -EINPROGRESS;
out_unlock:
- spin_unlock(&trace_state_lock);
+ mutex_unlock(&trace_state_mutex);
return rc;
}
@@ -296,12 +296,12 @@ static int dropmon_net_event(struct notifier_block *ev_block,
new_stat->dev = dev;
new_stat->last_rx = jiffies;
- spin_lock(&trace_state_lock);
+ mutex_lock(&trace_state_mutex);
list_add_rcu(&new_stat->list, &hw_stats_list);
- spin_unlock(&trace_state_lock);
+ mutex_unlock(&trace_state_mutex);
break;
case NETDEV_UNREGISTER:
- spin_lock(&trace_state_lock);
+ mutex_lock(&trace_state_mutex);
list_for_each_entry_safe(new_stat, tmp, &hw_stats_list, list) {
if (new_stat->dev == dev) {
new_stat->dev = NULL;
@@ -312,7 +312,7 @@ static int dropmon_net_event(struct notifier_block *ev_block,
}
}
}
- spin_unlock(&trace_state_lock);
+ mutex_unlock(&trace_state_mutex);
break;
}
out:
--
1.7.7.6
^ permalink raw reply related
* [PATCH v2 2/2] drop_monitor: Make updating data->skb smp safe
From: Neil Horman @ 2012-04-27 20:11 UTC (permalink / raw)
To: netdev; +Cc: Neil Horman, David Miller
In-Reply-To: <1335557509-32726-1-git-send-email-nhorman@tuxdriver.com>
Eric Dumazet pointed out to me that the drop_monitor protocol has some holes in
its smp protections. Specifically, its possible to replace data->skb while its
being written. This patch corrects that by making data->skb and rcu protected
variable. That will prevent it from being overwritten while a tracepoint is
modifying it.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: David Miller <davem@davemloft.net>
---
net/core/drop_monitor.c | 70 ++++++++++++++++++++++++++++++++++++-----------
1 files changed, 54 insertions(+), 16 deletions(-)
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index a221a5b..4e04cf6 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -46,7 +46,7 @@ static DEFINE_MUTEX(trace_state_mutex);
struct per_cpu_dm_data {
struct work_struct dm_alert_work;
- struct sk_buff *skb;
+ struct sk_buff __rcu *skb;
atomic_t dm_hit_count;
struct timer_list send_timer;
};
@@ -73,35 +73,58 @@ static int dm_hit_limit = 64;
static int dm_delay = 1;
static unsigned long dm_hw_check_delta = 2*HZ;
static LIST_HEAD(hw_stats_list);
+static int initalized = 0;
static void reset_per_cpu_data(struct per_cpu_dm_data *data)
{
size_t al;
struct net_dm_alert_msg *msg;
struct nlattr *nla;
+ struct sk_buff *skb;
+ struct sk_buff *oskb = rcu_dereference_protected(data->skb, 1);
al = sizeof(struct net_dm_alert_msg);
al += dm_hit_limit * sizeof(struct net_dm_drop_point);
al += sizeof(struct nlattr);
- data->skb = genlmsg_new(al, GFP_KERNEL);
- genlmsg_put(data->skb, 0, 0, &net_drop_monitor_family,
- 0, NET_DM_CMD_ALERT);
- nla = nla_reserve(data->skb, NLA_UNSPEC, sizeof(struct net_dm_alert_msg));
- msg = nla_data(nla);
- memset(msg, 0, al);
- atomic_set(&data->dm_hit_count, dm_hit_limit);
+ skb = genlmsg_new(al, GFP_KERNEL);
+
+ if (skb) {
+ genlmsg_put(skb, 0, 0, &net_drop_monitor_family,
+ 0, NET_DM_CMD_ALERT);
+ nla = nla_reserve(skb, NLA_UNSPEC,
+ sizeof(struct net_dm_alert_msg));
+ msg = nla_data(nla);
+ memset(msg, 0, al);
+ } else if (initalized)
+ schedule_work_on(smp_processor_id(), &data->dm_alert_work);
+
+ /*
+ * Don't need to lock this, since we are guaranteed to only
+ * run this on a single cpu at a time.
+ * Note also that we only update data->skb if the old and new skb
+ * pointers don't match. This ensures that we don't continually call
+ * synchornize_rcu if we repeatedly fail to alloc a new netlink message.
+ */
+ if (skb != oskb) {
+ rcu_assign_pointer(data->skb, skb);
+
+ synchronize_rcu();
+
+ atomic_set(&data->dm_hit_count, dm_hit_limit);
+ }
+
}
static void send_dm_alert(struct work_struct *unused)
{
struct sk_buff *skb;
- struct per_cpu_dm_data *data = &__get_cpu_var(dm_cpu_data);
+ struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data);
/*
* Grab the skb we're about to send
*/
- skb = data->skb;
+ skb = rcu_dereference_protected(data->skb, 1);
/*
* Replace it with a new one
@@ -111,8 +134,10 @@ static void send_dm_alert(struct work_struct *unused)
/*
* Ship it!
*/
- genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL);
+ if (skb)
+ genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL);
+ put_cpu_var(dm_cpu_data);
}
/*
@@ -123,9 +148,11 @@ static void send_dm_alert(struct work_struct *unused)
*/
static void sched_send_work(unsigned long unused)
{
- struct per_cpu_dm_data *data = &__get_cpu_var(dm_cpu_data);
+ struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data);
+
+ schedule_work_on(smp_processor_id(), &data->dm_alert_work);
- schedule_work(&data->dm_alert_work);
+ put_cpu_var(dm_cpu_data);
}
static void trace_drop_common(struct sk_buff *skb, void *location)
@@ -134,9 +161,16 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
struct nlmsghdr *nlh;
struct nlattr *nla;
int i;
- struct per_cpu_dm_data *data = &__get_cpu_var(dm_cpu_data);
+ struct sk_buff *dskb;
+ struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data);
+ rcu_read_lock();
+ dskb = rcu_dereference(data->skb);
+
+ if (!dskb)
+ goto out;
+
if (!atomic_add_unless(&data->dm_hit_count, -1, 0)) {
/*
* we're already at zero, discard this hit
@@ -144,7 +178,7 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
goto out;
}
- nlh = (struct nlmsghdr *)data->skb->data;
+ nlh = (struct nlmsghdr *)dskb->data;
nla = genlmsg_data(nlmsg_data(nlh));
msg = nla_data(nla);
for (i = 0; i < msg->entries; i++) {
@@ -158,7 +192,7 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
/*
* We need to create a new entry
*/
- __nla_reserve_nohdr(data->skb, sizeof(struct net_dm_drop_point));
+ __nla_reserve_nohdr(dskb, sizeof(struct net_dm_drop_point));
nla->nla_len += NLA_ALIGN(sizeof(struct net_dm_drop_point));
memcpy(msg->points[msg->entries].pc, &location, sizeof(void *));
msg->points[msg->entries].count = 1;
@@ -170,6 +204,8 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
}
out:
+ rcu_read_unlock();
+ put_cpu_var(dm_cpu_data);
return;
}
@@ -375,6 +411,8 @@ static int __init init_net_drop_monitor(void)
data->send_timer.function = sched_send_work;
}
+ initalized = 1;
+
goto out;
out_unreg:
--
1.7.7.6
^ permalink raw reply related
* Re: [PATCH RFC 1/2] netfilter: conntrack: remove RCU usage in conntrack notifier
From: Benjamin Poirier @ 2012-04-27 20:14 UTC (permalink / raw)
To: Eric Dumazet
Cc: netdev, Pablo Neira Ayuso, Patrick McHardy, David S. Miller,
Andrew Morton, Mike Frysinger, Arun Sharma, netfilter-devel,
netfilter, coreteam, linux-kernel, Paul E. McKenney
In-Reply-To: <1335553131.2775.252.camel@edumazet-glaptop>
On 2012/04/27 20:58, Eric Dumazet wrote:
> On Fri, 2012-04-27 at 14:28 -0400, Benjamin Poirier wrote:
> > I think that the rcu usage in this code is pointless. It should either be
> > removed or, if it was intended to protect against something, it ought to make
> > that clear.
> >
> > 1) The code does not make use of the deferred deletion/wait for completion rcu
> > api (ie. synchronize_rcu(), call_rcu()).
> > 2) It does not benefit from the barriers implied by the rcu primitives used.
> > The code deals with callback pointers. There's no need to order writes to the
> > function code (!) before writes to the function pointers here.
> > ---
>
> At a first glance, this seems pretty wrong.
>
> code can disappear under you, thats for sure.
>
> CONFIG_NF_CT_NETLINK=m
>
> hint : module unload contains an rcu barrier.
>
Thank you Eric. I had indeed failed to consider module load/unload
cases, which are effectively "writes to function code".
^ permalink raw reply
* Re: [PATCH 2/2] net/ieee802154/6lowpan.c: reuse eth_mac_addr()
From: Tony Cheneau @ 2012-04-27 20:21 UTC (permalink / raw)
To: Danny Kukawka
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, Danny Kukawka,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
David S. Miller
In-Reply-To: <1329914199-30862-3-git-send-email-danny.kukawka-2YacvwyR+KOzQB+pC5nmwQ@public.gmane.org>
Hello,
I believe the following patch should not have been applied and should
now be reverted.
The reason is because eth_mac_addr() is not functionally equivalent to
lowpan_set_address() that it replaces:
- lowpan_set_address() copies dev->addr_len bytes, where dev->addr_len
is set to 8 bytes for IEEE802154 devices (this is an IEEE EUI-64
address). Hence, the function copies the full 8 bytes of the address.
- eth_mac_addr() copies ETH_ALEN bytes, where ETH_ALEN is set to 6.
Hence, the function copies only 6 bytes of the 8 bytes address. So, 2
bytes of the address are never copied.
Does this sound reasonable?
Regards,
Tony
Le 22.02.2012 14:36, Danny Kukawka a écrit :
> Use eth_mac_addr() for .ndo_set_mac_address, remove
> lowpan_set_address since it do currently the same as
> eth_mac_addr(). Additional advantage: eth_mac_addr() already
> checks if the given address is valid
>
> Signed-off-by: Danny Kukawka <danny.kukawka@bisect.de>
> ---
> net/ieee802154/6lowpan.c | 16 ++--------------
> 1 files changed, 2 insertions(+), 14 deletions(-)
>
> diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
> index e4ecc1e..3685158 100644
> --- a/net/ieee802154/6lowpan.c
> +++ b/net/ieee802154/6lowpan.c
> @@ -55,6 +55,7 @@
> #include <linux/module.h>
> #include <linux/moduleparam.h>
> #include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
> #include <net/af_ieee802154.h>
> #include <net/ieee802154.h>
> #include <net/ieee802154_netdev.h>
> @@ -924,19 +925,6 @@ drop:
> return -EINVAL;
> }
>
> -static int lowpan_set_address(struct net_device *dev, void *p)
> -{
> - struct sockaddr *sa = p;
> -
> - if (netif_running(dev))
> - return -EBUSY;
> -
> - /* TODO: validate addr */
> - memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
> -
> - return 0;
> -}
> -
> static int lowpan_get_mac_header_length(struct sk_buff *skb)
> {
> /*
> @@ -1062,7 +1050,7 @@ static struct header_ops lowpan_header_ops = {
>
> static const struct net_device_ops lowpan_netdev_ops = {
> .ndo_start_xmit = lowpan_xmit,
> - .ndo_set_mac_address = lowpan_set_address,
> + .ndo_set_mac_address = eth_mac_addr,
> };
>
> static void lowpan_setup(struct net_device *dev)
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Linux-zigbee-devel mailing list
Linux-zigbee-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-zigbee-devel
^ permalink raw reply
* sky2 still badly broken
From: Niccolò Belli @ 2012-04-27 20:15 UTC (permalink / raw)
To: netdev
dmesg is full of
[ 1464.914044] sky2 0000:06:00.0: eth0: rx error, status 0x5220002
length 1314
[ 1465.005628] sky2 0000:06:00.0: eth0: rx error, status 0x7ffc0001
length 532
[ 1465.204459] sky2 0000:06:00.0: eth0: rx error, status 0x7ffc0001
length 532
[ 1465.825909] sky2 0000:06:00.0: eth0: rx error, status 0x7ffc0001
length 532
[ 1468.715858] net_ratelimit: 3 callbacks suppressed
[ 1468.715865] sky2 0000:06:00.0: eth0: rx error, status 0x7ffc0001
length 532
dhcp does not work (after a few minutes it does not renew the ip)
while under heavy load the card resets and I have to unload and reload
the module
also transfer rate is VERY low.
lowering the mtu does help a bit, but it doesn't make miracles...
kernel 3.4.0-rc4
06:00.0 Ethernet controller: Marvell Technology Group Ltd. 88E8055 PCI-E
Gigabit Ethernet Controller (rev 13)
http://forums.gentoo.org/viewtopic-t-487018-start-0-postdays-0-postorder-asc-highlight-.html
Thanks,
Niccolò
^ permalink raw reply
* [RFT] sky2: fix status length check on older chips
From: Stephen Hemminger @ 2012-04-27 20:41 UTC (permalink / raw)
To: Niccolò Belli; +Cc: netdev
In-Reply-To: <4F9AFE4E.8010108@linuxsystems.it>
Mirko and I were working on a related issue, here is his fix.
I proposed a similar alternative, but he was unavailable to test it,
and therefore was still pending. Does this fix your problem?
=================
From: From: Mirko Lindner <mlindner@marvell.com>
Bug: The VLAN bit of the MAC RX Status Word is unreliable in several older
supported chips. Sometimes the VLAN bit is not set for valid VLAN packets
and also sometimes the VLAN bit is set for non-VLAN packets that came after
a VLAN packet. This results in a receive length error when VLAN hardware
tagging is enabled.
Fix: The driver uses only VLAN information included in VLAN status list elements,
that signals that the VLAN tag field is valid. It must ignore the VLAN bit in the
MAC RX Status Word. An additional variable set when evaluating the VLAN opcodes
is used to indicate that the received packet is a VLAN packet and a packet length
correction (subtraction of VLAN header length) must be done.
Signed-off-by: Mirko Lindner <mlindner@marvell.com>
--- a/drivers/net/ethernet/marvell/sky2.c 2012-04-18 23:44:40.637276647 -0700
+++ b/drivers/net/ethernet/marvell/sky2.c 2012-04-27 13:36:07.487834432 -0700
@@ -2580,7 +2580,7 @@ static struct sk_buff *sky2_receive(stru
struct sk_buff *skb = NULL;
u16 count = (status & GMR_FS_LEN) >> 16;
- if (status & GMR_FS_VLAN)
+ if (sky2->rx_vlan)
count -= VLAN_HLEN; /* Account for vlan tag */
netif_printk(sky2, rx_status, KERN_DEBUG, dev,
@@ -2646,11 +2646,13 @@ static inline void sky2_tx_done(struct n
}
}
-static inline void sky2_skb_rx(const struct sky2_port *sky2,
- u32 status, struct sk_buff *skb)
+static inline void sky2_skb_rx(struct sky2_port *sky2,
+ struct sk_buff *skb)
{
- if (status & GMR_FS_VLAN)
+ if (sky2->rx_vlan) {
__vlan_hwaccel_put_tag(skb, be16_to_cpu(sky2->rx_tag));
+ sky2->rx_vlan = 0;
+ }
if (skb->ip_summed == CHECKSUM_NONE)
netif_receive_skb(skb);
--- a/drivers/net/ethernet/marvell/sky2.h 2012-02-13 09:23:53.642447236 -0800
+++ b/drivers/net/ethernet/marvell/sky2.h 2012-04-27 13:36:07.487834432 -0700
@@ -2242,6 +2242,7 @@ struct sky2_port {
u16 rx_data_size;
u16 rx_nfrags;
u16 rx_tag;
+ u8 rx_vlan;
struct {
unsigned long last;
^ permalink raw reply
* Re: [RFT] sky2: fix status length check on older chips
From: David Miller @ 2012-04-27 20:48 UTC (permalink / raw)
To: shemminger; +Cc: darkbasic, netdev
In-Reply-To: <20120427134127.6d536a96@nehalam.linuxnetplumber.net>
From: Stephen Hemminger <shemminger@vyatta.com>
Date: Fri, 27 Apr 2012 13:41:27 -0700
> Mirko and I were working on a related issue, here is his fix.
> I proposed a similar alternative, but he was unavailable to test it,
> and therefore was still pending. Does this fix your problem?
Nothing sets ->rx_vlan in that patch.
^ permalink raw reply
* Re: [RFT] sky2: fix status length check on older chips
From: Stephen Hemminger @ 2012-04-27 20:55 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Niccolò Belli, netdev
In-Reply-To: <20120427134127.6d536a96@nehalam.linuxnetplumber.net>
Mirko and I were working on a related issue, here is his fix.
I proposed a similar alternative, but he was unavailable to test it,
and therefore was still pending. Does this fix your problem?
Resend with missing bits.
The cleaner alternative is to not use the boolean flag, but instead
put tag on skb directly (eliminating rx_tag and rx_vlan from
data structure).
=================
From: From: Mirko Lindner <mlindner@marvell.com>
Bug: The VLAN bit of the MAC RX Status Word is unreliable in several older
supported chips. Sometimes the VLAN bit is not set for valid VLAN packets
and also sometimes the VLAN bit is set for non-VLAN packets that came after
a VLAN packet. This results in a receive length error when VLAN hardware
tagging is enabled.
Fix: The driver uses only VLAN information included in VLAN status list elements,
that signals that the VLAN tag field is valid. It must ignore the VLAN bit in the
MAC RX Status Word. An additional variable set when evaluating the VLAN opcodes
is used to indicate that the received packet is a VLAN packet and a packet length
correction (subtraction of VLAN header length) must be done.
Signed-off-by: Mirko Lindner <mlindner@marvell.com>
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
---
--- a/drivers/net/ethernet/marvell/sky2.c 2012-04-18 23:44:40.637276647 -0700
+++ b/drivers/net/ethernet/marvell/sky2.c 2012-04-27 13:52:06.154756866 -0700
@@ -2580,7 +2580,7 @@ static struct sk_buff *sky2_receive(stru
struct sk_buff *skb = NULL;
u16 count = (status & GMR_FS_LEN) >> 16;
- if (status & GMR_FS_VLAN)
+ if (sky2->rx_vlan)
count -= VLAN_HLEN; /* Account for vlan tag */
netif_printk(sky2, rx_status, KERN_DEBUG, dev,
@@ -2646,11 +2646,13 @@ static inline void sky2_tx_done(struct n
}
}
-static inline void sky2_skb_rx(const struct sky2_port *sky2,
- u32 status, struct sk_buff *skb)
+static inline void sky2_skb_rx(struct sky2_port *sky2,
+ struct sk_buff *skb)
{
- if (status & GMR_FS_VLAN)
+ if (sky2->rx_vlan) {
__vlan_hwaccel_put_tag(skb, be16_to_cpu(sky2->rx_tag));
+ sky2->rx_vlan = 0;
+ }
if (skb->ip_summed == CHECKSUM_NONE)
netif_receive_skb(skb);
@@ -2772,10 +2774,12 @@ static int sky2_status_intr(struct sky2_
break;
case OP_RXVLAN:
+ sky2->rx_vlan = 1;
sky2->rx_tag = length;
break;
case OP_RXCHKSVLAN:
+ sky2->rx_vlan = 1;
sky2->rx_tag = length;
/* fall through */
case OP_RXCHKS:
--- a/drivers/net/ethernet/marvell/sky2.h 2012-02-13 09:23:53.642447236 -0800
+++ b/drivers/net/ethernet/marvell/sky2.h 2012-04-27 13:36:07.487834432 -0700
@@ -2242,6 +2242,7 @@ struct sky2_port {
u16 rx_data_size;
u16 rx_nfrags;
u16 rx_tag;
+ u8 rx_vlan;
struct {
unsigned long last;
^ permalink raw reply
* Re: [PATCH][RFC] bonding: delete migrated IP addresses from the rlb hash table
From: Jiri Bohac @ 2012-04-27 21:03 UTC (permalink / raw)
To: Jay Vosburgh; +Cc: Jiri Bohac, Andy Gospodarek, netdev
In-Reply-To: <19845.1335471502@death.nxdomain>
On Thu, Apr 26, 2012 at 01:18:22PM -0700, Jay Vosburgh wrote:
> >On Wed, Mar 07, 2012 at 05:02:16PM +0100, Jiri Bohac wrote:
> >> I think it would be better to also
> >> store the source (server) MAC address in struct client_info and
> >> only flush the hash table entries if the MAC address from the
> >> incoming APR packet and the source MAC address stored in the hash
> >> table differ.
>
> Just to make sure I understand: the additional check you propose
> (beyond a check that the IP source address is not locally in use) is for
> the purpose of minimizing unnecessary flushes, by insuring that the
> address really has moved. Correct?
No. There is no check whether the IP source address is local.
The check looks if the IP source address is stored in the rlb
hash table as ip_src. Could be a result of using the IP address
locally, or by other hosts bridged with the bonding master.
And the additional check that prevents unnecessarry flushes
(caused by ARP packets sent out from the bond being looped back
by a switch) is a check for the MAC address in the ARP packet.
If the MAC address is different from the MAC address stored in
the rlb hash table, it means the host with IP address ip_src does
no longer use mac_src and we must not send out client updates
with this ip_src/mac_src combination.
If the MAC address in the ARP packet is equal to the mac_src, it
could mean two things:
- the IP address has not moved and is still used locally or
bridged to the bonding master; we received this packet because
a switch looped it back to another slave of the bond
- the IP address has actually moved, but the MAC address remained
the same (think of a virtual machine migration, keeping the
virtual NIC's MAC address). We don't mind keeping the
corresponding rlb entry, because the ip/mac combination is
still valid and will not polute ARP caches with invalid
information.
> I'm going to give this a spin this afternoon, but just skimming
> through it, I'm still not that thrilled about the "forward" and
> "reverse" terminology applying to "hash by dst" and "hash by src"; why
> not just call 'em "dst_next" and "src_next", et al, and cut out the
> middle man?
How about these naming changes - patch below:
next -> used_next
prev -> used_prev
rx_hashtbl_head -> rx_hashtbl_used_head
the currect linked list is _not_ a list of hash table
entries with colliding ip_dst. It's a list of entries that are
being used; its purpose is to avoid walking the whole hash table
when looking for used entries;
reverse_next -> src_next
reverse_prev -> src_prev
reverse_first -> src_first
I also renamed some of the functions, e.g.
rlb_src_unlink/rlb_src_link instead of
rlb_delete_table_entry_reverse/rlb_set_reverse_entry
because they actually link the existing entries to the
corresponding linked list.
Signed-off-by: Jiri Bohac <jbohac@suse.cz>
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 9abfde4..a7809ae 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -84,6 +84,9 @@ static inline struct arp_pkt *arp_pkt(const struct sk_buff *skb)
/* Forward declaration */
static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]);
+static void rlb_purge_src_ip(struct bonding *bond, struct arp_pkt *arp);
+static void rlb_src_unlink(struct bonding *bond, u32 index);
+static void rlb_src_link(struct bonding *bond, u32 ip_src_hash, u32 ip_dst_hash);
static inline u8 _simple_hash(const u8 *hash_start, int hash_size)
{
@@ -364,6 +367,17 @@ static void rlb_arp_recv(struct sk_buff *skb, struct bonding *bond,
return;
}
+ /* We received an ARP from arp->ip_src.
+ * We might have used this IP address previously (on the bonding host
+ * itself or on a system that is bridged together with the bond).
+ * However, if arp->mac_src is different than what is stored in
+ * rx_hashtbl, some other host is now using the IP and we must prevent
+ * sending out client updates with this IP address and the old MAC address.
+ * Clean up all hash table entries that have this address as ip_src but
+ * have a dirrerent mac_src.
+ */
+ rlb_purge_src_ip(bond, arp);
+
if (arp->op_code == htons(ARPOP_REPLY)) {
/* update rx hash table for this ARP */
rlb_update_entry_from_arp(bond, arp);
@@ -440,9 +454,9 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
_lock_rx_hashtbl_bh(bond);
rx_hash_table = bond_info->rx_hashtbl;
- index = bond_info->rx_hashtbl_head;
+ index = bond_info->rx_hashtbl_used_head;
for (; index != RLB_NULL_INDEX; index = next_index) {
- next_index = rx_hash_table[index].next;
+ next_index = rx_hash_table[index].used_next;
if (rx_hash_table[index].slave == slave) {
struct slave *assigned_slave = rlb_next_rx_slave(bond);
@@ -527,8 +541,8 @@ static void rlb_update_rx_clients(struct bonding *bond)
_lock_rx_hashtbl_bh(bond);
- hash_index = bond_info->rx_hashtbl_head;
- for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+ hash_index = bond_info->rx_hashtbl_used_head;
+ for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->used_next) {
client_info = &(bond_info->rx_hashtbl[hash_index]);
if (client_info->ntt) {
rlb_update_client(client_info);
@@ -556,8 +570,8 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla
_lock_rx_hashtbl_bh(bond);
- hash_index = bond_info->rx_hashtbl_head;
- for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+ hash_index = bond_info->rx_hashtbl_used_head;
+ for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->used_next) {
client_info = &(bond_info->rx_hashtbl[hash_index]);
if ((client_info->slave == slave) &&
@@ -586,8 +600,8 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, __be32 src_ip)
_lock_rx_hashtbl(bond);
- hash_index = bond_info->rx_hashtbl_head;
- for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+ hash_index = bond_info->rx_hashtbl_used_head;
+ for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->used_next) {
client_info = &(bond_info->rx_hashtbl[hash_index]);
if (!client_info->slave) {
@@ -633,6 +647,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
/* update mac address from arp */
memcpy(client_info->mac_dst, arp->mac_dst, ETH_ALEN);
}
+ memcpy(client_info->mac_src, arp->mac_src, ETH_ALEN);
assigned_slave = client_info->slave;
if (assigned_slave) {
@@ -655,6 +670,13 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
assigned_slave = rlb_next_rx_slave(bond);
if (assigned_slave) {
+ if (!(client_info->assigned && client_info->ip_src == arp->ip_src)) {
+ /* ip_src is going to be updated, fix the src hash list */
+ u32 hash_src = _simple_hash((u8 *)&arp->ip_src, sizeof(arp->ip_src));
+ rlb_src_unlink(bond, hash_index);
+ rlb_src_link(bond, hash_src, hash_index);
+ }
+
client_info->ip_src = arp->ip_src;
client_info->ip_dst = arp->ip_dst;
/* arp->mac_dst is broadcast for arp reqeusts.
@@ -662,6 +684,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
* upon receiving an arp reply.
*/
memcpy(client_info->mac_dst, arp->mac_dst, ETH_ALEN);
+ memcpy(client_info->mac_src, arp->mac_src, ETH_ALEN);
client_info->slave = assigned_slave;
if (compare_ether_addr_64bits(client_info->mac_dst, mac_bcast)) {
@@ -677,11 +700,11 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
}
if (!client_info->assigned) {
- u32 prev_tbl_head = bond_info->rx_hashtbl_head;
- bond_info->rx_hashtbl_head = hash_index;
- client_info->next = prev_tbl_head;
+ u32 prev_tbl_head = bond_info->rx_hashtbl_used_head;
+ bond_info->rx_hashtbl_used_head = hash_index;
+ client_info->used_next = prev_tbl_head;
if (prev_tbl_head != RLB_NULL_INDEX) {
- bond_info->rx_hashtbl[prev_tbl_head].prev =
+ bond_info->rx_hashtbl[prev_tbl_head].used_prev =
hash_index;
}
client_info->assigned = 1;
@@ -748,8 +771,8 @@ static void rlb_rebalance(struct bonding *bond)
_lock_rx_hashtbl_bh(bond);
ntt = 0;
- hash_index = bond_info->rx_hashtbl_head;
- for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+ hash_index = bond_info->rx_hashtbl_used_head;
+ for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->used_next) {
client_info = &(bond_info->rx_hashtbl[hash_index]);
assigned_slave = rlb_next_rx_slave(bond);
if (assigned_slave && (client_info->slave != assigned_slave)) {
@@ -767,11 +790,113 @@ static void rlb_rebalance(struct bonding *bond)
}
/* Caller must hold rx_hashtbl lock */
+static void rlb_init_table_entry_dst(struct rlb_client_info *entry)
+{
+ entry->used_next = RLB_NULL_INDEX;
+ entry->used_prev = RLB_NULL_INDEX;
+ entry->assigned = 0;
+ entry->slave = NULL;
+ entry->tag = 0;
+}
+static void rlb_init_table_entry_src(struct rlb_client_info *entry)
+{
+ entry->src_first = RLB_NULL_INDEX;
+ entry->src_prev = RLB_NULL_INDEX;
+ entry->src_next = RLB_NULL_INDEX;
+}
+
static void rlb_init_table_entry(struct rlb_client_info *entry)
{
memset(entry, 0, sizeof(struct rlb_client_info));
- entry->next = RLB_NULL_INDEX;
- entry->prev = RLB_NULL_INDEX;
+ rlb_init_table_entry_dst(entry);
+ rlb_init_table_entry_src(entry);
+}
+
+static void rlb_delete_table_entry_dst(struct bonding *bond, u32 index)
+{
+ struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+ u32 next_index = bond_info->rx_hashtbl[index].used_next;
+ u32 prev_index = bond_info->rx_hashtbl[index].used_prev;
+
+ if (index == bond_info->rx_hashtbl_used_head)
+ bond_info->rx_hashtbl_used_head = next_index;
+ if (prev_index != RLB_NULL_INDEX)
+ bond_info->rx_hashtbl[prev_index].used_next = next_index;
+ if (next_index != RLB_NULL_INDEX)
+ bond_info->rx_hashtbl[next_index].used_prev = prev_index;
+}
+
+/* unlink a rlb hash table entry from the src list */
+static void rlb_src_unlink(struct bonding *bond, u32 index)
+{
+ struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+ u32 next_index = bond_info->rx_hashtbl[index].src_next;
+ u32 prev_index = bond_info->rx_hashtbl[index].src_prev;
+
+ bond_info->rx_hashtbl[index].src_next = RLB_NULL_INDEX;
+ bond_info->rx_hashtbl[index].src_prev = RLB_NULL_INDEX;
+
+ if (next_index != RLB_NULL_INDEX)
+ bond_info->rx_hashtbl[next_index].src_prev = prev_index;
+
+ if (prev_index == RLB_NULL_INDEX)
+ return;
+
+ /* is prev_index pointing to the head of this list? */
+ if (bond_info->rx_hashtbl[prev_index].src_first == index)
+ bond_info->rx_hashtbl[prev_index].src_first = next_index;
+ else
+ bond_info->rx_hashtbl[prev_index].src_next = next_index;
+
+}
+
+static void rlb_delete_table_entry(struct bonding *bond, u32 index)
+{
+ struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+ struct rlb_client_info *entry = &(bond_info->rx_hashtbl[index]);
+
+ rlb_delete_table_entry_dst(bond, index);
+ rlb_init_table_entry_dst(entry);
+
+ rlb_src_unlink(bond, index);
+}
+
+/* add the rx_hashtbl[ip_dst_hash] entry to the list
+ * of entries with identical ip_src_hash
+ */
+static void rlb_src_link(struct bonding *bond, u32 ip_src_hash, u32 ip_dst_hash)
+{
+ struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+ u32 next;
+
+ bond_info->rx_hashtbl[ip_dst_hash].src_prev = ip_src_hash;
+ next = bond_info->rx_hashtbl[ip_src_hash].src_first;
+ bond_info->rx_hashtbl[ip_dst_hash].src_next = next;
+ if (next != RLB_NULL_INDEX)
+ bond_info->rx_hashtbl[next].src_prev = ip_dst_hash;
+ bond_info->rx_hashtbl[ip_src_hash].src_first = ip_dst_hash;
+}
+
+/* deletes all rx_hashtbl entries with arp->ip_src if their mac_src does
+ * not match arp->mac_src */
+static void rlb_purge_src_ip(struct bonding *bond, struct arp_pkt *arp)
+{
+ struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+ u32 ip_src_hash = _simple_hash((u8*)&(arp->ip_src), sizeof(arp->ip_src));
+ u32 index;
+
+ _lock_rx_hashtbl_bh(bond);
+
+ index = bond_info->rx_hashtbl[ip_src_hash].src_first;
+ while (index != RLB_NULL_INDEX) {
+ struct rlb_client_info *entry = &(bond_info->rx_hashtbl[index]);
+ u32 next_index = entry->src_next;
+ if (entry->ip_src == arp->ip_src &&
+ compare_ether_addr_64bits(arp->mac_src, entry->mac_src))
+ rlb_delete_table_entry(bond, index);
+ index = next_index;
+ }
+ _unlock_rx_hashtbl_bh(bond);
}
static int rlb_initialize(struct bonding *bond)
@@ -789,7 +914,7 @@ static int rlb_initialize(struct bonding *bond)
bond_info->rx_hashtbl = new_hashtbl;
- bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
+ bond_info->rx_hashtbl_used_head = RLB_NULL_INDEX;
for (i = 0; i < RLB_HASH_TABLE_SIZE; i++) {
rlb_init_table_entry(bond_info->rx_hashtbl + i);
@@ -811,7 +936,7 @@ static void rlb_deinitialize(struct bonding *bond)
kfree(bond_info->rx_hashtbl);
bond_info->rx_hashtbl = NULL;
- bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
+ bond_info->rx_hashtbl_used_head = RLB_NULL_INDEX;
_unlock_rx_hashtbl_bh(bond);
}
@@ -823,25 +948,13 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
_lock_rx_hashtbl_bh(bond);
- curr_index = bond_info->rx_hashtbl_head;
+ curr_index = bond_info->rx_hashtbl_used_head;
while (curr_index != RLB_NULL_INDEX) {
struct rlb_client_info *curr = &(bond_info->rx_hashtbl[curr_index]);
- u32 next_index = bond_info->rx_hashtbl[curr_index].next;
- u32 prev_index = bond_info->rx_hashtbl[curr_index].prev;
-
- if (curr->tag && (curr->vlan_id == vlan_id)) {
- if (curr_index == bond_info->rx_hashtbl_head) {
- bond_info->rx_hashtbl_head = next_index;
- }
- if (prev_index != RLB_NULL_INDEX) {
- bond_info->rx_hashtbl[prev_index].next = next_index;
- }
- if (next_index != RLB_NULL_INDEX) {
- bond_info->rx_hashtbl[next_index].prev = prev_index;
- }
+ u32 next_index = bond_info->rx_hashtbl[curr_index].used_next;
- rlb_init_table_entry(curr);
- }
+ if (curr->tag && (curr->vlan_id == vlan_id))
+ rlb_delete_table_entry(bond, curr_index);
curr_index = next_index;
}
diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
index 90f140a..1fbc938 100644
--- a/drivers/net/bonding/bond_alb.h
+++ b/drivers/net/bonding/bond_alb.h
@@ -100,9 +100,18 @@ struct tlb_client_info {
struct rlb_client_info {
__be32 ip_src; /* the server IP address */
__be32 ip_dst; /* the client IP address */
+ u8 mac_src[ETH_ALEN]; /* the server MAC address */
u8 mac_dst[ETH_ALEN]; /* the client MAC address */
- u32 next; /* The next Hash table entry index */
- u32 prev; /* The previous Hash table entry index */
+
+ /* list of used hash table entries, starting at rx_hashtbl_used_head */
+ u32 used_next;
+ u32 used_prev;
+
+ /* ip_src based hashing */
+ u32 src_next; /* next entry with same hash(ip_src) */
+ u32 src_prev; /* prev entry with same hash(ip_src) */
+ u32 src_first; /* first entry with hash(ip_src) == this entry's index */
+
u8 assigned; /* checking whether this entry is assigned */
u8 ntt; /* flag - need to transmit client info */
struct slave *slave; /* the slave assigned to this client */
@@ -131,7 +140,7 @@ struct alb_bond_info {
int rlb_enabled;
struct rlb_client_info *rx_hashtbl; /* Receive hash table */
spinlock_t rx_hashtbl_lock;
- u32 rx_hashtbl_head;
+ u32 rx_hashtbl_used_head;
u8 rx_ntt; /* flag - need to transmit
* to all rx clients
*/
diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c
index 3680aa2..a570843 100644
--- a/drivers/net/bonding/bond_debugfs.c
+++ b/drivers/net/bonding/bond_debugfs.c
@@ -31,8 +31,8 @@ static int bond_debug_rlb_hash_show(struct seq_file *m, void *v)
spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
- hash_index = bond_info->rx_hashtbl_head;
- for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+ hash_index = bond_info->rx_hashtbl_used_head;
+ for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->used_next) {
client_info = &(bond_info->rx_hashtbl[hash_index]);
seq_printf(m, "%-15pI4 %-15pI4 %-17pM %s\n",
&client_info->ip_src,
--
Jiri Bohac <jbohac@suse.cz>
SUSE Labs, SUSE CZ
^ permalink raw reply related
* Re: [PATCH V2 1/2] bonding support for IPv6 transmit hashing
From: John @ 2012-04-27 21:21 UTC (permalink / raw)
To: Jay Vosburgh; +Cc: netdev
In-Reply-To: <22560.1335307907@death.nxdomain>
Thanks Jay. It was against Linux 3.3.0. I will update my patch and re-post.
John
On 4/24/2012 3:51 PM, Jay Vosburgh wrote:
> John<linux@8192.net> wrote:
>
> In principle, I think this is a good idea, but the patch has
> some (mostly style) issues, and does not apply to net-next (you don't
> say what tree it is based on).
>
> Can you address the comments noted below, and repost against the
> current net-next?
>
^ permalink raw reply
* Re: [PATCH] mwl8k: Add 0x2a02 PCI device-id (Marvell 88W8361)
From: Sedat Dilek @ 2012-04-27 21:53 UTC (permalink / raw)
To: Lennert Buytenhek
Cc: John W. Linville, linux-wireless, netdev, linux-kernel, lautriv,
Jim Cromie
In-Reply-To: <20120427185809.GZ3157@wantstofly.org>
[-- Attachment #1: Type: text/plain, Size: 6523 bytes --]
On Fri, Apr 27, 2012 at 8:58 PM, Lennert Buytenhek
<buytenh@wantstofly.org> wrote:
> On Fri, Apr 27, 2012 at 03:29:26PM +0200, Sedat Dilek wrote:
>
>> >>> >> >> >> Are you planning to or even working on support (for) 8361 devices?
>> >>> >> >> >
>> >>> >> >> > I don't have any such plans, and I don't know of anyone who does.
>> >>> >> >>
>> >>> >> >> Does 8361 require firmware support?
>> >>> >> >
>> >>> >> > What do you mean by that?
>> >>> >>
>> >>> >> IIRC ath5k for example needs no external firmware file.
>> >>> >
>> >>> > The 8361 requires firmware to be loaded into it before it'll do
>> >>> > anything useful.
>> >>> >
>> >>> >
>> >>> >> >> Does a firmware file exist (name?)?
>> >>> >> >
>> >>> >> > There's firmware for the 8361 out there, however, that version of
>> >>> >> > the firmware implements a firmware API that is different from the
>> >>> >> > one that mwl8k currently implements.
>> >>> >> >
>> >>> >> > You could add 8361 support to mwl8k, but then you'd have to go over
>> >>> >> > all the firmware command invocations in mwl8k and make sure that they
>> >>> >> > will work on the 8361 firmware that you're trying to support as well.
>> >>> >>
>> >>> >> Without having a 8361 this will be even harder to walk through.
>> >>> >>
>> >>> >> Anyway, thanks for your detailed explanations.
>> >>> >>
>> >>> >> What's the alternative for such affected users?
>> >>> >> Use ndis-wrapper?
>> >>> >
>> >>> > I'm not sure. I've never tried to get a 8361 work under Linux.
>> >>>
>> >>> Just found on [1] this same wrong patch in [2] :-).
>> >>> Dunno if [3] worked and from where they have stolen fw-files.
>> >>>
>> >>> - Sedat -
>> >>>
>> >>> [1] https://dev.openwrt.org/ticket/7209
>> >>> [2] https://dev.openwrt.org/attachment/ticket/7209/mwl8k_fix_pci_id.patch
>> >>> [3] https://dev.openwrt.org/attachment/ticket/7209/mwl8k_8361p.patch
>> >>
>> >> I doubt that [3] is really all that's needed to make it work. But if
>> >> there's someone for whom it works, I'd like them to run some tests on
>> >> mwl8k + [3] on 88w8361p.
>> >
>> > Just asked lautriv to do so (he will do against linux-3.3.3), lets' see.
>> > Also, I refreshed and adapted a bit the instructions (see attachment).
>> >
>> > - Sedat -
>>
>> [ CC Jim Cromie ]
>>
>> Now, with extracted firmware files renamed & copied to
>> /lib/firmware/mwl8k/ and applied patch (see attachment) against
>> Linux-3.4-rc4+ I am seeing with modinfo:
>>
>> $ sudo modinfo mwl8k
>> filename:
>> /lib/modules/3.4.0-rc4-5-generic/kernel/drivers/net/wireless/mwl8k.ko
>> license: GPL
>> author: Lennert Buytenhek <buytenh@marvell.com>
>> version: 0.13
>> description: Marvell TOPDOG(R) 802.11 Wireless Network Driver
>> firmware: mwl8k/fmimage_8366_ap-2.fw
>> firmware: mwl8k/fmimage_8366.fw
>> firmware: mwl8k/helper_8366.fw
>> firmware: mwl8k/fmimage_8687.fw
>> firmware: mwl8k/helper_8687.fw
>> firmware: mwl8k/fmimage_8363.fw
>> firmware: mwl8k/helper_8363.fw
>> firmware: mwl8k/fmimage_8361p.fw
>> firmware: mwl8k/helper_8361p.fw
>> srcversion: 9E1479A05C8D67E6AE90746
>> alias: pci:v000011ABd00002A43sv*sd*bc*sc*i*
>> alias: pci:v000011ABd00002A40sv*sd*bc*sc*i*
>> alias: pci:v000011ABd00002A30sv*sd*bc*sc*i*
>> alias: pci:v000011ABd00002A2Bsv*sd*bc*sc*i*
>> alias: pci:v000011ABd00002A24sv*sd*bc*sc*i*
>> alias: pci:v000011ABd00002A0Csv*sd*bc*sc*i*
>> alias: pci:v000011ABd00002A0Asv*sd*bc*sc*i*
>> alias: pci:v000011ABd00002A02sv*sd*bc*sc*i* <--- 8361P:
>> 0x2a02 PCI device-id
>> depends: mac80211,cfg80211
>> vermagic: 3.4.0-rc4-5-generic SMP mod_unload modversions
>> parm: ap_mode_default:Set to 1 to make ap mode the default
>> instead of sta mode (bool)
>>
>> $ ls -l /lib/firmware/mwl8k/
>> insgesamt 456
>> -rw-r--r-- 1 root root 75848 Apr 27 13:49 fmimage_8361p.fw <---
>> 8361P: Firmware image
>> -rw-r--r-- 1 root root 101780 Mär 19 19:32 fmimage_8366_ap-1.fw
>> -rw-r--r-- 1 root root 101976 Mär 19 19:32 fmimage_8366_ap-2.fw
>> -rw-r--r-- 1 root root 96664 Mär 19 19:32 fmimage_8366.fw
>> -rw-r--r-- 1 root root 73252 Feb 23 20:07 fmimage_8687.fw
>> -rw-r--r-- 1 root root 2476 Apr 27 13:49 helper_8361p.fw <--- 8361P:
>> Helper image
>> -rw-r--r-- 1 root root 2476 Mär 19 19:32 helper_8366.fw
>> -rw-r--r-- 1 root root 2476 Feb 23 20:07 helper_8687.fw
>>
>> As said... ***compile-tested*** only here.
>
> Which doesn't say much at all, but..
>
As already pointed out, no Marwell WLAN hardware here. Marvell comics
of course :-).
>
>> I had a short query with lautriv on #linux-wireless this afternoon:
>> * mwl8k kernel-module was autoloaded
>> * wlan0 interface got fired up
>> * ESSID was accepted
>> * logs reported 802.11bgn support is active
>> * (he tested on Linux-3.3.3)
>>
>> With WPA/WPA2 lautriv had some problems as his installation was
>> missing wpasupplicant.
>> He setup a classic /etc/network/interfaces.
>> After resetting his router mwl8k worked nicely.
>>
>> Unfortunately, he was on the run and promised me to send logs and do
>> more testing this evening.
>
> ..but this is pretty interesting. I thought that the only available
> 8361p firmware used an incompatible firmware API, and I didn't know
> of the existence of an apparently compatible firmware.
>
>
>> So, Lennert if you want more testing - What? How? etc.
>
> For one, the output of 'iw phy', please.
>
> Also, does monitor mode work? Do you get plausible channel/rxpower
> values in tcpdump in monitor mode?
>
> Are there any messages in the syslog about failing commands?
>
>
> thanks,
> Lennert
On 1st sight, logs look fine:
[21:52:52] <lautriv> [ 6.050967] ieee80211 phy0: 88w8361p v4,
00173f3bdde3, STA firmware 2.1.4.25
But WLAN connection is not that fast and stable as lautriv reports
(several abnormalities were observed).
I requested a tarball which includes:
* dmesg (Linux-3.3.3)
* e_n_a (/etc/network/interfaces)
* ifconfig output
* iwconfig output
* iw_phy output
* ps_axu (WPA) output
lautriv will be so kind to be around on #linux-wireless/Freenode the
next days (UTC+2: German/Swiss local-time).
Just ping him.
Hope you have fun, together!
- Sedat -
[-- Attachment #2: 8361p.tar.xz --]
[-- Type: application/octet-stream, Size: 10076 bytes --]
^ permalink raw reply
* Re: [RFT] sky2: fix status length check on older chips
From: Niccolò Belli @ 2012-04-27 23:05 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20120427135514.48b03ce8@nehalam.linuxnetplumber.net>
It doesn't compile against 3.4-rc4:
CC [M] drivers/net/ethernet/intel/e1000e/param.o
CC [M] drivers/net/ethernet/marvell/sky2.o
CC [M] drivers/net/ethernet/intel/e1000e/ethtool.o
CC [M] net/sunrpc/svc_xprt.o
drivers/net/ethernet/marvell/sky2.c: In function ‘sky2_status_intr’:
drivers/net/ethernet/marvell/sky2.c:2769:4: warning: passing argument 2
of ‘sky2_skb_rx’ makes pointer from integer without a cast
drivers/net/ethernet/marvell/sky2.c:2649:20: note: expected ‘struct
sk_buff *’ but argument is of type ‘u32’
drivers/net/ethernet/marvell/sky2.c:2769:4: error: too many arguments to
function ‘sky2_skb_rx’
drivers/net/ethernet/marvell/sky2.c:2649:20: note: declared here
make[4]: *** [drivers/net/ethernet/marvell/sky2.o] Errore 1
make[3]: *** [drivers/net/ethernet/marvell] Errore 2
make[3]: *** Attesa dei processi non terminati....
CC [M] net/sunrpc/backchannel_rqst.o
CC [M] drivers/net/ethernet/intel/e1000e/netdev.o
Niccolò
^ permalink raw reply
* Re: [PATCH 1/4 net-next] net: allow skb->head to be a page fragment
From: Alexander Duyck @ 2012-04-28 0:27 UTC (permalink / raw)
To: Eric Dumazet
Cc: David Miller, netdev, Ilpo Järvinen, Neal Cardwell,
Tom Herbert, Maciej Żenczykowski, Jeff Kirsher,
Ben Hutchings, Matt Carlson, Michael Chan, Herbert Xu
In-Reply-To: <1335522818.2775.227.camel@edumazet-glaptop>
On 04/27/2012 03:33 AM, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> skb->head is currently allocated from kmalloc(). This is convenient but
> has the drawback the data cannot be converted to a page fragment if
> needed.
>
> We have three spots were it hurts :
>
> 1) GRO aggregation
>
> When a linear skb must be appended to another skb, GRO uses the
> frag_list fallback, very inefficient since we keep all struct sk_buff
> around. So drivers enabling GRO but delivering linear skbs to network
> stack aren't enabling full GRO power.
>
> 2) splice(socket -> pipe).
>
> We must copy the linear part to a page fragment.
> This kind of defeats splice() purpose (zero copy claim)
>
> 3) TCP coalescing.
>
> Recently introduced, this permits to group several contiguous segments
> into a single skb. This shortens queue lengths and save kernel memory,
> and greatly reduce probabilities of TCP collapses. This coalescing
> doesnt work on linear skbs (or we would need to copy data, this would be
> too slow)
>
> Given all these issues, the following patch introduces the possibility
> of having skb->head be a fragment in itself. We use a new skb flag,
> skb->head_frag to carry this information.
>
> build_skb() is changed to accept a frag_size argument. Drivers willing
> to provide a page fragment instead of kmalloc() data will set a non zero
> value, set to the fragment size.
>
> Then, on situations we need to convert the skb head to a frag in itself,
> we can check if skb->head_frag is set and avoid the copies or various
> fallbacks we have.
>
> This means drivers currently using frags could be updated to avoid the
> current skb->head allocation and reduce their memory footprint (aka skb
> truesize). (thats 512 or 1024 bytes saved per skb). This also makes
> bpf/netfilter faster since the 'first frag' will be part of skb linear
> part, no need to copy data.
[...]
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index 2342a72..effa75d 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -245,6 +245,7 @@ EXPORT_SYMBOL(__alloc_skb);
> /**
> * build_skb - build a network buffer
> * @data: data buffer provided by caller
> + * @frag_size: size of fragment, or 0 if head was kmalloced
> *
> * Allocate a new &sk_buff. Caller provides space holding head and
> * skb_shared_info. @data must have been allocated by kmalloc()
> @@ -258,20 +259,21 @@ EXPORT_SYMBOL(__alloc_skb);
> * before giving packet to stack.
> * RX rings only contains data buffers, not full skbs.
> */
> -struct sk_buff *build_skb(void *data)
> +struct sk_buff *build_skb(void *data, unsigned int frag_size)
> {
> struct skb_shared_info *shinfo;
> struct sk_buff *skb;
> - unsigned int size;
> + unsigned int size = frag_size ? : ksize(data);
>
> skb = kmem_cache_alloc(skbuff_head_cache, GFP_ATOMIC);
> if (!skb)
> return NULL;
>
> - size = ksize(data) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
> + size -= SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
>
> memset(skb, 0, offsetof(struct sk_buff, tail));
> skb->truesize = SKB_TRUESIZE(size);
> + skb->head_frag = frag_size != 0;
> atomic_set(&skb->users, 1);
> skb->head = data;
> skb->data = data;
This doesn't seem right to me. You are only counting the piece of the
page that got filled with data and the piece that will get overwritten
with the shared info. What about the rest of the page? It looks like
in the tg3 patch you have the driver using a half page. Based on this
function I suspect the resultant truesize would be something like 64 +
256 + 320 for an ack. Shouldn't your truesize in that case be 2048 + 256?
Thanks,
Alex
^ permalink raw reply
* RE: [PATCH net-next 2/5] be2net: Fix to allow setting of debug levels in the firmware.
From: Somnath.Kotur @ 2012-04-28 1:23 UTC (permalink / raw)
To: Somnath.Kotur, bhutchings; +Cc: netdev
In-Reply-To: <3367B80B08154D42A3B2BC708B5D41F6440F8979D6@EXMAIL.ad.emulex.com>
Ben,
Could you pls respond to my replies inline.
Thanks
Somnath
> -----Original Message-----
> From: netdev-owner@vger.kernel.org [mailto:netdev-
> owner@vger.kernel.org] On Behalf Of Somnath.Kotur@Emulex.Com
> Sent: Friday, April 27, 2012 12:16 PM
> To: bhutchings@solarflare.com
> Cc: netdev@vger.kernel.org
> Subject: RE: [PATCH net-next 2/5] be2net: Fix to allow setting of debug levels
> in the firmware.
>
> > > This operation is intended for controlling logging by the driver,
> > > and the flags
> > are defined in <linux/netdevice.h>. (Not exported to userland yet,
> > but ethtool knows their names.)
> >
> > If your firmware supports some kind of logging then it may be
> > reasonable to have this control both driver and firmware, but not *just*
> the firmware.
> Thanks for your comments Ben.
>
> Currently the driver logs only a very few critical errors/warnings; so we felt it
> might be an overkill to define driver log levels.
> On the other hand, the F/W has extensive logging and tracing facility and the
> ethtool 'msglevel' option seemed like a reasonable method for controlling
> the logging level.
>
> >
> > You should also implement the get_msglevel operation at the same time.
>
> Yes you are correct. We will implement the get_msglevel and re-post the
> patch.
> >
> > Ben.
> >
>
> Thanks
> Som
> N r y b X ǧv ^ ){.n + z ^ ) w*jg \x1e ݢj/ z ޖ 2 ޙ & )ߡ a \x7f \x1e G h \x0f j:+v
> w ٥
^ permalink raw reply
* [PATCH 00/10] atl1c: update hardware settings - v4
From: xiong @ 2012-04-28 1:58 UTC (permalink / raw)
To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong
This update contains a serial of patches, most of them are hardware
settings related. register definitions are refined (or removed if
meaningless) for each patch.
This is the last patch set.
The patches have addressed all sparse and checkpatch warnings.
Following NICs are tested:
AR8131/AR8132/AR8151A/AR8152A/AR8152B
Test item includes:
build/install/uninstall/dhcp/ping/iperf/wol/reboot/etc.
xiong (10):
atl1c: add workaround for issue of bit INTX-disable for MSI interrupt
atl1c: add PHY link event(up/down) patch
atl1c: clear WoL status when reset pcie
atl1c: remove code of closing register writable attribution
atl1c: refine mac address related code
atl1c: enlarge L1 response waiting timer
atl1c: cancel task when interface closed
atl1c: do MAC-reset when PHY link down
atl1c: Disable L0S when no cable link
atl1c: remove PHY polling from atl1c_change_mtu
drivers/net/ethernet/atheros/atl1c/atl1c.h | 1 +
drivers/net/ethernet/atheros/atl1c/atl1c_hw.c | 141 ++++++++++++---------
drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | 35 ++---
drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 153 +++++++++++++++++------
drivers/pci/quirks.c | 12 ++
5 files changed, 220 insertions(+), 122 deletions(-)
--
1.7.7
^ permalink raw reply
* [PATCH 03/10] atl1c: clear WoL status when reset pcie
From: xiong @ 2012-04-28 1:58 UTC (permalink / raw)
To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong
In-Reply-To: <1335578325-21326-1-git-send-email-xiong@qca.qualcomm.com>
WoL status is read-clear and should be cleared when in S0
status.
putting it in atl1c_reset_pcie is more suitable than
in atl1c_get_permanent_address.
Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
---
drivers/net/ethernet/atheros/atl1c/atl1c_hw.c | 5 -----
drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 3 +++
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
index 209c179..49f433e 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
@@ -73,7 +73,6 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
u32 otp_ctrl_data;
u32 twsi_ctrl_data;
u32 ltssm_ctrl_data;
- u32 wol_data;
u8 eth_addr[ETH_ALEN];
u16 phy_data;
bool raise_vol = false;
@@ -114,10 +113,6 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
ltssm_ctrl_data &= ~LTSSM_ID_EN_WRO;
AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, ltssm_ctrl_data);
- /* clear any WOL settings */
- AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
- AT_READ_REG(hw, REG_WOL_CTRL, &wol_data);
-
AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 50df437..6552913 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -133,6 +133,9 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
*/
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0);
+ /* wol sts read-clear */
+ AT_READ_REG(hw, REG_WOL_CTRL, &data);
+ AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
/*
* Mask some pcie error bits
--
1.7.7
^ permalink raw reply related
* [PATCH 04/10] atl1c: remove code of closing register writable attribution
From: xiong @ 2012-04-28 1:58 UTC (permalink / raw)
To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong
In-Reply-To: <1335578325-21326-1-git-send-email-xiong@qca.qualcomm.com>
The Close-action is done by atl1c_reset_pcie, remove it from
atl1c_get_permanent_address.
Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
---
drivers/net/ethernet/atheros/atl1c/atl1c_hw.c | 6 ------
1 files changed, 0 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
index 49f433e..2522685 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
@@ -72,7 +72,6 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
u32 i;
u32 otp_ctrl_data;
u32 twsi_ctrl_data;
- u32 ltssm_ctrl_data;
u8 eth_addr[ETH_ALEN];
u16 phy_data;
bool raise_vol = false;
@@ -108,11 +107,6 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
udelay(20);
raise_vol = true;
}
- /* close open bit of ReadOnly*/
- AT_READ_REG(hw, REG_LTSSM_ID_CTRL, <ssm_ctrl_data);
- ltssm_ctrl_data &= ~LTSSM_ID_EN_WRO;
- AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, ltssm_ctrl_data);
-
AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
--
1.7.7
^ permalink raw reply related
* [PATCH 05/10] atl1c: refine mac address related code
From: xiong @ 2012-04-28 1:58 UTC (permalink / raw)
To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong
In-Reply-To: <1335578325-21326-1-git-send-email-xiong@qca.qualcomm.com>
On some platform with EEPROM/OTP existing, the BIOS could overwrite
a new MAC address for the NIC. so, the permanent mac address should
be from BIOS. the address is restored when driver removing.
Voltage raising isn't applicable for l1d.
Replace swab32 with htonl for big/little endian platform.
related Registers are refined as well.
Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
---
drivers/net/ethernet/atheros/atl1c/atl1c_hw.c | 93 ++++++++++-------------
drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | 32 +++-----
drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 6 +-
3 files changed, 57 insertions(+), 74 deletions(-)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
index 2522685..ff9c738 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
@@ -43,7 +43,7 @@ int atl1c_check_eeprom_exist(struct atl1c_hw *hw)
return 0;
}
-void atl1c_hw_set_mac_addr(struct atl1c_hw *hw)
+void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr)
{
u32 value;
/*
@@ -51,33 +51,48 @@ void atl1c_hw_set_mac_addr(struct atl1c_hw *hw)
* 0: 6AF600DC 1: 000B
* low dword
*/
- value = (((u32)hw->mac_addr[2]) << 24) |
- (((u32)hw->mac_addr[3]) << 16) |
- (((u32)hw->mac_addr[4]) << 8) |
- (((u32)hw->mac_addr[5])) ;
+ value = mac_addr[2] << 24 |
+ mac_addr[3] << 16 |
+ mac_addr[4] << 8 |
+ mac_addr[5];
AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
/* hight dword */
- value = (((u32)hw->mac_addr[0]) << 8) |
- (((u32)hw->mac_addr[1])) ;
+ value = mac_addr[0] << 8 |
+ mac_addr[1];
AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
}
+/* read mac address from hardware register */
+static bool atl1c_read_current_addr(struct atl1c_hw *hw, u8 *eth_addr)
+{
+ u32 addr[2];
+
+ AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]);
+ AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]);
+
+ *(u32 *) ð_addr[2] = htonl(addr[0]);
+ *(u16 *) ð_addr[0] = htons((u16)addr[1]);
+
+ return is_valid_ether_addr(eth_addr);
+}
+
/*
* atl1c_get_permanent_address
* return 0 if get valid mac address,
*/
static int atl1c_get_permanent_address(struct atl1c_hw *hw)
{
- u32 addr[2];
u32 i;
u32 otp_ctrl_data;
u32 twsi_ctrl_data;
- u8 eth_addr[ETH_ALEN];
u16 phy_data;
bool raise_vol = false;
+ /* MAC-address from BIOS is the 1st priority */
+ if (atl1c_read_current_addr(hw, hw->perm_mac_addr))
+ return 0;
+
/* init */
- addr[0] = addr[1] = 0;
AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
if (atl1c_check_eeprom_exist(hw)) {
if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) {
@@ -89,21 +104,14 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
msleep(1);
}
}
-
- if (hw->nic_type == athr_l2c_b ||
- hw->nic_type == athr_l2c_b2 ||
- hw->nic_type == athr_l1d) {
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00);
- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
- goto out;
- phy_data &= 0xFF7F;
- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
-
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
- goto out;
- phy_data |= 0x8;
- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
+ /* raise voltage temporally for l2cb */
+ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) {
+ atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data);
+ phy_data &= ~ANACTRL_HB_EN;
+ atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data);
+ atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data);
+ phy_data |= VOLT_CTRL_SWLOWEST;
+ atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data);
udelay(20);
raise_vol = true;
}
@@ -127,37 +135,18 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
msleep(1);
}
if (raise_vol) {
- if (hw->nic_type == athr_l2c_b ||
- hw->nic_type == athr_l2c_b2 ||
- hw->nic_type == athr_l1d ||
- hw->nic_type == athr_l1d_2) {
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00);
- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
- goto out;
- phy_data |= 0x80;
- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
-
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
- goto out;
- phy_data &= 0xFFF7;
- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
- udelay(20);
- }
+ atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data);
+ phy_data |= ANACTRL_HB_EN;
+ atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data);
+ atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data);
+ phy_data &= ~VOLT_CTRL_SWLOWEST;
+ atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data);
+ udelay(20);
}
- /* maybe MAC-address is from BIOS */
- AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]);
- AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]);
- *(u32 *) ð_addr[2] = swab32(addr[0]);
- *(u16 *) ð_addr[0] = swab16(*(u16 *)&addr[1]);
-
- if (is_valid_ether_addr(eth_addr)) {
- memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+ if (atl1c_read_current_addr(hw, hw->perm_mac_addr))
return 0;
- }
-out:
return -1;
}
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
index ea3f520..21a5bc1 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
@@ -36,7 +36,7 @@ struct atl1c_hw;
/* function prototype */
void atl1c_phy_disable(struct atl1c_hw *hw);
-void atl1c_hw_set_mac_addr(struct atl1c_hw *hw);
+void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr);
int atl1c_phy_reset(struct atl1c_hw *hw);
int atl1c_read_mac_addr(struct atl1c_hw *hw);
int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex);
@@ -94,25 +94,17 @@ void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed);
#define REG_DEV_SERIAL_NUM_EN_SHIFT 1
#define REG_TWSI_CTRL 0x218
+#define TWSI_CTLR_FREQ_MASK 0x3UL
+#define TWSI_CTRL_FREQ_SHIFT 24
+#define TWSI_CTRL_FREQ_100K 0
+#define TWSI_CTRL_FREQ_200K 1
+#define TWSI_CTRL_FREQ_300K 2
+#define TWSI_CTRL_FREQ_400K 3
+#define TWSI_CTRL_LD_EXIST BIT(23)
+#define TWSI_CTRL_HW_LDSTAT BIT(12) /* 0:finish,1:in progress */
+#define TWSI_CTRL_SW_LDSTART BIT(11)
#define TWSI_CTRL_LD_OFFSET_MASK 0xFF
#define TWSI_CTRL_LD_OFFSET_SHIFT 0
-#define TWSI_CTRL_LD_SLV_ADDR_MASK 0x7
-#define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8
-#define TWSI_CTRL_SW_LDSTART 0x800
-#define TWSI_CTRL_HW_LDSTART 0x1000
-#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x7F
-#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15
-#define TWSI_CTRL_LD_EXIST 0x400000
-#define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3
-#define TWSI_CTRL_READ_FREQ_SEL_SHIFT 23
-#define TWSI_CTRL_FREQ_SEL_100K 0
-#define TWSI_CTRL_FREQ_SEL_200K 1
-#define TWSI_CTRL_FREQ_SEL_300K 2
-#define TWSI_CTRL_FREQ_SEL_400K 3
-#define TWSI_CTRL_SMB_SLV_ADDR
-#define TWSI_CTRL_WRITE_FREQ_SEL_MASK 0x3
-#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT 24
-
#define REG_PCIE_DEV_MISC_CTRL 0x21C
#define PCIE_DEV_MISC_EXT_PIPE 0x2
@@ -135,7 +127,7 @@ void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed);
#define L2CB1_PCIE_PHYMISC2_CDR_BW 3
#define REG_TWSI_DEBUG 0x1108
-#define TWSI_DEBUG_DEV_EXIST 0x20000000
+#define TWSI_DEBUG_DEV_EXIST BIT(29)
#define REG_DMA_DBG 0x1114
#define DMA_DBG_VENDOR_MSG BIT(0)
@@ -151,7 +143,7 @@ void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed);
#define REG_EEPROM_DATA_LO 0x12C4
#define REG_OTP_CTRL 0x12F0
-#define OTP_CTRL_CLK_EN 0x0002
+#define OTP_CTRL_CLK_EN BIT(1)
#define REG_PM_CTRL 0x12F8
#define PM_CTRL_HOTRST BIT(31)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 6552913..8fee1fc 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -463,7 +463,7 @@ static int atl1c_set_mac_addr(struct net_device *netdev, void *p)
memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
- atl1c_hw_set_mac_addr(&adapter->hw);
+ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr);
return 0;
}
@@ -2536,7 +2536,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
dev_dbg(&pdev->dev, "mac address : %pM\n",
adapter->hw.mac_addr);
- atl1c_hw_set_mac_addr(&adapter->hw);
+ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr);
INIT_WORK(&adapter->common_task, atl1c_common_task);
adapter->work_event = 0;
err = register_netdev(netdev);
@@ -2580,6 +2580,8 @@ static void __devexit atl1c_remove(struct pci_dev *pdev)
struct atl1c_adapter *adapter = netdev_priv(netdev);
unregister_netdev(netdev);
+ /* restore permanent address */
+ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.perm_mac_addr);
atl1c_phy_disable(&adapter->hw);
iounmap(adapter->hw.hw_addr);
--
1.7.7
^ permalink raw reply related
* [PATCH 06/10] atl1c: enlarge L1 response waiting timer
From: xiong @ 2012-04-28 1:58 UTC (permalink / raw)
To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong
In-Reply-To: <1335578325-21326-1-git-send-email-xiong@qca.qualcomm.com>
The hardware incorrectly process L0S/L1 entrance if the chipset/root
response after specific/shorter timer and cause system hang.
Enlarge the timeout value to avoid this issue.
Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
---
drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
index 21a5bc1..17d935b 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
@@ -157,7 +157,7 @@ void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed);
#define PM_CTRL_PM_REQ_TIMER_MASK 0xFUL
#define PM_CTRL_PM_REQ_TIMER_SHIFT 20 /* pm_request_l1 time > @
* ->L0s not L1 */
-#define PM_CTRL_PM_REQ_TO_DEF 0xC
+#define PM_CTRL_PM_REQ_TO_DEF 0xF
#define PMCTRL_TXL1_AFTER_L0S BIT(19) /* l1dv2.0+ */
#define L1D_PMCTRL_L1_ENTRY_TM_MASK 7UL /* l1dv2.0+, 3bits */
#define L1D_PMCTRL_L1_ENTRY_TM_SHIFT 16
--
1.7.7
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox