* Re: [PATCH] tproxy: nf_tproxy_assign_sock() can handle tw sockets
From: Felipe W Damasio @ 2010-07-14 3:27 UTC (permalink / raw)
To: Eric Dumazet
Cc: Avi Kivity, David Miller, Patrick McHardy, linux-kernel, netdev
In-Reply-To: <1279077678.2444.95.camel@edumazet-laptop>
Hi Mr. Dumazet,
2010/7/14 Eric Dumazet <eric.dumazet@gmail.com>:
> RDX being the sk pointer (and sk+0x38 contains the corrupted "sk_prot" value)
> , we notice RBP contains same "sk" value + 0x200000 (2 Mbytes).
>
> (same remark on your initial bug report)
>
> Could you enable CONFIG_FRAME_POINTER=y in your config ?
I can, but my bosses will kick my ass if I bring down the ISP again :)
If you think it's the only way to find the problem I'll tell them that
I need to do it. In this case, please tell me what other config
options/tools I can use to get as much info as possible...since I'll
probably be able to test this only once more on the production
environment for debugging purposes.
Cheers,
Felipe Damasio
^ permalink raw reply
* Re: [PATCH RFC] act_cpu: packet distributing
From: Eric Dumazet @ 2010-07-14 3:41 UTC (permalink / raw)
To: Changli Gao
Cc: Jamal Hadi Salim, David S. Miller, Patrick McHardy, Tom Herbert,
netdev
In-Reply-To: <1279077475-2956-1-git-send-email-xiaosuo@gmail.com>
Le mercredi 14 juillet 2010 à 11:17 +0800, Changli Gao a écrit :
> I want to know if I can assign the sk to skb as nf_tproxy_core does to avoid
> the duplicate search later. Thanks.
>
I suggest we first correct bugs before adding new features.
For me, tproxy is a high suspect at this moment, I would not use it on
production machine.
> act_cpu: packet distributing
>
> This TC action can be used to redirect packets to the CPU:
> * specified by the cpuid option
> * specified by the class minor ID obtained previously
> * on which the corresponding application runs
>
> It supports the similar functions of RPS and RFS, but is more flexible.
>
Thins kind of claims is disgusting.
No documentation, I have no idea how you setup the thing.
RPS still misses documentation, but activating it is easy.
> Signed-off-by: Changli Gao <xiaosuo@gmail.com>
> ----
> include/linux/netdevice.h | 2
> include/linux/tc_act/tc_cpu.h | 31 +++++
> include/net/sock.h | 24 +++
> include/net/tc_act/tc_cpu.h | 18 ++
> net/core/dev.c | 4
> net/core/sock.c | 1
> net/sched/Kconfig | 12 +
> net/sched/Makefile | 1
> net/sched/act_cpu.c | 260 ++++++++++++++++++++++++++++++++++++++++++
> 9 files changed, 350 insertions(+), 3 deletions(-)
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index c4fedf0..318d422 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -1435,6 +1435,8 @@ static inline void input_queue_tail_incr_save(struct softnet_data *sd,
>
> DECLARE_PER_CPU_ALIGNED(struct softnet_data, softnet_data);
>
> +int enqueue_to_backlog(struct sk_buff *skb, int cpu, unsigned int *qtail);
> +
> #define HAVE_NETIF_QUEUE
>
> extern void __netif_schedule(struct Qdisc *q);
> diff --git a/include/linux/tc_act/tc_cpu.h b/include/linux/tc_act/tc_cpu.h
> new file mode 100644
> index 0000000..2704607
> --- /dev/null
> +++ b/include/linux/tc_act/tc_cpu.h
> @@ -0,0 +1,31 @@
> +#ifndef __LINUX_TC_CPU_H
> +#define __LINUX_TC_CPU_H
> +
> +#include <linux/pkt_cls.h>
> +#include <linux/types.h>
> +
> +#define TCA_ACT_CPU 12
> +
> +enum {
> + TCA_CPU_UNSPEC,
> + TCA_CPU_PARMS,
> + TCA_CPU_TM,
> + __TCA_CPU_MAX
> +};
> +#define TCA_CPU_MAX (__TCA_CPU_MAX - 1)
> +
> +enum {
> + TCA_CPU_TYPE_MAP,
> + TCA_CPU_TYPE_CPUID,
> + TCA_CPU_TYPE_SOCKET,
> + __TCA_CPU_TYPE_MAX
> +};
> +#define TCA_CPU_TYPE_MAX (__TCA_CPU_TYPE_MAX - 1)
> +
> +struct tc_cpu {
> + tc_gen;
> + __u32 type;
> + __u32 value;
> +};
> +
> +#endif /* __LINUX_TC_CPU_H */
> diff --git a/include/net/sock.h b/include/net/sock.h
> index 3100e71..7913158 100644
> --- a/include/net/sock.h
> +++ b/include/net/sock.h
> @@ -200,6 +200,7 @@ struct sock_common {
> * @sk_rcvtimeo: %SO_RCVTIMEO setting
> * @sk_sndtimeo: %SO_SNDTIMEO setting
> * @sk_rxhash: flow hash received from netif layer
> + * @sk_cpu: the CPU on which the corresponding process works.
> * @sk_filter: socket filtering instructions
> * @sk_protinfo: private area, net family specific, when not using slab
> * @sk_timer: sock cleanup timer
> @@ -284,6 +285,9 @@ struct sock {
> #ifdef CONFIG_RPS
> __u32 sk_rxhash;
> #endif
> +#if defined(CONFIG_NET_ACT_CPU) || defined(CONFIG_NET_ACT_CPU_MODULE)
> + int sk_cpu;
> +#endif
> unsigned long sk_flags;
> unsigned long sk_lingertime;
> struct sk_buff_head sk_error_queue;
> @@ -639,7 +643,24 @@ static inline int sk_backlog_rcv(struct sock *sk, struct sk_buff *skb)
> return sk->sk_backlog_rcv(sk, skb);
> }
>
> -static inline void sock_rps_record_flow(const struct sock *sk)
> +static inline void sock_reset_cpu(struct sock *sk)
> +{
> +#if defined(CONFIG_NET_ACT_CPU) || defined(CONFIG_NET_ACT_CPU_MODULE)
> + sk->sk_cpu = nr_cpumask_bits;
> +#endif
> +}
> +
> +static inline void sock_save_cpu(struct sock *sk)
> +{
> +#if defined(CONFIG_NET_ACT_CPU) || defined(CONFIG_NET_ACT_CPU_MODULE)
> + int cpu = get_cpu();
> + if (sk->sk_cpu != cpu)
> + sk->sk_cpu = cpu;
> + put_cpu();
sk->sk_cpu = raw_smp_processor_id();
> +#endif
> +}
> +
> +static inline void sock_rps_record_flow(struct sock *sk)
> {
> #ifdef CONFIG_RPS
> struct rps_sock_flow_table *sock_flow_table;
> @@ -649,6 +670,7 @@ static inline void sock_rps_record_flow(const struct sock *sk)
> rps_record_sock_flow(sock_flow_table, sk->sk_rxhash);
> rcu_read_unlock();
> #endif
> + sock_save_cpu(sk);
> }
>
> static inline void sock_rps_reset_flow(const struct sock *sk)
> diff --git a/include/net/tc_act/tc_cpu.h b/include/net/tc_act/tc_cpu.h
> new file mode 100644
> index 0000000..0504bf0
> --- /dev/null
> +++ b/include/net/tc_act/tc_cpu.h
> @@ -0,0 +1,18 @@
> +#ifndef __NET_TC_CPU_H
> +#define __NET_TC_CPU_H
> +
> +#include <linux/types.h>
> +#include <net/act_api.h>
> +
> +struct tcf_cpu {
> + struct tcf_common common;
> + u32 type;
> + u32 value;
> +};
> +
> +static inline struct tcf_cpu *to_tcf_cpu(struct tcf_common *pc)
> +{
> + return container_of(pc, struct tcf_cpu, common);
> +}
> +
> +#endif /* __NET_TC_CPU_H */
> diff --git a/net/core/dev.c b/net/core/dev.c
> index e2b9fa2..45e8a21 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -2443,8 +2443,7 @@ static int rps_ipi_queued(struct softnet_data *sd)
> * enqueue_to_backlog is called to queue an skb to a per CPU backlog
> * queue (may be a remote CPU queue).
> */
> -static int enqueue_to_backlog(struct sk_buff *skb, int cpu,
> - unsigned int *qtail)
> +int enqueue_to_backlog(struct sk_buff *skb, int cpu, unsigned int *qtail)
> {
> struct softnet_data *sd;
> unsigned long flags;
> @@ -2482,6 +2481,7 @@ enqueue:
> kfree_skb(skb);
> return NET_RX_DROP;
> }
> +EXPORT_SYMBOL(enqueue_to_backlog);
>
> /**
> * netif_rx - post buffer to the network code
> diff --git a/net/core/sock.c b/net/core/sock.c
> index 363bc26..7a71e76 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
> @@ -1045,6 +1045,7 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
> if (!try_module_get(prot->owner))
> goto out_free_sec;
> sk_tx_queue_clear(sk);
> + sock_reset_cpu(sk);
> }
>
> return sk;
> diff --git a/net/sched/Kconfig b/net/sched/Kconfig
> index 2f691fb..a826758 100644
> --- a/net/sched/Kconfig
> +++ b/net/sched/Kconfig
> @@ -427,6 +427,18 @@ config NET_CLS_ACT
> A recent version of the iproute2 package is required to use
> extended matches.
>
> +config NET_ACT_CPU
> + tristate "Packet distributing"
> + depends on NET_CLS_ACT
> + depends on RPS
> + ---help---
> + Say Y here to do packets distributing. With it, you can distribute
> + the packets among the CPUs on the system in any way as you like. It
> + only works in ingress.
> +
> + To compile this code as a module, choose M here: the
> + module will be called act_cpu.
> +
> config NET_ACT_POLICE
> tristate "Traffic Policing"
> depends on NET_CLS_ACT
> diff --git a/net/sched/Makefile b/net/sched/Makefile
> index f14e71b..a9e0b96 100644
> --- a/net/sched/Makefile
> +++ b/net/sched/Makefile
> @@ -7,6 +7,7 @@ obj-y := sch_generic.o sch_mq.o
> obj-$(CONFIG_NET_SCHED) += sch_api.o sch_blackhole.o
> obj-$(CONFIG_NET_CLS) += cls_api.o
> obj-$(CONFIG_NET_CLS_ACT) += act_api.o
> +obj-$(CONFIG_NET_ACT_CPU) += act_cpu.o
> obj-$(CONFIG_NET_ACT_POLICE) += act_police.o
> obj-$(CONFIG_NET_ACT_GACT) += act_gact.o
> obj-$(CONFIG_NET_ACT_MIRRED) += act_mirred.o
> diff --git a/net/sched/act_cpu.c b/net/sched/act_cpu.c
> new file mode 100644
> index 0000000..6b7d7fc
> --- /dev/null
> +++ b/net/sched/act_cpu.c
> @@ -0,0 +1,260 @@
> +/*
> + * Packet distributing actions
> + *
> + * Copyright (c) 2010- Changli Gao <xiaosuo@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the Free
> + * Software Foundation; either version 2 of the License, or (at your option)
> + * any later version.
> + */
> +
> +#include <linux/types.h>
> +#include <linux/kernel.h>
> +#include <linux/string.h>
> +#include <linux/errno.h>
> +#include <linux/skbuff.h>
> +#include <linux/rtnetlink.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/gfp.h>
> +#include <net/net_namespace.h>
> +#include <net/netlink.h>
> +#include <net/pkt_sched.h>
> +#include <net/tcp.h>
> +#include <net/udp.h>
> +#include <linux/tc_act/tc_cpu.h>
> +#include <net/tc_act/tc_cpu.h>
> +
> +#define CPU_TAB_MASK 15
> +static struct tcf_common *tcf_cpu_ht[CPU_TAB_MASK + 1];
> +static u32 cpu_idx_gen;
> +static DEFINE_RWLOCK(cpu_lock);
> +
> +static struct tcf_hashinfo cpu_hash_info = {
> + .htab = tcf_cpu_ht,
> + .hmask = CPU_TAB_MASK,
> + .lock = &cpu_lock
> +};
> +
> +static const struct nla_policy cpu_policy[TCA_CPU_MAX + 1] = {
> + [TCA_CPU_PARMS] = { .len = sizeof(struct tc_cpu) },
> +};
> +
> +static int tcf_cpu_init(struct nlattr *nla, struct nlattr *est,
> + struct tc_action *a, int ovr, int bind)
> +{
> + struct nlattr *tb[TCA_CPU_MAX + 1];
> + struct tc_cpu *parm;
> + struct tcf_cpu *p;
> + struct tcf_common *pc;
> + int ret;
> +
> + if (nla == NULL)
> + return -EINVAL;
> + ret = nla_parse_nested(tb, TCA_CPU_MAX, nla, cpu_policy);
> + if (ret < 0)
> + return ret;
> + if (tb[TCA_CPU_PARMS] == NULL)
> + return -EINVAL;
> + parm = nla_data(tb[TCA_CPU_PARMS]);
> + if (parm->type > TCA_CPU_TYPE_MAX || parm->action != TC_ACT_STOLEN)
> + return -EINVAL;
> +
> + pc = tcf_hash_check(parm->index, a, bind, &cpu_hash_info);
> + if (!pc) {
> + pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind,
> + &cpu_idx_gen, &cpu_hash_info);
> + if (IS_ERR(pc))
> + return PTR_ERR(pc);
> + ret = ACT_P_CREATED;
> + } else {
> + if (!ovr) {
> + tcf_hash_release(pc, bind, &cpu_hash_info);
> + return -EEXIST;
> + }
> + ret = 0;
> + }
> + p = to_tcf_cpu(pc);
> +
> + spin_lock_bh(&p->tcf_lock);
> + p->type = parm->type;
> + p->value = parm->value;
> + p->tcf_action = parm->action;
> + spin_unlock_bh(&p->tcf_lock);
> +
> + if (ret == ACT_P_CREATED)
> + tcf_hash_insert(pc, &cpu_hash_info);
> +
> + return ret;
> +}
> +
> +static int tcf_cpu_cleanup(struct tc_action *a, int bind)
> +{
> + struct tcf_cpu *p = a->priv;
> +
> + return tcf_hash_release(&p->common, bind, &cpu_hash_info);
> +}
> +
> +static int tcf_cpu_from_sock(struct sk_buff *skb)
> +{
> + struct iphdr *iph;
> + struct sock *sk;
> + struct {
> + __be16 source, dest;
> + } *ports;
> + int cpu;
> +
> + if (skb->dev == NULL || skb->protocol != __constant_htons(ETH_P_IP))
> + goto err;
> + if (!pskb_may_pull(skb, sizeof(*iph)))
> + goto err;
> + iph = (struct iphdr *) skb->data;
> + if (!pskb_may_pull(skb, iph->ihl * 4 + 4))
> + goto err;
> + ports = (void *) (skb->data + iph->ihl * 4);
Why doing the search again, in case skb->sk already set by another
module before you, like tproxy ?
> + switch (iph->protocol) {
> + case IPPROTO_TCP:
> + sk = __inet_lookup(dev_net(skb->dev), &tcp_hashinfo, iph->saddr,
> + ports->source, iph->daddr, ports->dest,
> + skb->dev->ifindex);
> + break;
> + case IPPROTO_UDP:
> + sk = udp4_lib_lookup(dev_net(skb->dev), iph->saddr,
> + ports->source, iph->daddr, ports->dest,
> + skb->dev->ifindex);
> + break;
> + default:
> + goto err;
> + }
> +
> + if (!sk)
> + goto err;
> + cpu = sk->sk_cpu;
> + if (sk->sk_protocol == IPPROTO_TCP && sk->sk_state == TCP_TIME_WAIT)
> + inet_twsk_put(inet_twsk(sk));
> + else
> + sock_put(sk);
> +
> + return cpu;
> +
> +err:
> + return smp_processor_id();
> +}
> +
> +static int tcf_cpu(struct sk_buff *skb, struct tc_action *a,
> + struct tcf_result *res)
> +{
> + struct tcf_cpu *p = a->priv;
> + u32 type;
> + u32 value;
> + int cpu, action;
> + struct sk_buff *nskb;
> + unsigned int qtail;
> +
> + spin_lock(&p->tcf_lock);
Ok, the big lock...
We have a lockless TCP/UDP input path, and this modules adds a lock
again.
> + p->tcf_tm.lastuse = jiffies;
> + p->tcf_bstats.bytes += qdisc_pkt_len(skb);
> + p->tcf_bstats.packets++;
> + type = p->type;
> + value = p->value;
> + action = p->tcf_action;
> + spin_unlock(&p->tcf_lock);
> +
Please change all this crap (legacy crap, copied from other tc
modules), by modern one, using RCU and no locking in hot path.
^ permalink raw reply
* Re: [PATCH] tproxy: nf_tproxy_assign_sock() can handle tw sockets
From: Eric Dumazet @ 2010-07-14 3:43 UTC (permalink / raw)
To: Felipe W Damasio
Cc: Avi Kivity, David Miller, Patrick McHardy, linux-kernel, netdev
In-Reply-To: <AANLkTikkcaionMp3SJLgo3JmCjxQ7rPZv3-3_RbxCx_4@mail.gmail.com>
Le mercredi 14 juillet 2010 à 00:27 -0300, Felipe W Damasio a écrit :
> Hi Mr. Dumazet,
>
> 2010/7/14 Eric Dumazet <eric.dumazet@gmail.com>:
> > RDX being the sk pointer (and sk+0x38 contains the corrupted "sk_prot" value)
> > , we notice RBP contains same "sk" value + 0x200000 (2 Mbytes).
> >
> > (same remark on your initial bug report)
> >
> > Could you enable CONFIG_FRAME_POINTER=y in your config ?
>
> I can, but my bosses will kick my ass if I bring down the ISP again :)
>
I have no guarantee at all, even if we find the bug.
> If you think it's the only way to find the problem I'll tell them that
> I need to do it. In this case, please tell me what other config
> options/tools I can use to get as much info as possible...since I'll
> probably be able to test this only once more on the production
> environment for debugging purposes.
>
You really should try to setup a lab to trigger the bug, and not doing
experiments on production :)
^ permalink raw reply
* Re: [PATCH] tproxy: nf_tproxy_assign_sock() can handle tw sockets
From: Felipe W Damasio @ 2010-07-14 3:51 UTC (permalink / raw)
To: Eric Dumazet
Cc: Avi Kivity, David Miller, Patrick McHardy, linux-kernel, netdev
In-Reply-To: <1279078985.2444.105.camel@edumazet-laptop>
Hi,
2010/7/14 Eric Dumazet <eric.dumazet@gmail.com>:
>> I can, but my bosses will kick my ass if I bring down the ISP again :)
>
> I have no guarantee at all, even if we find the bug.
Ok :-)
>> If you think it's the only way to find the problem I'll tell them that
>> I need to do it. In this case, please tell me what other config
>> options/tools I can use to get as much info as possible...since I'll
>> probably be able to test this only once more on the production
>> environment for debugging purposes.
>
> You really should try to setup a lab to trigger the bug, and not doing
> experiments on production :)
Right, I'm trying.
The thing is: The ISP is a 200Mbps network with 10,000 users. The
first time it took around 2 minutes to trigger the bug. The second
time it took around 17 minutes.
So I *think* it's some TCP flag with some weird content...but I can't
find out what it is so I can trigger it on the lab.
So my only guess is to enable every possible debug flag I can think of
to track the bug down on the production environment. Any hints here
would be appreciated :)
Cheers,
Felipe Damasio
^ permalink raw reply
* Re: [PATCH RFC] act_cpu: packet distributing
From: Changli Gao @ 2010-07-14 4:17 UTC (permalink / raw)
To: Eric Dumazet
Cc: Jamal Hadi Salim, David S. Miller, Patrick McHardy, Tom Herbert,
netdev
In-Reply-To: <1279078875.2444.103.camel@edumazet-laptop>
On Wed, Jul 14, 2010 at 11:41 AM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> Le mercredi 14 juillet 2010 à 11:17 +0800, Changli Gao a écrit :
>> I want to know if I can assign the sk to skb as nf_tproxy_core does to avoid
>> the duplicate search later. Thanks.
>>
>
> I suggest we first correct bugs before adding new features.
>
> For me, tproxy is a high suspect at this moment, I would not use it on
> production machine.
>
>> act_cpu: packet distributing
>>
>> This TC action can be used to redirect packets to the CPU:
>> * specified by the cpuid option
>> * specified by the class minor ID obtained previously
>> * on which the corresponding application runs
>>
>> It supports the similar functions of RPS and RFS, but is more flexible.
>>
>
> Thins kind of claims is disgusting.
>
> No documentation, I have no idea how you setup the thing.
for example:
redirect packets to the CPU on which the corresponding application runs
tc qdisc add dev eth0 ingress
tc filter add dev eth0 parent ffff:0 protocol ip basic action cpu socket
redirect packets to special CPU.
tc filter add dev eth0 parent ffff:0 protocol ip basic action cpu cpuid 1
sport hash packet distributing among CPU 0-1.
tc filter add dev eth0 parent ffff:0 protocol ip handle 1 flow hash
keys proto-src divisor 2 action cpu map 1
>> +static inline void sock_save_cpu(struct sock *sk)
>> +{
>> +#if defined(CONFIG_NET_ACT_CPU) || defined(CONFIG_NET_ACT_CPU_MODULE)
>> + int cpu = get_cpu();
>> + if (sk->sk_cpu != cpu)
>> + sk->sk_cpu = cpu;
>> + put_cpu();
>
> sk->sk_cpu = raw_smp_processor_id();
Thanks.
>
> Why doing the search again, in case skb->sk already set by another
> module before you, like tproxy ?
>
Although it is unlikely skb->sk is non null, as tc is before
netfilter, I will handle this case. Thanks.
>> +static int tcf_cpu(struct sk_buff *skb, struct tc_action *a,
>> + struct tcf_result *res)
>> +{
>> + struct tcf_cpu *p = a->priv;
>> + u32 type;
>> + u32 value;
>> + int cpu, action;
>> + struct sk_buff *nskb;
>> + unsigned int qtail;
>> +
>> + spin_lock(&p->tcf_lock);
>
> Ok, the big lock...
>
> We have a lockless TCP/UDP input path, and this modules adds a lock
> again.
>
>> + p->tcf_tm.lastuse = jiffies;
>> + p->tcf_bstats.bytes += qdisc_pkt_len(skb);
>> + p->tcf_bstats.packets++;
>> + type = p->type;
>> + value = p->value;
>> + action = p->tcf_action;
>> + spin_unlock(&p->tcf_lock);
>> +
>
> Please change all this crap (legacy crap, copied from other tc
> modules), by modern one, using RCU and no locking in hot path.
>
Thanks, I'll try. It is a write critical section, and for me it is
difficult to convert this lock to RCU. Could you show me some
examples?
Thanks.
--
Regards,
Changli Gao(xiaosuo@gmail.com)
^ permalink raw reply
* Re: [PATCH RFC] act_cpu: packet distributing
From: Eric Dumazet @ 2010-07-14 4:30 UTC (permalink / raw)
To: Changli Gao
Cc: Jamal Hadi Salim, David S. Miller, Patrick McHardy, Tom Herbert,
netdev
In-Reply-To: <AANLkTimPmXWyAspJqnya7aM_vDRNzDdJJf2bl7CYrAXN@mail.gmail.com>
Le mercredi 14 juillet 2010 à 12:17 +0800, Changli Gao a écrit :
> On Wed, Jul 14, 2010 at 11:41 AM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> >
> > Why doing the search again, in case skb->sk already set by another
> > module before you, like tproxy ?
> >
>
> Although it is unlikely skb->sk is non null, as tc is before
> netfilter, I will handle this case. Thanks.
>
In this case, provide the skb->sk already set case on tproxy, not in
act_cpu. But doing it on both will give a hint for future modules...
> >> +static int tcf_cpu(struct sk_buff *skb, struct tc_action *a,
> >> + struct tcf_result *res)
> >> +{
> >> + struct tcf_cpu *p = a->priv;
> >> + u32 type;
> >> + u32 value;
> >> + int cpu, action;
> >> + struct sk_buff *nskb;
> >> + unsigned int qtail;
> >> +
> >> + spin_lock(&p->tcf_lock);
> >
> > Ok, the big lock...
> >
> > We have a lockless TCP/UDP input path, and this modules adds a lock
> > again.
> >
> >> + p->tcf_tm.lastuse = jiffies;
> >> + p->tcf_bstats.bytes += qdisc_pkt_len(skb);
> >> + p->tcf_bstats.packets++;
> >> + type = p->type;
> >> + value = p->value;
> >> + action = p->tcf_action;
> >> + spin_unlock(&p->tcf_lock);
> >> +
> >
> > Please change all this crap (legacy crap, copied from other tc
> > modules), by modern one, using RCU and no locking in hot path.
> >
>
> Thanks, I'll try. It is a write critical section, and for me it is
> difficult to convert this lock to RCU. Could you show me some
> examples?
We can convert bytes/packets stats to percpu stats for example.
That might need a generic change.
Then, a normal RCU protection should be enough to fetch
type/value/action fields.
^ permalink raw reply
* [PATCHv2 NEXT 0/5]qlcnic: aer state
From: amit.salecha @ 2010-07-14 5:54 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman
Hi
Resending series of 5 to support aer and minor fixes.
Please ignore earlier patches, this fixes minor sparse warning
and version update.
Please apply them on net-next.
-Amit
^ permalink raw reply
* [PATCHv2 NEXT 1/5] qlcnic: fix pause params setting
From: amit.salecha @ 2010-07-14 5:54 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Rajesh Borundia, Amit Kumar Salecha
In-Reply-To: <1279086893-22523-1-git-send-email-amit.salecha@qlogic.com>
From: Rajesh Borundia <rajesh.borundia@qlogic.com>
Turning off rx pause param and autoneg param is not supported so
return error in that case.
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_ethtool.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index baf5a52..8599993 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -578,8 +578,13 @@ qlcnic_set_pauseparam(struct net_device *netdev,
}
QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val);
} else if (adapter->ahw.port_type == QLCNIC_XGBE) {
+
+ if (!pause->rx_pause || pause->autoneg)
+ return -EOPNOTSUPP;
+
if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
return -EIO;
+
val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
if (port == 0) {
if (pause->tx_pause)
--
1.6.0.2
^ permalink raw reply related
* [PATCHv2 NEXT 3/5] qlcnic: fix netdev notifier in error path
From: amit.salecha @ 2010-07-14 5:54 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Amit Kumar Salecha
In-Reply-To: <1279086893-22523-1-git-send-email-amit.salecha@qlogic.com>
From: Amit Kumar Salecha <amit.salecha@qlogic.com>
netdev notifier are not unregistered if pci_register_driver fails.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index d511fd1..c8275f0 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -3451,6 +3451,7 @@ static struct pci_driver qlcnic_driver = {
static int __init qlcnic_init_module(void)
{
+ int ret;
printk(KERN_INFO "%s\n", qlcnic_driver_string);
@@ -3459,8 +3460,15 @@ static int __init qlcnic_init_module(void)
register_inetaddr_notifier(&qlcnic_inetaddr_cb);
#endif
+ ret = pci_register_driver(&qlcnic_driver);
+ if (ret) {
+#ifdef CONFIG_INET
+ unregister_inetaddr_notifier(&qlcnic_inetaddr_cb);
+ unregister_netdevice_notifier(&qlcnic_netdev_cb);
+#endif
+ }
- return pci_register_driver(&qlcnic_driver);
+ return ret;
}
module_init(qlcnic_init_module);
--
1.6.0.2
^ permalink raw reply related
* [PATCHv2 NEXT 4/5] qlcnic: aer support
From: amit.salecha @ 2010-07-14 5:54 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Sucheta Chakraborty, Amit Kumar Salecha
In-Reply-To: <1279086893-22523-1-git-send-email-amit.salecha@qlogic.com>
From: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Pci error recovery support added.
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 1 +
drivers/net/qlcnic/qlcnic_main.c | 137 +++++++++++++++++++++++++++++++++++++-
2 files changed, 137 insertions(+), 1 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 02a50e6..0644642 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -911,6 +911,7 @@ struct qlcnic_mac_req {
#define __QLCNIC_DEV_UP 1
#define __QLCNIC_RESETTING 2
#define __QLCNIC_START_FW 4
+#define __QLCNIC_AER 5
#define QLCNIC_INTERRUPT_TEST 1
#define QLCNIC_LOOPBACK_TEST 2
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index c8275f0..462cb6b 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -34,6 +34,7 @@
#include <linux/ipv6.h>
#include <linux/inetdevice.h>
#include <linux/sysfs.h>
+#include <linux/aer.h>
MODULE_DESCRIPTION("QLogic 1/10 GbE Converged/Intelligent Ethernet Driver");
MODULE_LICENSE("GPL");
@@ -1306,6 +1307,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_disable_pdev;
pci_set_master(pdev);
+ pci_enable_pcie_error_reporting(pdev);
netdev = alloc_etherdev(sizeof(struct qlcnic_adapter));
if (!netdev) {
@@ -1437,6 +1439,7 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
qlcnic_release_firmware(adapter);
+ pci_disable_pcie_error_reporting(pdev);
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
@@ -2521,6 +2524,9 @@ static void
qlcnic_schedule_work(struct qlcnic_adapter *adapter,
work_func_t func, int delay)
{
+ if (test_bit(__QLCNIC_AER, &adapter->state))
+ return;
+
INIT_DELAYED_WORK(&adapter->fw_work, func);
schedule_delayed_work(&adapter->fw_work, round_jiffies_relative(delay));
}
@@ -2631,6 +2637,128 @@ reschedule:
qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
}
+static int qlcnic_is_first_func(struct pci_dev *pdev)
+{
+ struct pci_dev *oth_pdev;
+ int val = pdev->devfn;
+
+ while (val-- > 0) {
+ oth_pdev = pci_get_domain_bus_and_slot(pci_domain_nr
+ (pdev->bus), pdev->bus->number,
+ PCI_DEVFN(PCI_SLOT(pdev->devfn), val));
+
+ if (oth_pdev && (oth_pdev->current_state != PCI_D3cold))
+ return 0;
+ }
+ return 1;
+}
+
+static int qlcnic_attach_func(struct pci_dev *pdev)
+{
+ int err, first_func;
+ struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+ struct net_device *netdev = adapter->netdev;
+
+ pdev->error_state = pci_channel_io_normal;
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_set_master(pdev);
+ pci_restore_state(pdev);
+
+ first_func = qlcnic_is_first_func(pdev);
+
+ if (qlcnic_api_lock(adapter))
+ return -EINVAL;
+
+ if (first_func) {
+ adapter->need_fw_reset = 1;
+ set_bit(__QLCNIC_START_FW, &adapter->state);
+ QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
+ QLCDB(adapter, DRV, "Restarting fw\n");
+ }
+ qlcnic_api_unlock(adapter);
+
+ err = adapter->nic_ops->start_firmware(adapter);
+ if (err)
+ return err;
+
+ qlcnic_clr_drv_state(adapter);
+ qlcnic_setup_intr(adapter);
+
+ if (netif_running(netdev)) {
+ err = qlcnic_attach(adapter);
+ if (err) {
+ qlcnic_clr_all_drv_state(adapter);
+ clear_bit(__QLCNIC_AER, &adapter->state);
+ netif_device_attach(netdev);
+ return err;
+ }
+
+ err = qlcnic_up(adapter, netdev);
+ if (err)
+ goto done;
+
+ qlcnic_config_indev_addr(netdev, NETDEV_UP);
+ }
+ done:
+ netif_device_attach(netdev);
+ return err;
+}
+
+static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+ struct net_device *netdev = adapter->netdev;
+
+ if (state == pci_channel_io_perm_failure)
+ return PCI_ERS_RESULT_DISCONNECT;
+
+ if (state == pci_channel_io_normal)
+ return PCI_ERS_RESULT_RECOVERED;
+
+ set_bit(__QLCNIC_AER, &adapter->state);
+ netif_device_detach(netdev);
+
+ cancel_delayed_work_sync(&adapter->fw_work);
+
+ if (netif_running(netdev))
+ qlcnic_down(adapter, netdev);
+
+ qlcnic_detach(adapter);
+ qlcnic_teardown_intr(adapter);
+
+ clear_bit(__QLCNIC_RESETTING, &adapter->state);
+
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t qlcnic_io_slot_reset(struct pci_dev *pdev)
+{
+ return qlcnic_attach_func(pdev) ? PCI_ERS_RESULT_DISCONNECT :
+ PCI_ERS_RESULT_RECOVERED;
+}
+
+static void qlcnic_io_resume(struct pci_dev *pdev)
+{
+ struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+
+ pci_cleanup_aer_uncorrect_error_status(pdev);
+
+ if ((QLCRD32(adapter, QLCNIC_CRB_DEV_STATE) == QLCNIC_DEV_READY) &&
+ (test_and_clear_bit(__QLCNIC_AER, &adapter->state)))
+ qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
+ FW_POLL_DELAY);
+}
+
+
static int
qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
{
@@ -3436,6 +3564,11 @@ static void
qlcnic_config_indev_addr(struct net_device *dev, unsigned long event)
{ }
#endif
+static struct pci_error_handlers qlcnic_err_handler = {
+ .error_detected = qlcnic_io_error_detected,
+ .slot_reset = qlcnic_io_slot_reset,
+ .resume = qlcnic_io_resume,
+};
static struct pci_driver qlcnic_driver = {
.name = qlcnic_driver_name,
@@ -3446,7 +3579,9 @@ static struct pci_driver qlcnic_driver = {
.suspend = qlcnic_suspend,
.resume = qlcnic_resume,
#endif
- .shutdown = qlcnic_shutdown
+ .shutdown = qlcnic_shutdown,
+ .err_handler = &qlcnic_err_handler
+
};
static int __init qlcnic_init_module(void)
--
1.6.0.2
^ permalink raw reply related
* [PATCHv2 NEXT 2/5] qlcnic: disable tx timeout recovery
From: amit.salecha @ 2010-07-14 5:54 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Amit Kumar Salecha
In-Reply-To: <1279086893-22523-1-git-send-email-amit.salecha@qlogic.com>
From: Amit Kumar Salecha <amit.salecha@qlogic.com>
Disable tx timeout recovery, if auto_fw_reset is disable
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 4d18313..d511fd1 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -2581,7 +2581,8 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
if (adapter->need_fw_reset)
goto detach;
- if (adapter->reset_context) {
+ if (adapter->reset_context &&
+ auto_fw_reset == AUTO_FW_RESET_ENABLED) {
qlcnic_reset_hw_context(adapter);
adapter->netdev->trans_start = jiffies;
}
@@ -2594,7 +2595,8 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
qlcnic_dev_request_reset(adapter);
- clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
+ if ((auto_fw_reset == AUTO_FW_RESET_ENABLED))
+ clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
dev_info(&netdev->dev, "firmware hang detected\n");
--
1.6.0.2
^ permalink raw reply related
* [PATCHv2 NEXT 5/5] qlcnic: restore NPAR config data after recovery
From: amit.salecha @ 2010-07-14 5:54 UTC (permalink / raw)
To: davem
Cc: netdev, ameen.rahman, Anirban Chakraborty, Rajesh Borundia,
Amit Kumar Salecha
In-Reply-To: <1279086893-22523-1-git-send-email-amit.salecha@qlogic.com>
From: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
o NPAR configuration which is programmed in fw, need to
restore after fw recovery.
o Update version to 5.0.7
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 7 ++-
drivers/net/qlcnic/qlcnic_ctx.c | 2 +
drivers/net/qlcnic/qlcnic_main.c | 86 +++++++++++++++++++++++++++++---------
3 files changed, 72 insertions(+), 23 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 0644642..e189477 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -51,8 +51,8 @@
#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 0
-#define _QLCNIC_LINUX_SUBVERSION 6
-#define QLCNIC_LINUX_VERSIONID "5.0.6"
+#define _QLCNIC_LINUX_SUBVERSION 7
+#define QLCNIC_LINUX_VERSIONID "5.0.7"
#define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c))
@@ -949,7 +949,6 @@ struct qlcnic_adapter {
u8 has_link_events;
u8 fw_type;
u16 tx_context_id;
- u16 mtu;
u16 is_up;
u16 link_speed;
@@ -1044,6 +1043,8 @@ struct qlcnic_pci_info {
struct qlcnic_npar_info {
u16 vlan_id;
+ u16 min_bw;
+ u16 max_bw;
u8 phy_port;
u8 type;
u8 active;
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index cdd44b4..cc5d861 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -636,6 +636,8 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
QLCNIC_CDRP_CMD_GET_NIC_INFO);
if (err == QLCNIC_RCODE_SUCCESS) {
+ npar_info->pci_func = le16_to_cpu(nic_info->pci_func);
+ npar_info->op_mode = le16_to_cpu(nic_info->op_mode);
npar_info->phys_port = le16_to_cpu(nic_info->phys_port);
npar_info->switch_mode = le16_to_cpu(nic_info->switch_mode);
npar_info->max_tx_ques = le16_to_cpu(nic_info->max_tx_ques);
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 462cb6b..dc0b22b 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -507,6 +507,8 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
adapter->npars[pfn].type = pci_info[i].type;
adapter->npars[pfn].phy_port = pci_info[i].default_port;
adapter->npars[pfn].mac_learning = DEFAULT_MAC_LEARN;
+ adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw;
+ adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw;
}
for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
@@ -771,6 +773,50 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
}
static int
+qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
+{
+ int i, err = 0;
+ struct qlcnic_npar_info *npar;
+ struct qlcnic_info nic_info;
+
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)
+ || !adapter->need_fw_reset)
+ return 0;
+
+ if (adapter->op_mode == QLCNIC_MGMT_FUNC) {
+ /* Set the NPAR config data after FW reset */
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ npar = &adapter->npars[i];
+ if (npar->type != QLCNIC_TYPE_NIC)
+ continue;
+ err = qlcnic_get_nic_info(adapter, &nic_info, i);
+ if (err)
+ goto err_out;
+ nic_info.min_tx_bw = npar->min_bw;
+ nic_info.max_tx_bw = npar->max_bw;
+ err = qlcnic_set_nic_info(adapter, &nic_info);
+ if (err)
+ goto err_out;
+
+ if (npar->enable_pm) {
+ err = qlcnic_config_port_mirroring(adapter,
+ npar->dest_npar, 1, i);
+ if (err)
+ goto err_out;
+
+ }
+ npar->mac_learning = DEFAULT_MAC_LEARN;
+ npar->host_vlan_tag = 0;
+ npar->promisc_mode = 0;
+ npar->discard_tagged = 0;
+ npar->vlan_id = 0;
+ }
+ }
+err_out:
+ return err;
+}
+
+static int
qlcnic_start_firmware(struct qlcnic_adapter *adapter)
{
int val, err, first_boot;
@@ -834,10 +880,9 @@ wait_init:
qlcnic_idc_debug_info(adapter, 1);
qlcnic_check_options(adapter);
-
- if (adapter->flags & QLCNIC_ESWITCH_ENABLED &&
- adapter->op_mode != QLCNIC_NON_PRIV_FUNC)
- qlcnic_dev_set_npar_ready(adapter);
+ if (qlcnic_reset_npar_config(adapter))
+ goto err_out;
+ qlcnic_dev_set_npar_ready(adapter);
adapter->need_fw_reset = 0;
@@ -2486,6 +2531,7 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
{
u32 state;
+ adapter->need_fw_reset = 1;
if (qlcnic_api_lock(adapter))
return;
@@ -2506,6 +2552,9 @@ qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter)
{
u32 state;
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
+ adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
+ return;
if (qlcnic_api_lock(adapter))
return;
@@ -3019,7 +3068,7 @@ static struct bin_attribute bin_attr_mem = {
.write = qlcnic_sysfs_write_mem,
};
-int
+static int
validate_pm_config(struct qlcnic_adapter *adapter,
struct qlcnic_pm_func_cfg *pm_cfg, int count)
{
@@ -3118,7 +3167,7 @@ qlcnic_sysfs_read_pm_config(struct file *filp, struct kobject *kobj,
return size;
}
-int
+static int
validate_esw_config(struct qlcnic_adapter *adapter,
struct qlcnic_esw_func_cfg *esw_cfg, int count)
{
@@ -3154,9 +3203,8 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
struct device *dev = container_of(kobj, struct device, kobj);
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
struct qlcnic_esw_func_cfg *esw_cfg;
- u8 id, discard_tagged, promsc_mode, mac_learn;
- u8 vlan_tagging, pci_func, vlan_id;
int count, rem, i, ret;
+ u8 id, pci_func;
count = size / sizeof(struct qlcnic_esw_func_cfg);
rem = size % sizeof(struct qlcnic_esw_func_cfg);
@@ -3171,17 +3219,13 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
for (i = 0; i < count; i++) {
pci_func = esw_cfg[i].pci_func;
id = adapter->npars[pci_func].phy_port;
- vlan_tagging = esw_cfg[i].host_vlan_tag;
- promsc_mode = esw_cfg[i].promisc_mode;
- mac_learn = esw_cfg[i].mac_learning;
- vlan_id = esw_cfg[i].vlan_id;
- discard_tagged = esw_cfg[i].discard_tagged;
- ret = qlcnic_config_switch_port(adapter, id, vlan_tagging,
- discard_tagged,
- promsc_mode,
- mac_learn,
- pci_func,
- vlan_id);
+ ret = qlcnic_config_switch_port(adapter, id,
+ esw_cfg[i].host_vlan_tag,
+ esw_cfg[i].discard_tagged,
+ esw_cfg[i].promisc_mode,
+ esw_cfg[i].mac_learning,
+ esw_cfg[i].pci_func,
+ esw_cfg[i].vlan_id);
if (ret)
return ret;
}
@@ -3227,7 +3271,7 @@ qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj,
return size;
}
-int
+static int
validate_npar_config(struct qlcnic_adapter *adapter,
struct qlcnic_npar_func_cfg *np_cfg, int count)
{
@@ -3282,6 +3326,8 @@ qlcnic_sysfs_write_npar_config(struct file *file, struct kobject *kobj,
ret = qlcnic_set_nic_info(adapter, &nic_info);
if (ret)
return ret;
+ adapter->npars[i].min_bw = nic_info.min_tx_bw;
+ adapter->npars[i].max_bw = nic_info.max_tx_bw;
}
return size;
--
1.6.0.2
^ permalink raw reply related
* Re: [PATCHv2 NEXT 1/5] qlcnic: fix pause params setting
From: David Miller @ 2010-07-14 6:09 UTC (permalink / raw)
To: amit.salecha; +Cc: netdev, ameen.rahman, rajesh.borundia
In-Reply-To: <1279086893-22523-2-git-send-email-amit.salecha@qlogic.com>
From: amit.salecha@qlogic.com
Date: Tue, 13 Jul 2010 22:54:49 -0700
> From: Rajesh Borundia <rajesh.borundia@qlogic.com>
>
> Turning off rx pause param and autoneg param is not supported so
> return error in that case.
>
> Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
> Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
> ---
> drivers/net/qlcnic/qlcnic_ethtool.c | 5 +++++
> 1 files changed, 5 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
> index baf5a52..8599993 100644
> --- a/drivers/net/qlcnic/qlcnic_ethtool.c
> +++ b/drivers/net/qlcnic/qlcnic_ethtool.c
> @@ -578,8 +578,13 @@ qlcnic_set_pauseparam(struct net_device *netdev,
> }
> QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val);
> } else if (adapter->ahw.port_type == QLCNIC_XGBE) {
> +
> + if (!pause->rx_pause || pause->autoneg)
> + return -EOPNOTSUPP;
There is no reason to add an empty line at the beginning of this
code block, please remove it.
^ permalink raw reply
* Re: [PATCHv2 NEXT 2/5] qlcnic: disable tx timeout recovery
From: David Miller @ 2010-07-14 6:09 UTC (permalink / raw)
To: amit.salecha; +Cc: netdev, ameen.rahman
In-Reply-To: <1279086893-22523-3-git-send-email-amit.salecha@qlogic.com>
From: amit.salecha@qlogic.com
Date: Tue, 13 Jul 2010 22:54:50 -0700
>
> - if (adapter->reset_context) {
> + if (adapter->reset_context &&
> + auto_fw_reset == AUTO_FW_RESET_ENABLED) {
This new second line is improperly indented.
"auto_fw_reset" should line up with the first character
after the openning "(" on the previous line.
^ permalink raw reply
* Re: [PATCHv2 NEXT 5/5] qlcnic: restore NPAR config data after recovery
From: David Miller @ 2010-07-14 6:10 UTC (permalink / raw)
To: amit.salecha; +Cc: netdev, ameen.rahman, anirban.chakraborty, rajesh.borundia
In-Reply-To: <1279086893-22523-6-git-send-email-amit.salecha@qlogic.com>
From: amit.salecha@qlogic.com
Date: Tue, 13 Jul 2010 22:54:53 -0700
> + if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)
> + || !adapter->need_fw_reset)
> + return 0;
There is more improper indentation of a conditional here.
It should read:
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
!adapter->need_fw_reset)
^ permalink raw reply
* [PATCHv3 NEXT 1/5] qlcnic: fix pause params setting
From: amit.salecha @ 2010-07-14 6:33 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Rajesh Borundia, Amit Kumar Salecha
In-Reply-To: <1279089215-23231-1-git-send-email-amit.salecha@qlogic.com>
From: Rajesh Borundia <rajesh.borundia@qlogic.com>
Turning off rx pause param and autoneg param is not supported so
return error in that case.
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_ethtool.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index baf5a52..7d6558e 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -578,8 +578,12 @@ qlcnic_set_pauseparam(struct net_device *netdev,
}
QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val);
} else if (adapter->ahw.port_type == QLCNIC_XGBE) {
+ if (!pause->rx_pause || pause->autoneg)
+ return -EOPNOTSUPP;
+
if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
return -EIO;
+
val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
if (port == 0) {
if (pause->tx_pause)
--
1.6.0.2
^ permalink raw reply related
* [PATCHv3 NEXT 0/5]qlcnic: aer state
From: amit.salecha @ 2010-07-14 6:33 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman
Hi
Sending revised patches based upon your comment.
I was in under impression that using space after tab is illegal.
I like this type of indentation and will take care in future.
-Amit
^ permalink raw reply
* [PATCHv3 NEXT 3/5] qlcnic: fix netdev notifier in error path
From: amit.salecha @ 2010-07-14 6:33 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Amit Kumar Salecha
In-Reply-To: <1279089215-23231-1-git-send-email-amit.salecha@qlogic.com>
From: Amit Kumar Salecha <amit.salecha@qlogic.com>
netdev notifier are not unregistered if pci_register_driver fails.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 0fef8c3..0995f90 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -3451,6 +3451,7 @@ static struct pci_driver qlcnic_driver = {
static int __init qlcnic_init_module(void)
{
+ int ret;
printk(KERN_INFO "%s\n", qlcnic_driver_string);
@@ -3459,8 +3460,15 @@ static int __init qlcnic_init_module(void)
register_inetaddr_notifier(&qlcnic_inetaddr_cb);
#endif
+ ret = pci_register_driver(&qlcnic_driver);
+ if (ret) {
+#ifdef CONFIG_INET
+ unregister_inetaddr_notifier(&qlcnic_inetaddr_cb);
+ unregister_netdevice_notifier(&qlcnic_netdev_cb);
+#endif
+ }
- return pci_register_driver(&qlcnic_driver);
+ return ret;
}
module_init(qlcnic_init_module);
--
1.6.0.2
^ permalink raw reply related
* [PATCHv3 NEXT 4/5] qlcnic: aer support
From: amit.salecha @ 2010-07-14 6:33 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Sucheta Chakraborty, Amit Kumar Salecha
In-Reply-To: <1279089215-23231-1-git-send-email-amit.salecha@qlogic.com>
From: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Pci error recovery support added.
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 1 +
drivers/net/qlcnic/qlcnic_main.c | 137 +++++++++++++++++++++++++++++++++++++-
2 files changed, 137 insertions(+), 1 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 02a50e6..0644642 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -911,6 +911,7 @@ struct qlcnic_mac_req {
#define __QLCNIC_DEV_UP 1
#define __QLCNIC_RESETTING 2
#define __QLCNIC_START_FW 4
+#define __QLCNIC_AER 5
#define QLCNIC_INTERRUPT_TEST 1
#define QLCNIC_LOOPBACK_TEST 2
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 0995f90..d5c94a3 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -34,6 +34,7 @@
#include <linux/ipv6.h>
#include <linux/inetdevice.h>
#include <linux/sysfs.h>
+#include <linux/aer.h>
MODULE_DESCRIPTION("QLogic 1/10 GbE Converged/Intelligent Ethernet Driver");
MODULE_LICENSE("GPL");
@@ -1306,6 +1307,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_disable_pdev;
pci_set_master(pdev);
+ pci_enable_pcie_error_reporting(pdev);
netdev = alloc_etherdev(sizeof(struct qlcnic_adapter));
if (!netdev) {
@@ -1437,6 +1439,7 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
qlcnic_release_firmware(adapter);
+ pci_disable_pcie_error_reporting(pdev);
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
@@ -2521,6 +2524,9 @@ static void
qlcnic_schedule_work(struct qlcnic_adapter *adapter,
work_func_t func, int delay)
{
+ if (test_bit(__QLCNIC_AER, &adapter->state))
+ return;
+
INIT_DELAYED_WORK(&adapter->fw_work, func);
schedule_delayed_work(&adapter->fw_work, round_jiffies_relative(delay));
}
@@ -2631,6 +2637,128 @@ reschedule:
qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
}
+static int qlcnic_is_first_func(struct pci_dev *pdev)
+{
+ struct pci_dev *oth_pdev;
+ int val = pdev->devfn;
+
+ while (val-- > 0) {
+ oth_pdev = pci_get_domain_bus_and_slot(pci_domain_nr
+ (pdev->bus), pdev->bus->number,
+ PCI_DEVFN(PCI_SLOT(pdev->devfn), val));
+
+ if (oth_pdev && (oth_pdev->current_state != PCI_D3cold))
+ return 0;
+ }
+ return 1;
+}
+
+static int qlcnic_attach_func(struct pci_dev *pdev)
+{
+ int err, first_func;
+ struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+ struct net_device *netdev = adapter->netdev;
+
+ pdev->error_state = pci_channel_io_normal;
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_set_master(pdev);
+ pci_restore_state(pdev);
+
+ first_func = qlcnic_is_first_func(pdev);
+
+ if (qlcnic_api_lock(adapter))
+ return -EINVAL;
+
+ if (first_func) {
+ adapter->need_fw_reset = 1;
+ set_bit(__QLCNIC_START_FW, &adapter->state);
+ QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
+ QLCDB(adapter, DRV, "Restarting fw\n");
+ }
+ qlcnic_api_unlock(adapter);
+
+ err = adapter->nic_ops->start_firmware(adapter);
+ if (err)
+ return err;
+
+ qlcnic_clr_drv_state(adapter);
+ qlcnic_setup_intr(adapter);
+
+ if (netif_running(netdev)) {
+ err = qlcnic_attach(adapter);
+ if (err) {
+ qlcnic_clr_all_drv_state(adapter);
+ clear_bit(__QLCNIC_AER, &adapter->state);
+ netif_device_attach(netdev);
+ return err;
+ }
+
+ err = qlcnic_up(adapter, netdev);
+ if (err)
+ goto done;
+
+ qlcnic_config_indev_addr(netdev, NETDEV_UP);
+ }
+ done:
+ netif_device_attach(netdev);
+ return err;
+}
+
+static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+ struct net_device *netdev = adapter->netdev;
+
+ if (state == pci_channel_io_perm_failure)
+ return PCI_ERS_RESULT_DISCONNECT;
+
+ if (state == pci_channel_io_normal)
+ return PCI_ERS_RESULT_RECOVERED;
+
+ set_bit(__QLCNIC_AER, &adapter->state);
+ netif_device_detach(netdev);
+
+ cancel_delayed_work_sync(&adapter->fw_work);
+
+ if (netif_running(netdev))
+ qlcnic_down(adapter, netdev);
+
+ qlcnic_detach(adapter);
+ qlcnic_teardown_intr(adapter);
+
+ clear_bit(__QLCNIC_RESETTING, &adapter->state);
+
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t qlcnic_io_slot_reset(struct pci_dev *pdev)
+{
+ return qlcnic_attach_func(pdev) ? PCI_ERS_RESULT_DISCONNECT :
+ PCI_ERS_RESULT_RECOVERED;
+}
+
+static void qlcnic_io_resume(struct pci_dev *pdev)
+{
+ struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+
+ pci_cleanup_aer_uncorrect_error_status(pdev);
+
+ if (QLCRD32(adapter, QLCNIC_CRB_DEV_STATE) == QLCNIC_DEV_READY &&
+ test_and_clear_bit(__QLCNIC_AER, &adapter->state))
+ qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
+ FW_POLL_DELAY);
+}
+
+
static int
qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
{
@@ -3436,6 +3564,11 @@ static void
qlcnic_config_indev_addr(struct net_device *dev, unsigned long event)
{ }
#endif
+static struct pci_error_handlers qlcnic_err_handler = {
+ .error_detected = qlcnic_io_error_detected,
+ .slot_reset = qlcnic_io_slot_reset,
+ .resume = qlcnic_io_resume,
+};
static struct pci_driver qlcnic_driver = {
.name = qlcnic_driver_name,
@@ -3446,7 +3579,9 @@ static struct pci_driver qlcnic_driver = {
.suspend = qlcnic_suspend,
.resume = qlcnic_resume,
#endif
- .shutdown = qlcnic_shutdown
+ .shutdown = qlcnic_shutdown,
+ .err_handler = &qlcnic_err_handler
+
};
static int __init qlcnic_init_module(void)
--
1.6.0.2
^ permalink raw reply related
* [PATCHv3 NEXT 2/5] qlcnic: disable tx timeout recovery
From: amit.salecha @ 2010-07-14 6:33 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Amit Kumar Salecha
In-Reply-To: <1279089215-23231-1-git-send-email-amit.salecha@qlogic.com>
From: Amit Kumar Salecha <amit.salecha@qlogic.com>
Disable tx timeout recovery, if auto_fw_reset is disable
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 4d18313..0fef8c3 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -2581,7 +2581,8 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
if (adapter->need_fw_reset)
goto detach;
- if (adapter->reset_context) {
+ if (adapter->reset_context &&
+ auto_fw_reset == AUTO_FW_RESET_ENABLED) {
qlcnic_reset_hw_context(adapter);
adapter->netdev->trans_start = jiffies;
}
@@ -2594,7 +2595,8 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
qlcnic_dev_request_reset(adapter);
- clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
+ if ((auto_fw_reset == AUTO_FW_RESET_ENABLED))
+ clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
dev_info(&netdev->dev, "firmware hang detected\n");
--
1.6.0.2
^ permalink raw reply related
* [PATCHv3 NEXT 5/5] qlcnic: restore NPAR config data after recovery
From: amit.salecha @ 2010-07-14 6:33 UTC (permalink / raw)
To: davem
Cc: netdev, ameen.rahman, Anirban Chakraborty, Rajesh Borundia,
Amit Kumar Salecha
In-Reply-To: <1279089215-23231-1-git-send-email-amit.salecha@qlogic.com>
From: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
o NPAR configuration which is programmed in fw, need to
restore after fw recovery.
o Update version to 5.0.7
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 7 ++-
drivers/net/qlcnic/qlcnic_ctx.c | 2 +
drivers/net/qlcnic/qlcnic_main.c | 86 +++++++++++++++++++++++++++++---------
3 files changed, 72 insertions(+), 23 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 0644642..e189477 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -51,8 +51,8 @@
#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 0
-#define _QLCNIC_LINUX_SUBVERSION 6
-#define QLCNIC_LINUX_VERSIONID "5.0.6"
+#define _QLCNIC_LINUX_SUBVERSION 7
+#define QLCNIC_LINUX_VERSIONID "5.0.7"
#define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c))
@@ -949,7 +949,6 @@ struct qlcnic_adapter {
u8 has_link_events;
u8 fw_type;
u16 tx_context_id;
- u16 mtu;
u16 is_up;
u16 link_speed;
@@ -1044,6 +1043,8 @@ struct qlcnic_pci_info {
struct qlcnic_npar_info {
u16 vlan_id;
+ u16 min_bw;
+ u16 max_bw;
u8 phy_port;
u8 type;
u8 active;
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index cdd44b4..cc5d861 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -636,6 +636,8 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
QLCNIC_CDRP_CMD_GET_NIC_INFO);
if (err == QLCNIC_RCODE_SUCCESS) {
+ npar_info->pci_func = le16_to_cpu(nic_info->pci_func);
+ npar_info->op_mode = le16_to_cpu(nic_info->op_mode);
npar_info->phys_port = le16_to_cpu(nic_info->phys_port);
npar_info->switch_mode = le16_to_cpu(nic_info->switch_mode);
npar_info->max_tx_ques = le16_to_cpu(nic_info->max_tx_ques);
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index d5c94a3..8d2d62f 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -507,6 +507,8 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
adapter->npars[pfn].type = pci_info[i].type;
adapter->npars[pfn].phy_port = pci_info[i].default_port;
adapter->npars[pfn].mac_learning = DEFAULT_MAC_LEARN;
+ adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw;
+ adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw;
}
for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
@@ -771,6 +773,50 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
}
static int
+qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
+{
+ int i, err = 0;
+ struct qlcnic_npar_info *npar;
+ struct qlcnic_info nic_info;
+
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
+ !adapter->need_fw_reset)
+ return 0;
+
+ if (adapter->op_mode == QLCNIC_MGMT_FUNC) {
+ /* Set the NPAR config data after FW reset */
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ npar = &adapter->npars[i];
+ if (npar->type != QLCNIC_TYPE_NIC)
+ continue;
+ err = qlcnic_get_nic_info(adapter, &nic_info, i);
+ if (err)
+ goto err_out;
+ nic_info.min_tx_bw = npar->min_bw;
+ nic_info.max_tx_bw = npar->max_bw;
+ err = qlcnic_set_nic_info(adapter, &nic_info);
+ if (err)
+ goto err_out;
+
+ if (npar->enable_pm) {
+ err = qlcnic_config_port_mirroring(adapter,
+ npar->dest_npar, 1, i);
+ if (err)
+ goto err_out;
+
+ }
+ npar->mac_learning = DEFAULT_MAC_LEARN;
+ npar->host_vlan_tag = 0;
+ npar->promisc_mode = 0;
+ npar->discard_tagged = 0;
+ npar->vlan_id = 0;
+ }
+ }
+err_out:
+ return err;
+}
+
+static int
qlcnic_start_firmware(struct qlcnic_adapter *adapter)
{
int val, err, first_boot;
@@ -834,10 +880,9 @@ wait_init:
qlcnic_idc_debug_info(adapter, 1);
qlcnic_check_options(adapter);
-
- if (adapter->flags & QLCNIC_ESWITCH_ENABLED &&
- adapter->op_mode != QLCNIC_NON_PRIV_FUNC)
- qlcnic_dev_set_npar_ready(adapter);
+ if (qlcnic_reset_npar_config(adapter))
+ goto err_out;
+ qlcnic_dev_set_npar_ready(adapter);
adapter->need_fw_reset = 0;
@@ -2486,6 +2531,7 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
{
u32 state;
+ adapter->need_fw_reset = 1;
if (qlcnic_api_lock(adapter))
return;
@@ -2506,6 +2552,9 @@ qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter)
{
u32 state;
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
+ adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
+ return;
if (qlcnic_api_lock(adapter))
return;
@@ -3019,7 +3068,7 @@ static struct bin_attribute bin_attr_mem = {
.write = qlcnic_sysfs_write_mem,
};
-int
+static int
validate_pm_config(struct qlcnic_adapter *adapter,
struct qlcnic_pm_func_cfg *pm_cfg, int count)
{
@@ -3118,7 +3167,7 @@ qlcnic_sysfs_read_pm_config(struct file *filp, struct kobject *kobj,
return size;
}
-int
+static int
validate_esw_config(struct qlcnic_adapter *adapter,
struct qlcnic_esw_func_cfg *esw_cfg, int count)
{
@@ -3154,9 +3203,8 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
struct device *dev = container_of(kobj, struct device, kobj);
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
struct qlcnic_esw_func_cfg *esw_cfg;
- u8 id, discard_tagged, promsc_mode, mac_learn;
- u8 vlan_tagging, pci_func, vlan_id;
int count, rem, i, ret;
+ u8 id, pci_func;
count = size / sizeof(struct qlcnic_esw_func_cfg);
rem = size % sizeof(struct qlcnic_esw_func_cfg);
@@ -3171,17 +3219,13 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
for (i = 0; i < count; i++) {
pci_func = esw_cfg[i].pci_func;
id = adapter->npars[pci_func].phy_port;
- vlan_tagging = esw_cfg[i].host_vlan_tag;
- promsc_mode = esw_cfg[i].promisc_mode;
- mac_learn = esw_cfg[i].mac_learning;
- vlan_id = esw_cfg[i].vlan_id;
- discard_tagged = esw_cfg[i].discard_tagged;
- ret = qlcnic_config_switch_port(adapter, id, vlan_tagging,
- discard_tagged,
- promsc_mode,
- mac_learn,
- pci_func,
- vlan_id);
+ ret = qlcnic_config_switch_port(adapter, id,
+ esw_cfg[i].host_vlan_tag,
+ esw_cfg[i].discard_tagged,
+ esw_cfg[i].promisc_mode,
+ esw_cfg[i].mac_learning,
+ esw_cfg[i].pci_func,
+ esw_cfg[i].vlan_id);
if (ret)
return ret;
}
@@ -3227,7 +3271,7 @@ qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj,
return size;
}
-int
+static int
validate_npar_config(struct qlcnic_adapter *adapter,
struct qlcnic_npar_func_cfg *np_cfg, int count)
{
@@ -3282,6 +3326,8 @@ qlcnic_sysfs_write_npar_config(struct file *file, struct kobject *kobj,
ret = qlcnic_set_nic_info(adapter, &nic_info);
if (ret)
return ret;
+ adapter->npars[i].min_bw = nic_info.min_tx_bw;
+ adapter->npars[i].max_bw = nic_info.max_tx_bw;
}
return size;
--
1.6.0.2
^ permalink raw reply related
* Re: [PATCH] tproxy: nf_tproxy_assign_sock() can handle tw sockets
From: Bill Fink @ 2010-07-14 6:56 UTC (permalink / raw)
To: Felipe W Damasio
Cc: Eric Dumazet, Avi Kivity, David Miller, Patrick McHardy,
linux-kernel, netdev
In-Reply-To: <AANLkTikmuK0iWDjmG6lVgPyoZAHQ7ZdJmQobVrAQmgNh@mail.gmail.com>
On Wed, 14 Jul 2010, Felipe W Damasio wrote:
> Hi,
>
> 2010/7/14 Eric Dumazet <eric.dumazet@gmail.com>:
> >> I can, but my bosses will kick my ass if I bring down the ISP again :)
> >
> > I have no guarantee at all, even if we find the bug.
>
> Ok :-)
>
> >> If you think it's the only way to find the problem I'll tell them that
> >> I need to do it. In this case, please tell me what other config
> >> options/tools I can use to get as much info as possible...since I'll
> >> probably be able to test this only once more on the production
> >> environment for debugging purposes.
> >
> > You really should try to setup a lab to trigger the bug, and not doing
> > experiments on production :)
>
> Right, I'm trying.
>
> The thing is: The ISP is a 200Mbps network with 10,000 users. The
> first time it took around 2 minutes to trigger the bug. The second
> time it took around 17 minutes.
>
> So I *think* it's some TCP flag with some weird content...but I can't
> find out what it is so I can trigger it on the lab.
>
> So my only guess is to enable every possible debug flag I can think of
> to track the bug down on the production environment. Any hints here
> would be appreciated :)
Is it possible for you to mirror the production traffic to another
port, and then do a tcpdump capture to a series of files, so that
you might possibly be able to correlate the kernel crash to the
actual packets on the wire (and the Invalid Request squid errors)?
Just a suggestion.
-Bill
^ permalink raw reply
* [PATCH net-next-2.6] xfrm: cleanup of xfrm_input.c.
From: Rami Rosen @ 2010-07-14 8:18 UTC (permalink / raw)
To: davem, netdev
[-- Attachment #1: Type: text/plain, Size: 213 bytes --]
Hi,
The patch removes unneeded inclusion of header files
(linux/module.h, linux/netdevice.h, net/dst.h and net/ip.h)
in net/xfrm/xfrm_input.c
Regards,
Rami Rosen
Signed-off-by: Rami Rosen <ramirose@gmail.com>
[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 376 bytes --]
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 45f1c98..662d3fe 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -8,10 +8,6 @@
*/
#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <net/dst.h>
-#include <net/ip.h>
#include <net/xfrm.h>
static struct kmem_cache *secpath_cachep __read_mostly;
^ permalink raw reply related
* [PATCH] net/nuc900: enable Mac driver clock
From: Wan ZongShun @ 2010-07-14 9:48 UTC (permalink / raw)
To: LKML, netdev, David Miller
This patch fixed a bug that Mac driver does not work,because I missed the clk enable.
I have ever tested the driver when I submitted previous Mac driver patch,
and it worked good, since my bootloader has enabled the clock in advance.
But when I try to use other bootloader where clock engine was disabled,the
Mac driver does not work, so I send this patch to fix this issue.
Signed-off-by: Wan ZongShun <mcuos.com@gmail.com>
---
drivers/net/arm/w90p910_ether.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c
index 2e85246..4545d5a 100644
--- a/drivers/net/arm/w90p910_ether.c
+++ b/drivers/net/arm/w90p910_ether.c
@@ -822,6 +822,9 @@ static int w90p910_ether_open(struct net_device *dev)
w90p910_set_global_maccmd(dev);
w90p910_enable_rx(dev, 1);
+ clk_enable(ether->rmiiclk);
+ clk_enable(ether->clk);
+
ether->rx_packets = 0x0;
ether->rx_bytes = 0x0;
--
1.6.3.3
^ permalink raw reply related
* Re: [Pv-drivers] RFC: Network Plugin Architecture (NPA) for vmxnet3
From: Greg KH @ 2010-07-14 9:49 UTC (permalink / raw)
To: Shreyas Bhatewara
Cc: Christoph Hellwig, Stephen Hemminger, Pankaj Thakkar,
pv-drivers@vmware.com, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org,
virtualization@lists.linux-foundation.org
In-Reply-To: <1278990388.32650.22.camel@eng-rhel5-64>
On Mon, Jul 12, 2010 at 08:06:28PM -0700, Shreyas Bhatewara wrote:
> drivers/net/vmxnet3/vmxnet3_drv.c | 1845
> +++++++++++++++++++--------------
Your patch is line-wrapped and can not be applied :(
Care to fix your email client?
One thing just jumped out at me when glancing at this:
> +static INLINE void
> +MoveMemory(void *dst,
> + void *src,
> + size_t length)
> +{
> + size_t i;
> + for (i = 0; i < length; ++i)
> + ((u8 *)dst)[i] = ((u8 *)src)[i];
> +}
> +
> +static INLINE void
> +ZeroMemory(void *memory,
> + size_t length)
> +{
> + size_t i;
> + for (i = 0; i < length; ++i)
> + ((u8 *)memory)[i] = 0;
> +}
Is there some reason that our in-kernel functions that do this type of
logic are not working for you to require you to reimplement this?
thanks,
greg k-h
^ permalink raw reply
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