* Re: [PATCH] sctp: fix warning when compiling without IPv6
From: David Miller @ 2012-06-19 7:28 UTC (permalink / raw)
To: dhalperi; +Cc: netdev
In-Reply-To: <B7062EEE-046D-4435-B5FC-54FF3F763645@cs.washington.edu>
From: Daniel Halperin <dhalperi@cs.washington.edu>
Date: Mon, 18 Jun 2012 14:04:55 -0700
> net/sctp/protocol.c: In function ‘sctp_addr_wq_timeout_handler’:
> net/sctp/protocol.c:676: warning: label ‘free_next’ defined but not used
>
> Signed-off-by: Daniel Halperin <dhalperi@cs.washington.edu>
Applied.
^ permalink raw reply
* Re: [PATCH RESEND] net: lpc_eth: Driver cleanup
From: David Miller @ 2012-06-19 7:28 UTC (permalink / raw)
To: stigge
Cc: eric.dumazet, netdev, linux-kernel, kevin.wells, srinivas.bakki,
aletes.xgr, linux-arm-kernel
In-Reply-To: <1340050482-22666-1-git-send-email-stigge@antcom.de>
From: Roland Stigge <stigge@antcom.de>
Date: Mon, 18 Jun 2012 22:14:42 +0200
> This patch removes some nowadays superfluous definitions (one unused define and
> an obsolete function forward declaration) and corrects a netdev_err() to
> netdev_dbg().
>
> Signed-off-by: Roland Stigge <stigge@antcom.de>
> Signed-off-by: Alexandre Pereira da Silva <aletes.xgr@gmail.com>
Applied.
^ permalink raw reply
* Re: [PATCH] net: added support for 40GbE link.
From: David Miller @ 2012-06-19 7:29 UTC (permalink / raw)
To: bhutchings; +Cc: parav.pandit, netdev
In-Reply-To: <1340039376.2913.13.camel@bwh-desktop.uk.solarflarecom.com>
From: Ben Hutchings <bhutchings@solarflare.com>
Date: Mon, 18 Jun 2012 18:09:36 +0100
> On Mon, 2012-06-18 at 18:14 +0530, Parav Pandit wrote:
...
>> -/* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE. */
>> +/* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE, 40GbE. */
>
> I don't think there's any need to name all possible link speeds, and it
> just encourages the bad practice of ethtool API users checking for
> specific values. You may notice there is no SPEED_20000.
Agreed.
>> @@ -542,13 +542,11 @@ static int prb_calc_retire_blk_tmo(struct packet_sock *po,
...
> This function should be fixed properly. Firstly, it must use
> ethtool_cmd_speed() rather than directly accessing ecmd.speed.
> Secondly, it should allow any speed value rather than checking for
> specific values. Then there will be no need to make further changes for
> 100G or any other new speed.
Agreed.
^ permalink raw reply
* Re: [PATCH] phy/micrel: change phy_id_mask for KSZ9021 and KS8001
From: David Miller @ 2012-06-19 7:31 UTC (permalink / raw)
To: jason77.wang; +Cc: david.choi, nobuhiro.iwamatsu.yj, netdev
In-Reply-To: <1340009529-4231-1-git-send-email-jason77.wang@gmail.com>
From: Hui Wang <jason77.wang@gmail.com>
Date: Mon, 18 Jun 2012 16:52:09 +0800
> On a freescale imx6q platform, a hardware phy chip KSZ9021 is
> recognized as a KS8001 chip by the current driver like this:
> eth0: Freescale FEC PHY driver [Micrel KS8001 or KS8721]
>
> KSZ9021 has phy_id 0x00221610, while KSZ8001 has phy_id
> 0x0022161a, the current phy_id_mask (0x00fffff0/0x00ffff10) can't
> distinguish them. So change phy_id_mask to resolve this problem.
>
> Although the micrel datasheet says that the 4 LSB of phyid2 register
> contains the chip revision number and the current driver is designed
> to follow this rule, in reality the chip implementation doesn't follow
> it.
>
> Cc: David J. Choi <david.choi@micrel.com>
> Cc: David S. Miller <davem@davemloft.net>
> Cc: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
> Signed-off-by: Hui Wang <jason77.wang@gmail.com>
Applied, thanks.
^ permalink raw reply
* RE: [PATCH] net: added support for 40GbE link.
From: Parav.Pandit @ 2012-06-19 7:33 UTC (permalink / raw)
To: davem, bhutchings; +Cc: netdev
In-Reply-To: <20120619.002905.922583388766089167.davem@davemloft.net>
> -----Original Message-----
> From: David Miller [mailto:davem@davemloft.net]
> Sent: Tuesday, June 19, 2012 12:59 PM
> To: bhutchings@solarflare.com
> Cc: Pandit, Parav; netdev@vger.kernel.org
> Subject: Re: [PATCH] net: added support for 40GbE link.
>
> From: Ben Hutchings <bhutchings@solarflare.com>
> Date: Mon, 18 Jun 2012 18:09:36 +0100
>
> > On Mon, 2012-06-18 at 18:14 +0530, Parav Pandit wrote:
> ...
> >> -/* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE. */
> >> +/* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE, 40GbE. */
> >
> > I don't think there's any need to name all possible link speeds, and
> > it just encourages the bad practice of ethtool API users checking for
> > specific values. You may notice there is no SPEED_20000.
>
> Agreed.
Should eventually all net driver should remove using SPEED_xxxxxx and start using hard coded value of 10, 100, 1000, 20000?
>
> >> @@ -542,13 +542,11 @@ static int prb_calc_retire_blk_tmo(struct
> >> packet_sock *po,
> ...
> > This function should be fixed properly. Firstly, it must use
> > ethtool_cmd_speed() rather than directly accessing ecmd.speed.
> > Secondly, it should allow any speed value rather than checking for
> > specific values. Then there will be no need to make further changes
> > for 100G or any other new speed.
>
> Agreed.
That means ethtool_cmd_speed() should not be called in this function?
If I understand correctly, it should return the value of 8ms (for 10Mb,s 100Mbps, 2.5 Gbps, 20Gbps) as today and remaining it should return calculated value?
Or
Function needs a fix for all these speeds (10Mbps, 100Mbs, 20Gbps too)?
^ permalink raw reply
* Re: [XFRM][RFC v1] Fix unexpected SA hard expiration after setting new date
From: David Miller @ 2012-06-19 7:34 UTC (permalink / raw)
To: herbert; +Cc: fan.du, netdev, fdu
In-Reply-To: <20120618084021.GA24902@gondor.apana.org.au>
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Mon, 18 Jun 2012 16:40:21 +0800
> I guess I can live with your workaround if Dave is happy with
> it. But IMHO we should just go back to relative time and fix
> the suspend/resume user-space scripts instead.
In the short term I'm happy with it too.
But I seem to remember that last time this issue came up the
suggestion was to use highres timers. Someone tried but they did an
amazingly poor job so the effort just died off. It takes someone with
some skill because highres timers operate with different context
requirements than normal timers.
^ permalink raw reply
* Re: [PATCH] net: added support for 40GbE link.
From: David Miller @ 2012-06-19 7:35 UTC (permalink / raw)
To: Parav.Pandit; +Cc: bhutchings, netdev
In-Reply-To: <5D6C0ABE6A236946864C45679362BBE20AC52269@CMEXMB1.ad.emulex.com>
From: <Parav.Pandit@Emulex.Com>
Date: Tue, 19 Jun 2012 07:33:12 +0000
> Should eventually all net driver should remove using SPEED_xxxxxx and start using hard coded value of 10, 100, 1000, 20000?
No, the ones that exist can stay, just no new ones.
> That means ethtool_cmd_speed() should not be called in this function?
Ben said that it must be called, what are you talking about?
^ permalink raw reply
* RE: [PATCH] net: added support for 40GbE link.
From: Parav.Pandit @ 2012-06-19 7:42 UTC (permalink / raw)
To: davem; +Cc: bhutchings, netdev
In-Reply-To: <20120619.003517.2067426285873138772.davem@davemloft.net>
> -----Original Message-----
> From: David Miller [mailto:davem@davemloft.net]
> Sent: Tuesday, June 19, 2012 1:05 PM
> To: Pandit, Parav
> Cc: bhutchings@solarflare.com; netdev@vger.kernel.org
> Subject: Re: [PATCH] net: added support for 40GbE link.
>
> From: <Parav.Pandit@Emulex.Com>
> Date: Tue, 19 Jun 2012 07:33:12 +0000
>
> > Should eventually all net driver should remove using SPEED_xxxxxx and
> start using hard coded value of 10, 100, 1000, 20000?
>
> No, the ones that exist can stay, just no new ones.
>
So driver which supports 40Gpbs, 100Gbps should hardcode to 40000, 100000 respectively?
> > That means ethtool_cmd_speed() should not be called in this function?
>
> Ben said that it must be called, what are you talking about?
Sorry, I wanted to ask - Do you need switch case for speed like below new code or its should be speed independent code?
switch (ethtool_cmd_speed()) {
case SPEED_100:
case SPEED_10:
return DEFAULT_PRB_RETIRE_TOV;
default:
msec = 1;
div = ethtool_cmd_speed() / 1000;
break;
/*
}
^ permalink raw reply
* Re: [XFRM][RFC v1] Fix unexpected SA hard expiration after setting new date
From: Herbert Xu @ 2012-06-19 7:43 UTC (permalink / raw)
To: David Miller; +Cc: fan.du, netdev, fdu
In-Reply-To: <20120619.003422.1109786261235176550.davem@davemloft.net>
On Tue, Jun 19, 2012 at 12:34:22AM -0700, David Miller wrote:
>
> But I seem to remember that last time this issue came up the
> suggestion was to use highres timers. Someone tried but they did an
> amazingly poor job so the effort just died off. It takes someone with
> some skill because highres timers operate with different context
> requirements than normal timers.
Sorry I think I didn't see that discussion or if I did, then
it has completely left my mind :)
So excuse my ignorance, are highres timers relative like jiffies
or absolute? If it's absolute, I don't see how it would impact this
case.
If it's relative, what exactly does it buy for us over jiffies?
Thanks,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* [XFRM][RFC v2] Fix unexpected SA hard expiration after setting new date
From: fan.du @ 2012-06-19 7:51 UTC (permalink / raw)
To: davem, herbert; +Cc: netdev, fdu
Hi, Dave and Herbert
Could you give a try to review this?
thanks :)
Changelog:
v1->v2
1) use xflags instead of creating new flags(suggested by Steffen Klassert)
*Background*:
Once IPsec SAs are created between two peers, kernel setup a timer to monitor
two events: soft/hard expiration. However the timer handler use xtime to
caculate whether it's soft or hard expiration event.
normal code flow(hard expire time:100s, soft expire time:82s)
a) When new SAs created, xfrm_timer_handler is called one second
after its creation. At this point, calculate soft expire
interval(81s), setup the timer;
b) soft expire occur, rearm the timer with hard expire interval(18s)
then notify racoon2 about soft expire event. racoon2 will create
new SAs.
c) hard expire happen, notify racoon2 about it. racoon2 will delete
the old SAs.
*Scenario*:
Setting a new date before b),and after a) could result c) happens first,
As a result, old SAs is deleted before new ones are created. Normally
new SAs will be created by the next time networking traffic, but there
is a small time being when networking connection is down, this could
result in upper layer connections failed in tel comm area, thus it's
better to keep it strict in sequence.
*Workaround*:
set new time could happen:
1) before a), then SAs is updated with new time.
2) before b),and after a)
2a) When new SAs created, xfrm_timer_handler is called one second
after its creation. At this point, calculate soft expire
interval(81s), setup the timer;(set flag to mark next time should
be soft time expire)
<<---- new date comes
2b) soft expire occur, the calculation results in a hard time expire
event, but flag is set, so catch ya. Sync the addtime, and rearm
the timer with hard expire interval(18s), then notify racoon2
about soft expire event;
2c) hard expire happen, notify racoon2 about it;
so everything is in order.
3) after b), hard expire always happened anyway.
^ permalink raw reply
* [PATCH] [XFRM] Fix unexpected SA hard expiration after changing date
From: fan.du @ 2012-06-19 7:51 UTC (permalink / raw)
To: davem, herbert; +Cc: netdev, fdu
In-Reply-To: <1340092269-6136-1-git-send-email-fan.du@windriver.com>
From: "fan.du" <fan.du@windriver.com>
After SA is setup, one timer is armed to detect soft/hard expiration,
however the timer handler uses xtime to do the math. This makes hard
expiration occurs first before soft expiration after setting new date
with big interval. As a result new child SA is deleted before rekeying
the new one.
Signed-off-by: fan.du <fan.du@windriver.com>
---
include/net/xfrm.h | 3 +++
net/xfrm/xfrm_state.c | 21 +++++++++++++++++----
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 2933d74..8d16777 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -197,6 +197,8 @@ struct xfrm_state
struct xfrm_lifetime_cur curlft;
struct timer_list timer;
+ /* used to fix curlft->add_time when changing date */
+ long saved_tmo;
/* Last used time */
unsigned long lastused;
@@ -218,6 +220,7 @@ struct xfrm_state
/* xflags - make enum if more show up */
#define XFRM_TIME_DEFER 1
+#define XFRM_SOFT_EXPIRE 2
enum {
XFRM_STATE_VOID,
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index fd77cf0..ab4aa0f 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -442,8 +442,17 @@ static void xfrm_timer_handler(unsigned long data)
if (x->lft.hard_add_expires_seconds) {
long tmo = x->lft.hard_add_expires_seconds +
x->curlft.add_time - now;
- if (tmo <= 0)
- goto expired;
+ if (tmo <= 0) {
+ if (x->xflags & XFRM_SOFT_EXPIRE) {
+ /* enter hard expire without soft expire first?!
+ * setting a new date could trigger this.
+ * workarbound: fix x->curflt.add_time by below:
+ */
+ x->curlft.add_time = now - x->saved_tmo - 1;
+ tmo = x->lft.hard_add_expires_seconds - x->saved_tmo;
+ } else
+ goto expired;
+ }
if (tmo < next)
next = tmo;
}
@@ -460,10 +469,14 @@ static void xfrm_timer_handler(unsigned long data)
if (x->lft.soft_add_expires_seconds) {
long tmo = x->lft.soft_add_expires_seconds +
x->curlft.add_time - now;
- if (tmo <= 0)
+ if (tmo <= 0) {
warn = 1;
- else if (tmo < next)
+ x->xflags |= ~XFRM_SOFT_EXPIRE;
+ } else if (tmo < next) {
next = tmo;
+ x->xflags |= XFRM_SOFT_EXPIRE;
+ x->saved_tmo = tmo;
+ }
}
if (x->lft.soft_use_expires_seconds) {
long tmo = x->lft.soft_use_expires_seconds +
--
1.7.11
^ permalink raw reply related
* Re: [PATCH net-next v2 06/12] netfilter: merge udpv[4,6]_net_init into udp_net_init
From: Gao feng @ 2012-06-19 8:08 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netdev, netfilter-devel
In-Reply-To: <20120616112259.GG18251@1984>
于 2012年06月16日 19:22, Pablo Neira Ayuso 写道:
> On Sat, Jun 16, 2012 at 11:41:17AM +0800, Gao feng wrote:
>> merge udpv4_net_init and udpv6_net_init into udp_net_init to
>> reduce the redundancy codes.
>>
>> and use nf_proto_net.users to identify if it's the first time
>> we use the nf_proto_net. when it's the first time,we will
>> initialized it.
>>
>> Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
>> ---
>> net/netfilter/nf_conntrack_proto_udp.c | 56 ++++++++++---------------------
>> 1 files changed, 18 insertions(+), 38 deletions(-)
>>
>> diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
>> index 2b978e6..61bca4f 100644
>> --- a/net/netfilter/nf_conntrack_proto_udp.c
>> +++ b/net/netfilter/nf_conntrack_proto_udp.c
>> @@ -270,52 +270,32 @@ static int udp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn)
>> return 0;
>> }
>>
>> -static void udp_init_net_data(struct nf_udp_net *un)
>> +static int udp_init_net(struct net *net, u_int16_t proto)
>> {
>> - int i;
>> -#ifdef CONFIG_SYSCTL
>> - if (!un->pn.ctl_table) {
>> -#else
>> - if (!un->pn.users++) {
>> -#endif
>> + int ret;
>> + struct nf_udp_net *un = udp_pernet(net);
>> + struct nf_proto_net *pn = &un->pn;
>> +
>> + if (!pn->users) {
>> + int i;
>> for (i = 0; i < UDP_CT_MAX; i++)
>> un->timeouts[i] = udp_timeouts[i];
>> }
>> -}
>> -
>> -static int udpv4_init_net(struct net *net, u_int16_t proto)
>> -{
>> - int ret;
>> - struct nf_udp_net *un = udp_pernet(net);
>> - struct nf_proto_net *pn = (struct nf_proto_net *)un;
>>
>> - udp_init_net_data(un);
>> + if (proto == AF_INET) {
>
> I think we can remove that u_int16_t proto that I proposed to make
> something like:
>
> static int udp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn)
> {
> #ifdef CONFIG_SYSCTL
> #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
> struct nf_udp_net *un = (struct nf_udp_net *)pn;
> +
> + if (pn->ctl_compat_table)
> + return 0;
> +
> pn->ctl_compat_table = kmemdup(udp_compat_sysctl_table,
> sizeof(udp_compat_sysctl_table),
> GFP_KERNEL);
> if (!pn->ctl_compat_table)
> return -ENOMEM;
>
> That should be enough to ensure that the compat is registered once. No
> matter if it's done by the IPv4 or IPv6 invocation of udp_init_net.
>
> Thus, it will look consistent with udp_kmemdup_sysctl_table.
yes, but this will be very terrible to unregister compat sysctl
and free compat sysctl table.
thinking about, we may insmod nf_conntrack_ipv6 only, as your idea,
we will allocate compat_sysctl_table.so we have to free it when
rmmod nf_conntrack_ipv6.
in order to implement it, we have to change the logic of
nf_ct_l4proto_unregister_sysctl and nf_ct_unregister_sysctl. because we
only free the sysctl table when we unregister the proto.
^ permalink raw reply
* Re: [PATCH net-next v2 06/12] netfilter: merge udpv[4,6]_net_init into udp_net_init
From: Gao feng @ 2012-06-19 8:12 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netdev, netfilter-devel
In-Reply-To: <4FE0337F.6030000@cn.fujitsu.com>
于 2012年06月19日 16:08, Gao feng 写道:
>
> in order to implement it, we have to change the logic of
> nf_ct_l4proto_unregister_sysctl and nf_ct_unregister_sysctl. because we
> only free the sysctl table when we unregister the proto.
I means free the sysctl table when we register sysctl success
(pn->ctl_table_header != NULL).
^ permalink raw reply
* Re: [PATCH net-next v2 11/12] netfilter: nf_conntrack_l4proto_icmp cleanup
From: Gao feng @ 2012-06-19 8:14 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netdev, netfilter-devel
In-Reply-To: <20120616110828.GE18251@1984>
于 2012年06月16日 19:08, Pablo Neira Ayuso 写道:
> extra line unrequiered.
>
> I'm sorry, I'm stressing a lot on this because I don't like abusing
> follow-up patches that clean up extra lines / missing lines and that
> sort of nitpicks...
>
Sorry for this,I will double check this when I send the v3 patch.
Thanks.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] [XFRM] Fix unexpected SA hard expiration after changing date
From: David Miller @ 2012-06-19 9:01 UTC (permalink / raw)
To: fan.du; +Cc: herbert, netdev, fdu
In-Reply-To: <1340092269-6136-2-git-send-email-fan.du@windriver.com>
From: "fan.du" <fan.du@windriver.com>
Date: Tue, 19 Jun 2012 15:51:09 +0800
> From: "fan.du" <fan.du@windriver.com>
Please don't put your email user name instead of real name in quotes
there. Thank you.
^ permalink raw reply
* Re: [PATCH] [XFRM] Fix unexpected SA hard expiration after changing date
From: David Miller @ 2012-06-19 9:05 UTC (permalink / raw)
To: fan.du; +Cc: herbert, netdev, fdu
In-Reply-To: <20120619.020111.1596676335106760442.davem@davemloft.net>
From: David Miller <davem@davemloft.net>
Date: Tue, 19 Jun 2012 02:01:11 -0700 (PDT)
> From: "fan.du" <fan.du@windriver.com>
> Date: Tue, 19 Jun 2012 15:51:09 +0800
>
>> From: "fan.du" <fan.du@windriver.com>
>
> Please don't put your email user name instead of real name in quotes
> there. Thank you.
Also fdu@windriver.com bounces, do not put it in the CC: list.
^ permalink raw reply
* [XFRM][RFC v3] Fix unexpected SA hard expiration after setting new date
From: Fan Du @ 2012-06-19 9:28 UTC (permalink / raw)
To: davem, herbert; +Cc: netdev
Hi, Dave and Herbert
Could you give a try to review this?
thanks
Changelog:
v1->v2
1) use xflags instead of creating new flags(suggested by Steffen Klassert)
v2->v3
1) fix email problem, and remove cc to myself(requested by David Miller)
*Background*:
Once IPsec SAs are created between two peers, kernel setup a timer to monitor
two events: soft/hard expiration. However the timer handler use xtime to
caculate whether it's soft or hard expiration event.
normal code flow(hard expire time:100s, soft expire time:82s)
a) When new SAs created, xfrm_timer_handler is called one second
after its creation. At this point, calculate soft expire
interval(81s), setup the timer;
b) soft expire occur, rearm the timer with hard expire interval(18s)
then notify racoon2 about soft expire event. racoon2 will create
new SAs.
c) hard expire happen, notify racoon2 about it. racoon2 will delete
the old SAs.
*Scenario*:
Setting a new date before b),and after a) could result c) happens first,
As a result, old SAs is deleted before new ones are created. Normally
new SAs will be created by the next time networking traffic, but there
is a small time being when networking connection is down, this could
result in upper layer connections failed in tel comm area, thus it's
better to keep it strict in sequence.
*Workaround*:
set new time could happen:
1) before a), then SAs is updated with new time.
2) before b),and after a)
2a) When new SAs created, xfrm_timer_handler is called one second
after its creation. At this point, calculate soft expire
interval(81s), setup the timer;(set flag to mark next time should
be soft time expire)
<<---- new date comes
2b) soft expire occur, the calculation results in a hard time expire
event, but flag is set, so catch ya. Sync the addtime, and rearm
the timer with hard expire interval(18s), then notify racoon2
about soft expire event;
2c) hard expire happen, notify racoon2 about it;
so everything is in order.
3) after b), hard expire always happened anyway.
^ permalink raw reply
* [PATCH] [XFRM] Fix unexpected SA hard expiration after changing date
From: Fan Du @ 2012-06-19 9:28 UTC (permalink / raw)
To: davem, herbert; +Cc: netdev
In-Reply-To: <1340098118-21529-1-git-send-email-fdu@windriver.com>
After SA is setup, one timer is armed to detect soft/hard expiration,
however the timer handler uses xtime to do the math. This makes hard
expiration occurs first before soft expiration after setting new date
with big interval. As a result new child SA is deleted before rekeying
the new one.
Signed-off-by: Fan Du <fdu@windriver.com>
---
include/net/xfrm.h | 3 +++
net/xfrm/xfrm_state.c | 21 +++++++++++++++++----
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 2933d74..8d16777 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -197,6 +197,8 @@ struct xfrm_state
struct xfrm_lifetime_cur curlft;
struct timer_list timer;
+ /* used to fix curlft->add_time when changing date */
+ long saved_tmo;
/* Last used time */
unsigned long lastused;
@@ -218,6 +220,7 @@ struct xfrm_state
/* xflags - make enum if more show up */
#define XFRM_TIME_DEFER 1
+#define XFRM_SOFT_EXPIRE 2
enum {
XFRM_STATE_VOID,
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index fd77cf0..ab4aa0f 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -442,8 +442,17 @@ static void xfrm_timer_handler(unsigned long data)
if (x->lft.hard_add_expires_seconds) {
long tmo = x->lft.hard_add_expires_seconds +
x->curlft.add_time - now;
- if (tmo <= 0)
- goto expired;
+ if (tmo <= 0) {
+ if (x->xflags & XFRM_SOFT_EXPIRE) {
+ /* enter hard expire without soft expire first?!
+ * setting a new date could trigger this.
+ * workarbound: fix x->curflt.add_time by below:
+ */
+ x->curlft.add_time = now - x->saved_tmo - 1;
+ tmo = x->lft.hard_add_expires_seconds - x->saved_tmo;
+ } else
+ goto expired;
+ }
if (tmo < next)
next = tmo;
}
@@ -460,10 +469,14 @@ static void xfrm_timer_handler(unsigned long data)
if (x->lft.soft_add_expires_seconds) {
long tmo = x->lft.soft_add_expires_seconds +
x->curlft.add_time - now;
- if (tmo <= 0)
+ if (tmo <= 0) {
warn = 1;
- else if (tmo < next)
+ x->xflags |= ~XFRM_SOFT_EXPIRE;
+ } else if (tmo < next) {
next = tmo;
+ x->xflags |= XFRM_SOFT_EXPIRE;
+ x->saved_tmo = tmo;
+ }
}
if (x->lft.soft_use_expires_seconds) {
long tmo = x->lft.soft_use_expires_seconds +
--
1.7.11
^ permalink raw reply related
* [PATCH net-next 0/5] qmi_wwan fixes for 3.6
From: Bjørn Mork @ 2012-06-19 10:41 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: Oliver Neukum, Dan Williams, linux-usb-u79uwXL29TY76Z2rM5mHXA,
Andrew Bird (Sphere Systems), Bjørn Mork
None of these are critical, so I don't think they are appropriate
for 3.5 at this point. I've therefore based them on net-next.
The two first patches prepare the driver for the new probing
model introduced by patch #3, which is the main change in this
set. A RFC version of this was posted to linux-usb 29 May 2012
for discussion, as it also implicitly affects the cdc-wdm driver,
without any comments so far.
Probing on the data interface was a mistake which was introduced
at a point where I didn't realize that the cdc-wdm subdriver
support was required in any case, because most of the supported
devices only provide a single USB interface. Apart from creating
a confusing and inconsistent driver usage, where some devices would
use cdc-wdm as a subdriver and some would not, a number of real
problems has also shown up. The most important one at the moment
is the need to make cdc_ether and qmi_wwan cooperate wrt which
devices are supported by which driver. This is close to impossible
unless the two probes both look at the same control interface. It
is not enough that the probe does this. We need to fine tune the
alias matching, which implies fine tuning the device ID tables.
Completing this change will require removing the now unnecessary
and conflicting device ID entries from cdc-wdm. This will be
submitted as a separate patch against usb-next to avoid mixing
patches for both trees in one patch set. There is no build
dependency.
The two last patches are minor obvious editorial fixes.
Bjørn Mork (5):
net: qmi_wwan: define a structure for driver specific state
net: qmi_wwan: rearranging to prepare for code sharing
net: qmi_wwan: bind to both control and data interface
net: qmi_wwan: shorten driver description
net: qmi_wwan: use module_usb_driver macro
drivers/net/usb/qmi_wwan.c | 308 +++++++++++++++++++++++---------------------
1 file changed, 163 insertions(+), 145 deletions(-)
--
1.7.10
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH net-next 1/5] net: qmi_wwan: define a structure for driver specific state
From: Bjørn Mork @ 2012-06-19 10:41 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: Oliver Neukum, Dan Williams, linux-usb-u79uwXL29TY76Z2rM5mHXA,
Andrew Bird (Sphere Systems), Bjørn Mork
In-Reply-To: <1340102523-23990-1-git-send-email-bjorn-yOkvZcmFvRU@public.gmane.org>
usbnet allocates a fixed size array for minidriver specific
state. Naming the fields and taking advantage of type checking
is a bit more failsafe than casting array elements each time
they are referenced.
Signed-off-by: Bjørn Mork <bjorn-yOkvZcmFvRU@public.gmane.org>
---
drivers/net/usb/qmi_wwan.c | 49 ++++++++++++++++++++++++++------------------
1 file changed, 29 insertions(+), 20 deletions(-)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 3b20678..c7b9be8 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -54,6 +54,13 @@
* corresponding management interface
*/
+/* driver specific data */
+struct qmi_wwan_state {
+ struct usb_driver *subdriver;
+ atomic_t pmcount;
+ unsigned long unused[3];
+};
+
static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
{
int status = -1;
@@ -65,9 +72,11 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
struct usb_cdc_ether_desc *cdc_ether = NULL;
u32 required = 1 << USB_CDC_HEADER_TYPE | 1 << USB_CDC_UNION_TYPE;
u32 found = 0;
- atomic_t *pmcount = (void *)&dev->data[1];
+ struct qmi_wwan_state *info = (void *)&dev->data;
+
+ BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state)));
- atomic_set(pmcount, 0);
+ atomic_set(&info->pmcount, 0);
/*
* assume a data interface has no additional descriptors and
@@ -177,12 +186,12 @@ err:
/* using a counter to merge subdriver requests with our own into a combined state */
static int qmi_wwan_manage_power(struct usbnet *dev, int on)
{
- atomic_t *pmcount = (void *)&dev->data[1];
+ struct qmi_wwan_state *info = (void *)&dev->data;
int rv = 0;
- dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(pmcount), on);
+ dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(&info->pmcount), on);
- if ((on && atomic_add_return(1, pmcount) == 1) || (!on && atomic_dec_and_test(pmcount))) {
+ if ((on && atomic_add_return(1, &info->pmcount) == 1) || (!on && atomic_dec_and_test(&info->pmcount))) {
/* need autopm_get/put here to ensure the usbcore sees the new value */
rv = usb_autopm_get_interface(dev->intf);
if (rv < 0)
@@ -212,7 +221,7 @@ static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf)
{
int rv;
struct usb_driver *subdriver = NULL;
- atomic_t *pmcount = (void *)&dev->data[1];
+ struct qmi_wwan_state *info = (void *)&dev->data;
/* ZTE makes devices where the interface descriptors and endpoint
* configurations of two or more interfaces are identical, even
@@ -228,7 +237,7 @@ static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf)
goto err;
}
- atomic_set(pmcount, 0);
+ atomic_set(&info->pmcount, 0);
/* collect all three endpoints */
rv = usbnet_get_endpoints(dev, intf);
@@ -251,7 +260,7 @@ static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf)
dev->status = NULL;
/* save subdriver struct for suspend/resume wrappers */
- dev->data[0] = (unsigned long)subdriver;
+ info->subdriver = subdriver;
err:
return rv;
@@ -282,12 +291,12 @@ err:
static void qmi_wwan_unbind_shared(struct usbnet *dev, struct usb_interface *intf)
{
- struct usb_driver *subdriver = (void *)dev->data[0];
+ struct qmi_wwan_state *info = (void *)&dev->data;
- if (subdriver && subdriver->disconnect)
- subdriver->disconnect(intf);
+ if (info->subdriver && info->subdriver->disconnect)
+ info->subdriver->disconnect(intf);
- dev->data[0] = (unsigned long)NULL;
+ info->subdriver = NULL;
}
/* suspend/resume wrappers calling both usbnet and the cdc-wdm
@@ -299,15 +308,15 @@ static void qmi_wwan_unbind_shared(struct usbnet *dev, struct usb_interface *int
static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message)
{
struct usbnet *dev = usb_get_intfdata(intf);
- struct usb_driver *subdriver = (void *)dev->data[0];
+ struct qmi_wwan_state *info = (void *)&dev->data;
int ret;
ret = usbnet_suspend(intf, message);
if (ret < 0)
goto err;
- if (subdriver && subdriver->suspend)
- ret = subdriver->suspend(intf, message);
+ if (info->subdriver && info->subdriver->suspend)
+ ret = info->subdriver->suspend(intf, message);
if (ret < 0)
usbnet_resume(intf);
err:
@@ -317,16 +326,16 @@ err:
static int qmi_wwan_resume(struct usb_interface *intf)
{
struct usbnet *dev = usb_get_intfdata(intf);
- struct usb_driver *subdriver = (void *)dev->data[0];
+ struct qmi_wwan_state *info = (void *)&dev->data;
int ret = 0;
- if (subdriver && subdriver->resume)
- ret = subdriver->resume(intf);
+ if (info->subdriver && info->subdriver->resume)
+ ret = info->subdriver->resume(intf);
if (ret < 0)
goto err;
ret = usbnet_resume(intf);
- if (ret < 0 && subdriver && subdriver->resume && subdriver->suspend)
- subdriver->suspend(intf, PMSG_SUSPEND);
+ if (ret < 0 && info->subdriver && info->subdriver->resume && info->subdriver->suspend)
+ info->subdriver->suspend(intf, PMSG_SUSPEND);
err:
return ret;
}
--
1.7.10
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH net-next 5/5] net: qmi_wwan: use module_usb_driver macro
From: Bjørn Mork @ 2012-06-19 10:42 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: Oliver Neukum, Dan Williams, linux-usb-u79uwXL29TY76Z2rM5mHXA,
Andrew Bird (Sphere Systems), Bjørn Mork
In-Reply-To: <1340102523-23990-1-git-send-email-bjorn-yOkvZcmFvRU@public.gmane.org>
Signed-off-by: Bjørn Mork <bjorn-yOkvZcmFvRU@public.gmane.org>
---
drivers/net/usb/qmi_wwan.c | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index f12ba3c..f1e7791 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -593,17 +593,7 @@ static struct usb_driver qmi_wwan_driver = {
.disable_hub_initiated_lpm = 1,
};
-static int __init qmi_wwan_init(void)
-{
- return usb_register(&qmi_wwan_driver);
-}
-module_init(qmi_wwan_init);
^ permalink raw reply related
* [PATCH net-next 4/5] net: qmi_wwan: shorten driver description
From: Bjørn Mork @ 2012-06-19 10:42 UTC (permalink / raw)
To: netdev
Cc: Oliver Neukum, Dan Williams, linux-usb,
Andrew Bird (Sphere Systems), Bjørn Mork
In-Reply-To: <1340102523-23990-1-git-send-email-bjorn@mork.no>
The description is used in ethtool fixed length fields. Make
it shorter to avoid truncation.
Signed-off-by: Bjørn Mork <bjorn@mork.no>
---
drivers/net/usb/qmi_wwan.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 05571fc..f12ba3c 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -360,7 +360,7 @@ err:
}
static const struct driver_info qmi_wwan_info = {
- .description = "QMI speaking wwan device",
+ .description = "WWAN/QMI device",
.flags = FLAG_WWAN,
.bind = qmi_wwan_bind,
.unbind = qmi_wwan_unbind,
@@ -368,7 +368,7 @@ static const struct driver_info qmi_wwan_info = {
};
static const struct driver_info qmi_wwan_shared = {
- .description = "QMI speaking wwan device with combined interface",
+ .description = "WWAN/QMI device",
.flags = FLAG_WWAN,
.bind = qmi_wwan_bind_shared,
.unbind = qmi_wwan_unbind,
--
1.7.10
^ permalink raw reply related
* [PATCH net-next 2/5] net: qmi_wwan: rearranging to prepare for code sharing
From: Bjørn Mork @ 2012-06-19 10:42 UTC (permalink / raw)
To: netdev
Cc: Oliver Neukum, Dan Williams, linux-usb,
Andrew Bird (Sphere Systems), Bjørn Mork
In-Reply-To: <1340102523-23990-1-git-send-email-bjorn@mork.no>
Most of the subdriver registration code can be reused for devices
with separate control and data interfaces. Move the code a bit
around to prepare for such reuse.
Signed-off-by: Bjørn Mork <bjorn@mork.no>
---
drivers/net/usb/qmi_wwan.c | 128 ++++++++++++++++++++++++++------------------
1 file changed, 76 insertions(+), 52 deletions(-)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index c7b9be8..6fcf54d 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -58,9 +58,80 @@
struct qmi_wwan_state {
struct usb_driver *subdriver;
atomic_t pmcount;
- unsigned long unused[3];
+ unsigned long unused;
+ struct usb_interface *control;
+ struct usb_interface *data;
};
+/* using a counter to merge subdriver requests with our own into a combined state */
+static int qmi_wwan_manage_power(struct usbnet *dev, int on)
+{
+ struct qmi_wwan_state *info = (void *)&dev->data;
+ int rv = 0;
+
+ dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(&info->pmcount), on);
+
+ if ((on && atomic_add_return(1, &info->pmcount) == 1) || (!on && atomic_dec_and_test(&info->pmcount))) {
+ /* need autopm_get/put here to ensure the usbcore sees the new value */
+ rv = usb_autopm_get_interface(dev->intf);
+ if (rv < 0)
+ goto err;
+ dev->intf->needs_remote_wakeup = on;
+ usb_autopm_put_interface(dev->intf);
+ }
+err:
+ return rv;
+}
+
+static int qmi_wwan_cdc_wdm_manage_power(struct usb_interface *intf, int on)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ return qmi_wwan_manage_power(dev, on);
+}
+
+/* collect all three endpoints and register subdriver */
+static int qmi_wwan_register_subdriver(struct usbnet *dev)
+{
+ int rv;
+ struct usb_driver *subdriver = NULL;
+ struct qmi_wwan_state *info = (void *)&dev->data;
+
+ /* collect bulk endpoints */
+ rv = usbnet_get_endpoints(dev, info->data);
+ if (rv < 0)
+ goto err;
+
+ /* update status endpoint if separate control interface */
+ if (info->control != info->data)
+ dev->status = &info->control->cur_altsetting->endpoint[0];
+
+ /* require interrupt endpoint for subdriver */
+ if (!dev->status) {
+ rv = -EINVAL;
+ goto err;
+ }
+
+ /* for subdriver power management */
+ atomic_set(&info->pmcount, 0);
+
+ /* register subdriver */
+ subdriver = usb_cdc_wdm_register(info->control, &dev->status->desc, 512, &qmi_wwan_cdc_wdm_manage_power);
+ if (IS_ERR(subdriver)) {
+ dev_err(&info->control->dev, "subdriver registration failed\n");
+ rv = PTR_ERR(subdriver);
+ goto err;
+ }
+
+ /* prevent usbnet from using status endpoint */
+ dev->status = NULL;
+
+ /* save subdriver struct for suspend/resume wrappers */
+ info->subdriver = subdriver;
+
+err:
+ return rv;
+}
+
static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
{
int status = -1;
@@ -183,32 +254,6 @@ err:
return status;
}
-/* using a counter to merge subdriver requests with our own into a combined state */
-static int qmi_wwan_manage_power(struct usbnet *dev, int on)
-{
- struct qmi_wwan_state *info = (void *)&dev->data;
- int rv = 0;
-
- dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(&info->pmcount), on);
-
- if ((on && atomic_add_return(1, &info->pmcount) == 1) || (!on && atomic_dec_and_test(&info->pmcount))) {
- /* need autopm_get/put here to ensure the usbcore sees the new value */
- rv = usb_autopm_get_interface(dev->intf);
- if (rv < 0)
- goto err;
- dev->intf->needs_remote_wakeup = on;
- usb_autopm_put_interface(dev->intf);
- }
-err:
- return rv;
-}
-
-static int qmi_wwan_cdc_wdm_manage_power(struct usb_interface *intf, int on)
-{
- struct usbnet *dev = usb_get_intfdata(intf);
- return qmi_wwan_manage_power(dev, on);
-}
-
/* Some devices combine the "control" and "data" functions into a
* single interface with all three endpoints: interrupt + bulk in and
* out
@@ -220,7 +265,6 @@ static int qmi_wwan_cdc_wdm_manage_power(struct usb_interface *intf, int on)
static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf)
{
int rv;
- struct usb_driver *subdriver = NULL;
struct qmi_wwan_state *info = (void *)&dev->data;
/* ZTE makes devices where the interface descriptors and endpoint
@@ -237,30 +281,10 @@ static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf)
goto err;
}
- atomic_set(&info->pmcount, 0);
-
- /* collect all three endpoints */
- rv = usbnet_get_endpoints(dev, intf);
- if (rv < 0)
- goto err;
-
- /* require interrupt endpoint for subdriver */
- if (!dev->status) {
- rv = -EINVAL;
- goto err;
- }
-
- subdriver = usb_cdc_wdm_register(intf, &dev->status->desc, 512, &qmi_wwan_cdc_wdm_manage_power);
- if (IS_ERR(subdriver)) {
- rv = PTR_ERR(subdriver);
- goto err;
- }
-
- /* can't let usbnet use the interrupt endpoint */
- dev->status = NULL;
-
- /* save subdriver struct for suspend/resume wrappers */
- info->subdriver = subdriver;
+ /* control and data is shared */
+ info->control = intf;
+ info->data = intf;
+ rv = qmi_wwan_register_subdriver(dev);
err:
return rv;
--
1.7.10
^ permalink raw reply related
* [PATCH net-next 3/5] net: qmi_wwan: bind to both control and data interface
From: Bjørn Mork @ 2012-06-19 10:42 UTC (permalink / raw)
To: netdev
Cc: Oliver Neukum, Dan Williams, linux-usb,
Andrew Bird (Sphere Systems), Bjørn Mork,
Thomas Schäfer
In-Reply-To: <1340102523-23990-1-git-send-email-bjorn@mork.no>
Always bind to control interface regardless of whether
it is a shared interface or not.
A QMI/wwan function is required to provide both a control
interface (QMI) and a data interface (wwan). All devices
supported by this driver do so. But the vendors may
choose to use different USB descriptor layouts, and some
vendors even allow the same device to present different
layouts.
Most of these devices use a USB descriptor layout with a
single USB interface for both control and data. But some
split control and data into two interfaces, bound together
by a CDC Union descriptor on the control interface. Before
the cdc-wdm subdriver support was added, this split was
used to let cdc-wdm drive the QMI control interface and
qmi_wwan drive the wwna data interface.
This split driver model has a number of issues:
- qmi_wwan must match on the data interface descriptor,
which often are indistiguishable from data interfaces
belonging to other CDC (like) functions like ACM
- supporting a single QMI/wwan function requires adding
the device to two drivers
- syncronizing the probes among a number of drivers, to
ensure selecting the correct driver, is difficult unless
all drivers match on the same interface
This patch resolves these problems by using the same
probing mechanism as cdc-ether for devices with a two-
interface USB descriptor layout. This makes the driver
behave consistently, supporting both the control and data
part of the QMI/wwan function, regardless of the USB
descriptors.
Cc: Thomas Schäfer <tschaefer@t-online.de>
Signed-off-by: Bjørn Mork <bjorn@mork.no>
---
drivers/net/usb/qmi_wwan.c | 131 +++++++++++++++++++++-----------------------
1 file changed, 63 insertions(+), 68 deletions(-)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 6fcf54d..05571fc 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -1,6 +1,10 @@
/*
* Copyright (c) 2012 Bjørn Mork <bjorn@mork.no>
*
+ * The probing code is heavily inspired by cdc_ether, which is:
+ * Copyright (C) 2003-2005 by David Brownell
+ * Copyright (C) 2006 by Ole Andre Vadla Ravnas (ActiveSync)
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -15,11 +19,7 @@
#include <linux/usb/usbnet.h>
#include <linux/usb/cdc-wdm.h>
-/* The name of the CDC Device Management driver */
-#define DM_DRIVER "cdc_wdm"
-
-/*
- * This driver supports wwan (3G/LTE/?) devices using a vendor
+/* This driver supports wwan (3G/LTE/?) devices using a vendor
* specific management protocol called Qualcomm MSM Interface (QMI) -
* in addition to the more common AT commands over serial interface
* management
@@ -31,27 +31,16 @@
* management protocol is used in place of the standard CDC
* notifications NOTIFY_NETWORK_CONNECTION and NOTIFY_SPEED_CHANGE
*
+ * Alternatively, control and data functions can be combined in a
+ * single USB interface.
+ *
* Handling a protocol like QMI is out of the scope for any driver.
- * It can be exported as a character device using the cdc-wdm driver,
- * which will enable userspace applications ("modem managers") to
- * handle it. This may be required to use the network interface
- * provided by the driver.
+ * It is exported as a character device using the cdc-wdm driver as
+ * a subdriver, enabling userspace applications ("modem managers") to
+ * handle it.
*
* These devices may alternatively/additionally be configured using AT
- * commands on any of the serial interfaces driven by the option driver
- *
- * This driver binds only to the data ("slave") interface to enable
- * the cdc-wdm driver to bind to the control interface. It still
- * parses the CDC functional descriptors on the control interface to
- * a) verify that this is indeed a handled interface (CDC Union
- * header lists it as slave)
- * b) get MAC address and other ethernet config from the CDC Ethernet
- * header
- * c) enable user bind requests against the control interface, which
- * is the common way to bind to CDC Ethernet Control Model type
- * interfaces
- * d) provide a hint to the user about which interface is the
- * corresponding management interface
+ * commands on a serial interface
*/
/* driver specific data */
@@ -135,7 +124,6 @@ err:
static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
{
int status = -1;
- struct usb_interface *control = NULL;
u8 *buf = intf->cur_altsetting->extra;
int len = intf->cur_altsetting->extralen;
struct usb_interface_descriptor *desc = &intf->cur_altsetting->desc;
@@ -143,27 +131,14 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
struct usb_cdc_ether_desc *cdc_ether = NULL;
u32 required = 1 << USB_CDC_HEADER_TYPE | 1 << USB_CDC_UNION_TYPE;
u32 found = 0;
+ struct usb_driver *driver = driver_of(intf);
struct qmi_wwan_state *info = (void *)&dev->data;
BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state)));
- atomic_set(&info->pmcount, 0);
-
- /*
- * assume a data interface has no additional descriptors and
- * that the control and data interface are numbered
- * consecutively - this holds for the Huawei device at least
- */
- if (len == 0 && desc->bInterfaceNumber > 0) {
- control = usb_ifnum_to_if(dev->udev, desc->bInterfaceNumber - 1);
- if (!control)
- goto err;
-
- buf = control->cur_altsetting->extra;
- len = control->cur_altsetting->extralen;
- dev_dbg(&intf->dev, "guessing \"control\" => %s, \"data\" => this\n",
- dev_name(&control->dev));
- }
+ /* require a single interrupt status endpoint for subdriver */
+ if (intf->cur_altsetting->desc.bNumEndpoints != 1)
+ goto err;
while (len > 3) {
struct usb_descriptor_header *h = (void *)buf;
@@ -227,10 +202,17 @@ next_desc:
goto err;
}
- /* give the user a helpful hint if trying to bind to the wrong interface */
- if (cdc_union && desc->bInterfaceNumber == cdc_union->bMasterInterface0) {
- dev_err(&intf->dev, "leaving \"control\" interface for " DM_DRIVER " - try binding to %s instead!\n",
- dev_name(&usb_ifnum_to_if(dev->udev, cdc_union->bSlaveInterface0)->dev));
+ /* verify CDC Union */
+ if (desc->bInterfaceNumber != cdc_union->bMasterInterface0) {
+ dev_err(&intf->dev, "bogus CDC Union: master=%u\n", cdc_union->bMasterInterface0);
+ goto err;
+ }
+
+ /* need to save these for unbind */
+ info->control = intf;
+ info->data = usb_ifnum_to_if(dev->udev, cdc_union->bSlaveInterface0);
+ if (!info->data) {
+ dev_err(&intf->dev, "bogus CDC Union: slave=%u\n", cdc_union->bSlaveInterface0);
goto err;
}
@@ -240,15 +222,16 @@ next_desc:
usbnet_get_ethernet_addr(dev, cdc_ether->iMACAddress);
}
- /* success! point the user to the management interface */
- if (control)
- dev_info(&intf->dev, "Use \"" DM_DRIVER "\" for QMI interface %s\n",
- dev_name(&control->dev));
-
- /* XXX: add a sysfs symlink somewhere to help management applications find it? */
+ /* claim data interface and set it up */
+ status = usb_driver_claim_interface(driver, info->data, dev);
+ if (status < 0)
+ goto err;
- /* collect bulk endpoints now that we know intf == "data" interface */
- status = usbnet_get_endpoints(dev, intf);
+ status = qmi_wwan_register_subdriver(dev);
+ if (status < 0) {
+ usb_set_intfdata(info->data, NULL);
+ usb_driver_release_interface(driver, info->data);
+ }
err:
return status;
@@ -257,11 +240,7 @@ err:
/* Some devices combine the "control" and "data" functions into a
* single interface with all three endpoints: interrupt + bulk in and
* out
- *
- * Setting up cdc-wdm as a subdriver owning the interrupt endpoint
- * will let it provide userspace access to the encapsulated QMI
- * protocol without interfering with the usbnet operations.
- */
+ */
static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf)
{
int rv;
@@ -313,14 +292,30 @@ err:
return rv;
}
-static void qmi_wwan_unbind_shared(struct usbnet *dev, struct usb_interface *intf)
+static void qmi_wwan_unbind(struct usbnet *dev, struct usb_interface *intf)
{
struct qmi_wwan_state *info = (void *)&dev->data;
+ struct usb_driver *driver = driver_of(intf);
+ struct usb_interface *other;
if (info->subdriver && info->subdriver->disconnect)
- info->subdriver->disconnect(intf);
+ info->subdriver->disconnect(info->control);
+
+ /* allow user to unbind using either control or data */
+ if (intf == info->control)
+ other = info->data;
+ else
+ other = info->control;
+
+ /* only if not shared */
+ if (other && intf != other) {
+ usb_set_intfdata(other, NULL);
+ usb_driver_release_interface(driver, other);
+ }
info->subdriver = NULL;
+ info->data = NULL;
+ info->control = NULL;
}
/* suspend/resume wrappers calling both usbnet and the cdc-wdm
@@ -364,11 +359,11 @@ err:
return ret;
}
-
static const struct driver_info qmi_wwan_info = {
.description = "QMI speaking wwan device",
.flags = FLAG_WWAN,
.bind = qmi_wwan_bind,
+ .unbind = qmi_wwan_unbind,
.manage_power = qmi_wwan_manage_power,
};
@@ -376,7 +371,7 @@ static const struct driver_info qmi_wwan_shared = {
.description = "QMI speaking wwan device with combined interface",
.flags = FLAG_WWAN,
.bind = qmi_wwan_bind_shared,
- .unbind = qmi_wwan_unbind_shared,
+ .unbind = qmi_wwan_unbind,
.manage_power = qmi_wwan_manage_power,
};
@@ -384,7 +379,7 @@ static const struct driver_info qmi_wwan_gobi = {
.description = "Qualcomm Gobi wwan/QMI device",
.flags = FLAG_WWAN,
.bind = qmi_wwan_bind_gobi,
- .unbind = qmi_wwan_unbind_shared,
+ .unbind = qmi_wwan_unbind,
.manage_power = qmi_wwan_manage_power,
};
@@ -393,7 +388,7 @@ static const struct driver_info qmi_wwan_force_int1 = {
.description = "Qualcomm WWAN/QMI device",
.flags = FLAG_WWAN,
.bind = qmi_wwan_bind_shared,
- .unbind = qmi_wwan_unbind_shared,
+ .unbind = qmi_wwan_unbind,
.manage_power = qmi_wwan_manage_power,
.data = BIT(1), /* interface whitelist bitmap */
};
@@ -402,7 +397,7 @@ static const struct driver_info qmi_wwan_force_int4 = {
.description = "Qualcomm WWAN/QMI device",
.flags = FLAG_WWAN,
.bind = qmi_wwan_bind_shared,
- .unbind = qmi_wwan_unbind_shared,
+ .unbind = qmi_wwan_unbind,
.manage_power = qmi_wwan_manage_power,
.data = BIT(4), /* interface whitelist bitmap */
};
@@ -424,7 +419,7 @@ static const struct driver_info qmi_wwan_sierra = {
.description = "Sierra Wireless wwan/QMI device",
.flags = FLAG_WWAN,
.bind = qmi_wwan_bind_gobi,
- .unbind = qmi_wwan_unbind_shared,
+ .unbind = qmi_wwan_unbind,
.manage_power = qmi_wwan_manage_power,
.data = BIT(8) | BIT(19), /* interface whitelist bitmap */
};
@@ -440,7 +435,7 @@ static const struct usb_device_id products[] = {
.idVendor = HUAWEI_VENDOR_ID,
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
.bInterfaceSubClass = 1,
- .bInterfaceProtocol = 8, /* NOTE: This is the *slave* interface of the CDC Union! */
+ .bInterfaceProtocol = 9, /* CDC Ethernet *control* interface */
.driver_info = (unsigned long)&qmi_wwan_info,
},
{ /* Vodafone/Huawei K5005 (12d1:14c8) and similar modems */
@@ -448,7 +443,7 @@ static const struct usb_device_id products[] = {
.idVendor = HUAWEI_VENDOR_ID,
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
.bInterfaceSubClass = 1,
- .bInterfaceProtocol = 56, /* NOTE: This is the *slave* interface of the CDC Union! */
+ .bInterfaceProtocol = 57, /* CDC Ethernet *control* interface */
.driver_info = (unsigned long)&qmi_wwan_info,
},
{ /* Huawei E392, E398 and possibly others in "Windows mode"
--
1.7.10
^ permalink raw reply related
* Patches depending on changes in usb-next
From: Bjørn Mork @ 2012-06-19 10:52 UTC (permalink / raw)
To: netdev
Hello,
I have a couple of 3.6 patches for the qmi_wwan driver which depend on
81df2d5 USB: allow match on bInterfaceNumber
fec1868 USB: properly pad out usb_device_id.driver_info
only available in usb-next. Do you prefer that I hold on to these until
after the 3.6 merge window? They only affect module aliases and
probing so the risk isn't too high, although they do represent quite
major changes in that particular area.
Bjørn
^ 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