* Re: [PATCH] tcp: assign the sock correctly to an outgoing SYNACK packet
From: Paul Moore @ 2013-04-08 21:09 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev, mvadkert
In-Reply-To: <1365454501.3887.45.camel@edumazet-glaptop>
On Monday, April 08, 2013 01:55:01 PM Eric Dumazet wrote:
> On Mon, 2013-04-08 at 16:37 -0400, Paul Moore wrote:
> > The people who use this functionality almost never use upstream kernels,
> > they need to protection/certification/warm-fuzzies/etc. that come from a
> > distribution kernel and a support infrastructure. I didn't catch it
> > because I use a slightly different configuration that didn't expose this
> > bug; while I would like to run a full regression test every release I
> > simply don't have the time to do that myself.
> >
> > > This sounds like a very small issue to me, a revert is simply overkill.
> >
> > It all depends on your use case. To you, whom I assume doesn't use
> > SELinux, it is indeed a trivial issue. To someone who relies on SELinux
> > for its network access controls this is a pretty significant issue.
>
> Is the patch I sent addressing the problem or not ?
>
> Note that I do have : CONFIG_SECURITY=y
>
> So this patch basically adds the overhead back, and I'll have to use
> real hook later in net-next.
Please repost the patch to the LSM list, it needs to be discussed there.
> At least my patch clearly _shows_ the security requirement, instead of
> relying on a side effect of a previous sock_wmalloc()
I don't see it as a side effect, and as far as demonstration, I think the
SELinux network access controls in their entirety shows the security
requirement. If we want to make the security requirements even more explicit
in the networking stack, let's add a security blob to the sk_buff and allow
some proper LSM hooks.
> Again, it would be nice you understand the plan.
I have no idea what the above sentence is trying to say.
--
paul moore
security and virtualization @ redhat
^ permalink raw reply
* Re: [PATCH] tcp: assign the sock correctly to an outgoing SYNACK packet
From: Paul Moore @ 2013-04-08 21:10 UTC (permalink / raw)
To: David Miller
Cc: Eric Dumazet, netdev, mvadkert, selinux, linux-security-module
In-Reply-To: <31036542.d4Dp22e6Ij@sifl>
On Monday, April 08, 2013 02:32:00 PM Paul Moore wrote:
> On Monday, April 08, 2013 02:12:01 PM Paul Moore wrote:
> > On Monday, April 08, 2013 10:47:47 AM Eric Dumazet wrote:
> > > On Mon, 2013-04-08 at 13:40 -0400, Paul Moore wrote:
> > > > Sort of a similar problem, but not really the same. Also, arguably,
> > > > there is no real associated sock/socket for a RST so orphaning the
> > > > packet makes sense. In the case of a SYNACK we can, and should,
> > > > associate the packet with a sock/socket.
> > >
> > > What is the intent ?
> >
> > We have to do a number of painful things in SELinux because we aren't
> > allowed a proper security blob (void *security) in a sk_buff. One of
> > those things ...
>
> Actually, I wonder if this problem means it is a good time to revisit the
> no- security-blob-in-sk_buff decision? The management of the blob would be
> hidden behind the LSM hooks like everything else and it would have a number
> of advantages including making problems like we are seeing here easier to
> fix or avoid entirely. It would also make life much easier for those of
> working on LSM stuff and it would pave the way for including network access
> controls in the stacked-LSM stuff Casey is kicking around.
No comment, or am I just too anxious?
--
paul moore
security and virtualization @ redhat
^ permalink raw reply
* Re: [PATCH] rtnetlink: Call nlmsg_parse() with correct header length
From: David Miller @ 2013-04-08 21:12 UTC (permalink / raw)
To: mark.d.rustad; +Cc: michael.riesch, netdev, gregkh, jbenc, tytso, linux-kernel
In-Reply-To: <CD31A507-C3E1-4499-9F06-2F83B3FBFE61@intel.com>
From: "Rustad, Mark D" <mark.d.rustad@intel.com>
Date: Mon, 8 Apr 2013 18:13:36 +0000
> On Apr 8, 2013, at 8:45 AM, Michael Riesch <michael.riesch@omicron.at> wrote:
>
>>
>> Signed-off-by: Michael Riesch <michael.riesch@omicron.at>
...
> I found that fcoemon has also been triggering these messages for
> some time. I found the same problem and arrived at exactly the same
> solution. I would have already sent it, but it is still in
> validation. As far as I am concerned:
>
> Acked-by: Mark Rustad <mark.d.rustad@intel.com>
Looks good to me too, applied and queued up for -stable, thanks!
^ permalink raw reply
* Re: [PATCH] tcp: assign the sock correctly to an outgoing SYNACK packet
From: David Miller @ 2013-04-08 21:14 UTC (permalink / raw)
To: pmoore; +Cc: eric.dumazet, netdev, mvadkert
In-Reply-To: <6182509.cOVcY8B4g7@sifl>
From: Paul Moore <pmoore@redhat.com>
Date: Mon, 08 Apr 2013 17:09:32 -0400
> On Monday, April 08, 2013 01:55:01 PM Eric Dumazet wrote:
>> At least my patch clearly _shows_ the security requirement, instead of
>> relying on a side effect of a previous sock_wmalloc()
>
> I don't see it as a side effect, and as far as demonstration, I think the
> SELinux network access controls in their entirety shows the security
> requirement. If we want to make the security requirements even more explicit
> in the networking stack, let's add a security blob to the sk_buff and allow
> some proper LSM hooks.
You don't get it.
Without LSM there is no need to use sock_wmalloc() or to have a socket
context attacked to the SYN/ACK packet at all.
Therefore, the need should be explicit (Eric's approach), rather than
implicit (what you seem to be after).
^ permalink raw reply
* Re: [PATCH] tcp: assign the sock correctly to an outgoing SYNACK packet
From: David Miller @ 2013-04-08 21:15 UTC (permalink / raw)
To: pmoore; +Cc: eric.dumazet, netdev, mvadkert, selinux, linux-security-module
In-Reply-To: <3505145.vfXt1x4t0P@sifl>
From: Paul Moore <pmoore@redhat.com>
Date: Mon, 08 Apr 2013 17:10:43 -0400
> On Monday, April 08, 2013 02:32:00 PM Paul Moore wrote:
>> On Monday, April 08, 2013 02:12:01 PM Paul Moore wrote:
>> > On Monday, April 08, 2013 10:47:47 AM Eric Dumazet wrote:
>> > > On Mon, 2013-04-08 at 13:40 -0400, Paul Moore wrote:
>> > > > Sort of a similar problem, but not really the same. Also, arguably,
>> > > > there is no real associated sock/socket for a RST so orphaning the
>> > > > packet makes sense. In the case of a SYNACK we can, and should,
>> > > > associate the packet with a sock/socket.
>> > >
>> > > What is the intent ?
>> >
>> > We have to do a number of painful things in SELinux because we aren't
>> > allowed a proper security blob (void *security) in a sk_buff. One of
>> > those things ...
>>
>> Actually, I wonder if this problem means it is a good time to revisit the
>> no- security-blob-in-sk_buff decision? The management of the blob would be
>> hidden behind the LSM hooks like everything else and it would have a number
>> of advantages including making problems like we are seeing here easier to
>> fix or avoid entirely. It would also make life much easier for those of
>> working on LSM stuff and it would pave the way for including network access
>> controls in the stacked-LSM stuff Casey is kicking around.
>
> No comment, or am I just too anxious?
There is no way I'm putting LSM overhead into sk_buff, it's already
too big.
I didn't comment because it wasn't worth a comment, but since you're
pushing me on the issue, I'll make the no explicit.
^ permalink raw reply
* Re: [patch 0/2] s390: network bug fixes for net [v2]
From: David Miller @ 2013-04-08 21:17 UTC (permalink / raw)
To: frank.blaschka; +Cc: netdev, linux-s390
In-Reply-To: <20130408081925.995757091@de.ibm.com>
From: frank.blaschka@de.ibm.com
Date: Mon, 08 Apr 2013 10:19:25 +0200
> here are the fixes for net again, including
> feedback from Eric (Thx!)
Both applied, thanks.
^ permalink raw reply
* Re: [PATCH] tcp: assign the sock correctly to an outgoing SYNACK packet
From: Eric Dumazet @ 2013-04-08 21:17 UTC (permalink / raw)
To: Paul Moore; +Cc: David Miller, netdev, mvadkert
In-Reply-To: <6182509.cOVcY8B4g7@sifl>
On Mon, 2013-04-08 at 17:09 -0400, Paul Moore wrote:
> I have no idea what the above sentence is trying to say.
I guess the amount of mails exchanged today on this subject is kind of
astonishing. I am truly sorry I had more urgent issues to deal with
today.
If the patch is not officially sent by you today, I'll take care of it
after my day work.
Thank you.
^ permalink raw reply
* Re: [PATCH] tcp: assign the sock correctly to an outgoing SYNACK packet
From: Paul Moore @ 2013-04-08 21:24 UTC (permalink / raw)
To: David Miller
Cc: eric.dumazet, netdev, mvadkert, selinux, linux-security-module
In-Reply-To: <20130408.171512.973275376690340387.davem@davemloft.net>
On Monday, April 08, 2013 05:15:12 PM David Miller wrote:
> From: Paul Moore <pmoore@redhat.com>
> Date: Mon, 08 Apr 2013 17:10:43 -0400
>
> > On Monday, April 08, 2013 02:32:00 PM Paul Moore wrote:
> >> On Monday, April 08, 2013 02:12:01 PM Paul Moore wrote:
> >> > On Monday, April 08, 2013 10:47:47 AM Eric Dumazet wrote:
> >> > > On Mon, 2013-04-08 at 13:40 -0400, Paul Moore wrote:
> >> > > > Sort of a similar problem, but not really the same. Also,
> >> > > > arguably,
> >> > > > there is no real associated sock/socket for a RST so orphaning the
> >> > > > packet makes sense. In the case of a SYNACK we can, and should,
> >> > > > associate the packet with a sock/socket.
> >> > >
> >> > > What is the intent ?
> >> >
> >> > We have to do a number of painful things in SELinux because we aren't
> >> > allowed a proper security blob (void *security) in a sk_buff. One of
> >> > those things ...
> >>
> >> Actually, I wonder if this problem means it is a good time to revisit the
> >> no- security-blob-in-sk_buff decision? The management of the blob would
> >> be hidden behind the LSM hooks like everything else and it would have a
> >> number of advantages including making problems like we are seeing here
> >> easier to fix or avoid entirely. It would also make life much easier for
> >> those of working on LSM stuff and it would pave the way for including
> >> network access controls in the stacked-LSM stuff Casey is kicking around.
> >
> > No comment, or am I just too anxious?
>
> There is no way I'm putting LSM overhead into sk_buff, it's already
> too big.
If the void pointer is wrapped by a #ifdef (plenty of precedence for that) and
the management of that pointer is handled by LSM hooks why is it a concern? I
apologize for pushing on the issue, but I'm having a hard time reconciling the
reason for the "no" with the comments/decisions about the regression fix; at
present there seems to be a level of contradiction between the two.
> I didn't comment because it wasn't worth a comment, but since you're
> pushing me on the issue, I'll make the no explicit.
--
paul moore
security and virtualization @ redhat
^ permalink raw reply
* Re: [PATCH] tcp: assign the sock correctly to an outgoing SYNACK packet
From: David Miller @ 2013-04-08 21:33 UTC (permalink / raw)
To: pmoore; +Cc: eric.dumazet, netdev, mvadkert, selinux, linux-security-module
In-Reply-To: <2921619.mqaHl5PnPI@sifl>
From: Paul Moore <pmoore@redhat.com>
Date: Mon, 08 Apr 2013 17:24:50 -0400
> If the void pointer is wrapped by a #ifdef (plenty of precedence for that) and
> the management of that pointer is handled by LSM hooks why is it a concern? I
> apologize for pushing on the issue, but I'm having a hard time reconciling the
> reason for the "no" with the comments/decisions about the regression fix; at
> present there seems to be a level of contradiction between the two.
8 bytes times however many millions of packets per second we can process
on a big machine, you do the math.
It's memory, less cache locality, etc. etc. etc.
It's the most important data structure in the entire networking stack,
and every single byte matters.
I want the overhead to be your problem, so that only users of your
stuff eat the overhead, rather than everyone.
And don't even mention ifdefs, that's bogus, because every
distribution turns every option on, %99.9999999 of users will
therefore not see the savings.
Really, this is a dead topic, let's move on.
Thanks.
^ permalink raw reply
* Re: [PATCH] tcp: assign the sock correctly to an outgoing SYNACK packet
From: Ben Hutchings @ 2013-04-08 21:34 UTC (permalink / raw)
To: Paul Moore
Cc: David Miller, eric.dumazet, netdev, mvadkert, selinux,
linux-security-module
In-Reply-To: <2921619.mqaHl5PnPI@sifl>
On Mon, 2013-04-08 at 17:24 -0400, Paul Moore wrote:
> On Monday, April 08, 2013 05:15:12 PM David Miller wrote:
> > From: Paul Moore <pmoore@redhat.com>
> > Date: Mon, 08 Apr 2013 17:10:43 -0400
> >
> > > On Monday, April 08, 2013 02:32:00 PM Paul Moore wrote:
> > >> On Monday, April 08, 2013 02:12:01 PM Paul Moore wrote:
> > >> > On Monday, April 08, 2013 10:47:47 AM Eric Dumazet wrote:
> > >> > > On Mon, 2013-04-08 at 13:40 -0400, Paul Moore wrote:
> > >> > > > Sort of a similar problem, but not really the same. Also,
> > >> > > > arguably,
> > >> > > > there is no real associated sock/socket for a RST so orphaning the
> > >> > > > packet makes sense. In the case of a SYNACK we can, and should,
> > >> > > > associate the packet with a sock/socket.
> > >> > >
> > >> > > What is the intent ?
> > >> >
> > >> > We have to do a number of painful things in SELinux because we aren't
> > >> > allowed a proper security blob (void *security) in a sk_buff. One of
> > >> > those things ...
> > >>
> > >> Actually, I wonder if this problem means it is a good time to revisit the
> > >> no- security-blob-in-sk_buff decision? The management of the blob would
> > >> be hidden behind the LSM hooks like everything else and it would have a
> > >> number of advantages including making problems like we are seeing here
> > >> easier to fix or avoid entirely. It would also make life much easier for
> > >> those of working on LSM stuff and it would pave the way for including
> > >> network access controls in the stacked-LSM stuff Casey is kicking around.
> > >
> > > No comment, or am I just too anxious?
> >
> > There is no way I'm putting LSM overhead into sk_buff, it's already
> > too big.
>
> If the void pointer is wrapped by a #ifdef (plenty of precedence for that) and
> the management of that pointer is handled by LSM hooks why is it a concern? I
> apologize for pushing on the issue, but I'm having a hard time reconciling the
> reason for the "no" with the comments/decisions about the regression fix; at
> present there seems to be a level of contradiction between the two.
Most Linux users are running distribution kernels with one or more LSMs
built-in. Anything you make dependent on CONFIG_SECURITY or similar
generic symbol will have a cost for all those users, whether or not they
actually use the LSM.
Ben.
> > I didn't comment because it wasn't worth a comment, but since you're
> > pushing me on the issue, I'll make the no explicit.
>
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH] tcp: assign the sock correctly to an outgoing SYNACK packet
From: Paul Moore @ 2013-04-08 22:01 UTC (permalink / raw)
To: David Miller
Cc: eric.dumazet, netdev, mvadkert, selinux, linux-security-module
In-Reply-To: <20130408.173325.1683493727549657170.davem@davemloft.net>
On Monday, April 08, 2013 05:33:25 PM David Miller wrote:
> From: Paul Moore <pmoore@redhat.com>
> Date: Mon, 08 Apr 2013 17:24:50 -0400
>
> > If the void pointer is wrapped by a #ifdef (plenty of precedence for that)
> > and the management of that pointer is handled by LSM hooks why is it a
> > concern? I apologize for pushing on the issue, but I'm having a hard
> > time reconciling the reason for the "no" with the comments/decisions
> > about the regression fix; at present there seems to be a level of
> > contradiction between the two.
>
> 8 bytes times however many millions of packets per second we can process
> on a big machine, you do the math.
>
> It's memory, less cache locality, etc. etc. etc.
>
> It's the most important data structure in the entire networking stack,
> and every single byte matters.
>
> I want the overhead to be your problem, so that only users of your
> stuff eat the overhead, rather than everyone.
Okay, if the objection is really just one of structure size and not the hooks,
what if I did the work to consolidate the skb->secmark and skb->sp fields into
a new structure/pointer? Assuming it wasn't too painful, it would be a net
reduction of four bytes. If that worked would you have an objection to us
adding a LSM security blob to this new structure?
--
paul moore
security and virtualization @ redhat
^ permalink raw reply
* Re: [PATCH] tcp: assign the sock correctly to an outgoing SYNACK packet
From: David Miller @ 2013-04-08 22:08 UTC (permalink / raw)
To: pmoore; +Cc: eric.dumazet, netdev, mvadkert, selinux, linux-security-module
In-Reply-To: <2162769.UZ73yv7g6c@sifl>
From: Paul Moore <pmoore@redhat.com>
Date: Mon, 08 Apr 2013 18:01:56 -0400
> Okay, if the objection is really just one of structure size and not the hooks,
> what if I did the work to consolidate the skb->secmark and skb->sp fields into
> a new structure/pointer? Assuming it wasn't too painful, it would be a net
> reduction of four bytes. If that worked would you have an objection to us
> adding a LSM security blob to this new structure?
'sp' is sepreate from LSM and making it indirect would hurt IPSEC
performance.
Please, really, just drop this.
Thanks.
^ permalink raw reply
* Re: [PATCH net-next] net: ipv6: add tokenized interface identifier support
From: Hannes Frederic Sowa @ 2013-04-08 22:21 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: davem, netdev, YOSHIFUJI Hideaki, Thomas Graf
In-Reply-To: <1365429690-17342-1-git-send-email-dborkman@redhat.com>
Sorry, I was a bit busy and just had more time to look at your patch
again. Perhaps you could look into my comments. (A new patch would be
needed as it already landed in net-next).
On Mon, Apr 08, 2013 at 04:01:30PM +0200, Daniel Borkmann wrote:
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index a33b157..65d8139 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -422,6 +422,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
> ipv6_regen_rndid((unsigned long) ndev);
> }
> #endif
> + memset(ndev->token.s6_addr, 0, sizeof(ndev->token.s6_addr));
ndev is allocated with __GFP_ZERO so no need to clear it. Otherwise I would do
ndev->token = in6addr_any;
to make the check in addrconf_prefix_rcv more clear.
> +static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token)
> +{
> + struct in6_addr ll_addr;
> + struct inet6_ifaddr *ifp;
> + struct net_device *dev = idev->dev;
> +
> + if (token == NULL)
> + return -EINVAL;
> + if (ipv6_addr_any(token))
> + return -EINVAL;
> + if (dev->flags & (IFF_LOOPBACK | IFF_NOARP))
> + return -EINVAL;
> + if (idev->dead || !(idev->if_flags & IF_READY))
> + return -EINVAL;
> + if (!ipv6_accept_ra(idev))
> + return -EINVAL;
> + if (idev->cnf.rtr_solicits <= 0)
> + return -EINVAL;
IF_READY marks an interface which is already up. So we are not allowed to set
a token on an interface which is down? I would drop this requirement, seems
like a usability issue. ;)
> +
> + write_lock_bh(&idev->lock);
> +
> + BUILD_BUG_ON(sizeof(token->s6_addr) != 16);
> + memcpy(idev->token.s6_addr + 8, token->s6_addr + 8, 8);
> +
> + write_unlock_bh(&idev->lock);
> +
{
> + ipv6_get_lladdr(dev, &ll_addr, IFA_F_TENTATIVE | IFA_F_OPTIMISTIC);
> + ndisc_send_rs(dev, &ll_addr, &in6addr_linklocal_allrouters);
> +
> + write_lock_bh(&idev->lock);
> + idev->if_flags |= IF_RS_SENT;
}
This should then be only called if IF_READY is set. Otherwise normal ifup
handling will send out the rs. If one day there is the possibility to add more
than one token we would actually have to check the minimum solicitation
intervals. I think this does not matter now.
> +
> + /* Well, that's kinda nasty ... */
> + list_for_each_entry(ifp, &idev->addr_list, if_list) {
> + spin_lock(&ifp->lock);
> + if (ipv6_addr_src_scope(&ifp->addr) ==
> + IPV6_ADDR_SCOPE_GLOBAL) {
> + ifp->valid_lft = 0;
> + ifp->prefered_lft = 0;
> + }
> + spin_unlock(&ifp->lock);
> + }
As I understand this logic it also does deprecate current statically configured ip
addresses? Perhaps another per-inet6_ifaddr flag to mark the ip address as
token configured and just clean these address.
The flag would have to be set in addrconf_prefix_rcv if tokens are active.
Thanks,
Hannes
^ permalink raw reply
* Re: [PATCH net-next] net: ipv6: add tokenized interface identifier support
From: Daniel Borkmann @ 2013-04-08 22:27 UTC (permalink / raw)
To: davem, netdev, YOSHIFUJI Hideaki, Thomas Graf
In-Reply-To: <20130408222154.GA25696@order.stressinduktion.org>
On 04/09/2013 12:21 AM, Hannes Frederic Sowa wrote:
> Sorry, I was a bit busy and just had more time to look at your patch
> again. Perhaps you could look into my comments. (A new patch would be
> needed as it already landed in net-next).
Right, I'll prepare this follow-up patch(es) by tomorrow. Thanks for your
feedback Hannes!
> On Mon, Apr 08, 2013 at 04:01:30PM +0200, Daniel Borkmann wrote:
>> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
>> index a33b157..65d8139 100644
>> --- a/net/ipv6/addrconf.c
>> +++ b/net/ipv6/addrconf.c
>> @@ -422,6 +422,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
>> ipv6_regen_rndid((unsigned long) ndev);
>> }
>> #endif
>> + memset(ndev->token.s6_addr, 0, sizeof(ndev->token.s6_addr));
>
> ndev is allocated with __GFP_ZERO so no need to clear it. Otherwise I would do
>
> ndev->token = in6addr_any;
>
> to make the check in addrconf_prefix_rcv more clear.
>
>> +static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token)
>> +{
>> + struct in6_addr ll_addr;
>> + struct inet6_ifaddr *ifp;
>> + struct net_device *dev = idev->dev;
>> +
>> + if (token == NULL)
>> + return -EINVAL;
>> + if (ipv6_addr_any(token))
>> + return -EINVAL;
>> + if (dev->flags & (IFF_LOOPBACK | IFF_NOARP))
>> + return -EINVAL;
>> + if (idev->dead || !(idev->if_flags & IF_READY))
>> + return -EINVAL;
>> + if (!ipv6_accept_ra(idev))
>> + return -EINVAL;
>> + if (idev->cnf.rtr_solicits <= 0)
>> + return -EINVAL;
>
> IF_READY marks an interface which is already up. So we are not allowed to set
> a token on an interface which is down? I would drop this requirement, seems
> like a usability issue. ;)
>
>> +
>> + write_lock_bh(&idev->lock);
>> +
>> + BUILD_BUG_ON(sizeof(token->s6_addr) != 16);
>> + memcpy(idev->token.s6_addr + 8, token->s6_addr + 8, 8);
>> +
>> + write_unlock_bh(&idev->lock);
>> +
>
> {
>> + ipv6_get_lladdr(dev, &ll_addr, IFA_F_TENTATIVE | IFA_F_OPTIMISTIC);
>> + ndisc_send_rs(dev, &ll_addr, &in6addr_linklocal_allrouters);
>> +
>> + write_lock_bh(&idev->lock);
>> + idev->if_flags |= IF_RS_SENT;
> }
>
> This should then be only called if IF_READY is set. Otherwise normal ifup
> handling will send out the rs. If one day there is the possibility to add more
> than one token we would actually have to check the minimum solicitation
> intervals. I think this does not matter now.
>
>> +
>> + /* Well, that's kinda nasty ... */
>> + list_for_each_entry(ifp, &idev->addr_list, if_list) {
>> + spin_lock(&ifp->lock);
>> + if (ipv6_addr_src_scope(&ifp->addr) ==
>> + IPV6_ADDR_SCOPE_GLOBAL) {
>> + ifp->valid_lft = 0;
>> + ifp->prefered_lft = 0;
>> + }
>> + spin_unlock(&ifp->lock);
>> + }
>
> As I understand this logic it also does deprecate current statically configured ip
> addresses? Perhaps another per-inet6_ifaddr flag to mark the ip address as
> token configured and just clean these address.
>
> The flag would have to be set in addrconf_prefix_rcv if tokens are active.
>
> Thanks,
>
> Hannes
>
^ permalink raw reply
* Re: [PATCH] tcp: assign the sock correctly to an outgoing SYNACK packet
From: Casey Schaufler @ 2013-04-08 23:40 UTC (permalink / raw)
To: David Miller
Cc: pmoore, eric.dumazet, netdev, mvadkert, selinux,
linux-security-module, Casey Schaufler
In-Reply-To: <20130408.173325.1683493727549657170.davem@davemloft.net>
On 4/8/2013 2:33 PM, David Miller wrote:
> From: Paul Moore <pmoore@redhat.com>
> Date: Mon, 08 Apr 2013 17:24:50 -0400
>
>> If the void pointer is wrapped by a #ifdef (plenty of precedence for that) and
>> the management of that pointer is handled by LSM hooks why is it a concern? I
>> apologize for pushing on the issue, but I'm having a hard time reconciling the
>> reason for the "no" with the comments/decisions about the regression fix; at
>> present there seems to be a level of contradiction between the two.
> 8 bytes times however many millions of packets per second we can process
> on a big machine, you do the math.
OK, let's do the math.
First off, it's 4 bytes, not 8. It replaces the secmark.
Your increased memory usage is going to be
4 bytes/packet * M packets/second * N seconds
Where M is the rate at which you're processing packets and
N is the length of time it takes to process a packet.
Let's pretend we have an embedded system that does nothing but send
128 byte packets on a 10Gb port. That's 10M packets/second. If it
takes a full second to process a packet the overhead is 40MB for that
second. I have it on good authority that packets can be processed
in considerably less time than that. The real number is more like
0.05 seconds. That means your actual overhead is more like 1MB.
These are dumbed down calculations. I am not a memory usage expert.
I am convinced that "real" calculations are going to get similar
numbers. I am, of course, willing to be swayed by evidence that I
am wrong.
Compare that to the overhead associated with using CIPSO on packets
that never leave the box.
>
> It's memory, less cache locality, etc. etc. etc.
>
> It's the most important data structure in the entire networking stack,
> and every single byte matters.
>
> I want the overhead to be your problem, so that only users of your
> stuff eat the overhead, rather than everyone.
>
> And don't even mention ifdefs, that's bogus, because every
> distribution turns every option on, %99.9999999 of users will
> therefore not see the savings.
>
> Really, this is a dead topic, let's move on.
>
> Thanks.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" 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] tcp: assign the sock correctly to an outgoing SYNACK packet
From: Eric Dumazet @ 2013-04-09 0:33 UTC (permalink / raw)
To: Casey Schaufler
Cc: David Miller, pmoore, netdev, mvadkert, selinux,
linux-security-module
In-Reply-To: <51635573.7030706@schaufler-ca.com>
On Mon, 2013-04-08 at 16:40 -0700, Casey Schaufler wrote:
> OK, let's do the math.
>
> First off, it's 4 bytes, not 8. It replaces the secmark.
> Your increased memory usage is going to be
>
> 4 bytes/packet * M packets/second * N seconds
>
> Where M is the rate at which you're processing packets and
> N is the length of time it takes to process a packet.
>
> Let's pretend we have an embedded system that does nothing but send
> 128 byte packets on a 10Gb port. That's 10M packets/second. If it
> takes a full second to process a packet the overhead is 40MB for that
> second. I have it on good authority that packets can be processed
> in considerably less time than that. The real number is more like
> 0.05 seconds. That means your actual overhead is more like 1MB.
>
> These are dumbed down calculations. I am not a memory usage expert.
> I am convinced that "real" calculations are going to get similar
> numbers. I am, of course, willing to be swayed by evidence that I
> am wrong.
>
> Compare that to the overhead associated with using CIPSO on packets
> that never leave the box.
Maths are not that simple, and its not about size of sk_buff, since the
number of in-flight skb should be quite small.
Its the time to init this memory for _every_ packet.
sizeof(sk_buff) is 0xf8, very close to cross the 256 bytes limit.
Add a single _byte_ and it becomes a matter of adding a _cache_ line,
and thats 25 % cost, assuming 64bytes cache lines.
So instead of processing 10M packets per second, we would process 9M
packets per second, or maybe less.
Yes, 256 bytes per sk_buff, this is the current insane situation.
(Not counting the struct skb_shared_info, adding at least one additional
cache line)
^ permalink raw reply
* [RFC/RFT PATCH 0/2 V2] Adding a new bluetooth driver to the kernel
From: Larry Finger @ 2013-04-09 0:57 UTC (permalink / raw)
To: linville-2XuSBdqkA4R54TAoqtyWWQ
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA, Larry Finger,
netdev-u79uwXL29TY76Z2rM5mHXA, marcel-kz+m5ild9QBg9hUCZPvPmw,
gustavo-THi1TnShQwVAfugRpC6u6w,
johan.hedberg-Re5JQEeQqe8AvxtiuMwx3w,
linux-bluetooth-u79uwXL29TY76Z2rM5mHXA,
champion_chen-kXabqFNEczNtrwSWzY7KCg
These patches supply the code needed to operate the bluetooth portion of
the Realtek RTL8723AE chip. Much of the necessary code is already present
in btusb, thus that driver is changed to export the necessary routines.
The second patch implements the routines that differ from the standard
driver.
Signed-off-by: Larry Finger <Larry.Finger-tQ5ms3gMjBLk1uMJSBkQmQ@public.gmane.org>
Larry Finger (2):
btusb: Modify code for use with a similar driver
rtk_btusb: A new driver for the Bluetooth portion of the Realtek
RTL8723AE chip
drivers/bluetooth/Kconfig | 10 +
drivers/bluetooth/Makefile | 1 +
drivers/bluetooth/btusb.c | 79 +---
drivers/bluetooth/btusb.h | 88 ++++
drivers/bluetooth/rtk_btusb.c | 974 ++++++++++++++++++++++++++++++++++++++++++
drivers/bluetooth/rtk_btusb.h | 102 +++++
6 files changed, 1194 insertions(+), 60 deletions(-)
create mode 100644 drivers/bluetooth/btusb.h
create mode 100644 drivers/bluetooth/rtk_btusb.c
create mode 100644 drivers/bluetooth/rtk_btusb.h
--
1.8.1.4
^ permalink raw reply
* [RFC/RFT PATCH 2/2] rtk_btusb: A new driver for the Bluetooth portion of the Realtek RTL8723AE chip
From: Larry Finger @ 2013-04-09 0:57 UTC (permalink / raw)
To: linville-2XuSBdqkA4R54TAoqtyWWQ
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA, Larry Finger,
netdev-u79uwXL29TY76Z2rM5mHXA, marcel-kz+m5ild9QBg9hUCZPvPmw,
gustavo-THi1TnShQwVAfugRpC6u6w,
johan.hedberg-Re5JQEeQqe8AvxtiuMwx3w,
linux-bluetooth-u79uwXL29TY76Z2rM5mHXA,
champion_chen-kXabqFNEczNtrwSWzY7KCg
In-Reply-To: <1365469068-4548-1-git-send-email-Larry.Finger-tQ5ms3gMjBLk1uMJSBkQmQ@public.gmane.org>
This driver is similar to btusb, and uses as much of that code as possible.
Those parts that are unique are provided here.
Signed-off-by: Larry Finger <Larry.Finger-tQ5ms3gMjBLk1uMJSBkQmQ@public.gmane.org>
---
drivers/bluetooth/Kconfig | 10 +
drivers/bluetooth/Makefile | 1 +
drivers/bluetooth/rtk_btusb.c | 974 ++++++++++++++++++++++++++++++++++++++++++
drivers/bluetooth/rtk_btusb.h | 102 +++++
4 files changed, 1087 insertions(+)
create mode 100644 drivers/bluetooth/rtk_btusb.c
create mode 100644 drivers/bluetooth/rtk_btusb.h
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index fdfd61a..11a9e80 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -242,4 +242,14 @@ config BT_WILINK
Say Y here to compile support for Texas Instrument's WiLink7 driver
into the kernel or say M to compile it as module.
+
+config BT_RTKUSB
+ tristate "Realtek BT driver for RTL8723AE"
+ select FW_LOADER
+ help
+ This enables the Bluetooth driver for the Realtek RTL8723AE Wifi/BT
+ combo device.
+
+ Say Y here to compile support for these devices into the kernel
+ or say M to build it as a module.
endmenu
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index 4afae20..167ccc0 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_BT_ATH3K) += ath3k.o
obj-$(CONFIG_BT_MRVL) += btmrvl.o
obj-$(CONFIG_BT_MRVL_SDIO) += btmrvl_sdio.o
obj-$(CONFIG_BT_WILINK) += btwilink.o
+obj-$(CONFIG_BT_RTKUSB) += rtk_btusb.o
btmrvl-y := btmrvl_main.o
btmrvl-$(CONFIG_DEBUG_FS) += btmrvl_debugfs.o
diff --git a/drivers/bluetooth/rtk_btusb.c b/drivers/bluetooth/rtk_btusb.c
new file mode 100644
index 0000000..9a12855
--- /dev/null
+++ b/drivers/bluetooth/rtk_btusb.c
@@ -0,0 +1,974 @@
+/*
+ *
+ * Realtek Bluetooth USB driver
+ *
+ * Copyright (C) 2012-2013 Edward Bian <edward_bian-kXabqFNEczNtrwSWzY7KCg@public.gmane.org>
+ *
+ * Parts of this routine are copied and modified from btusb, the
+ * Generic Bluetooth USB driver. In addition, several of the routines
+ * in btusb are used directly. The btusb code is
+ * Copyright (C) 2005-2008 Marcel Holtmann <marcel-kz+m5ild9QBg9hUCZPvPmw@public.gmane.org>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/firmware.h>
+#include <linux/suspend.h>
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <linux/completion.h>
+#include <linux/version.h>
+#include <linux/pm_runtime.h>
+
+#include "btusb.h"
+#include "rtk_btusb.h"
+
+#define VERSION "0.8"
+
+static struct usb_driver btusb_driver;
+
+static struct patch_info patch_table[] = {
+ {0, 0x1200, "rtl_bt/rtl8723a.bin", "rtk8723_bt_config", NULL, 0}
+};
+
+static LIST_HEAD(dev_data_list);
+
+/*******************************/
+
+static struct usb_device_id btusb_table[] = {
+ {USB_DEVICE(0x0bda, 0x8723)},
+ { }
+};
+
+/*******************************/
+
+MODULE_DEVICE_TABLE(usb, btusb_table);
+
+static int send_hci_cmd(struct xchange_data *xdata)
+{
+ int ret_val;
+
+ ret_val = usb_control_msg(
+ xdata->dev_entry->udev, xdata->pipe_out,
+ 0, USB_TYPE_CLASS, 0, 0,
+ (void *)(xdata->send_pkt),
+ xdata->pkt_len, MSG_TO);
+
+ return ret_val;
+}
+
+static int rcv_hci_evt(struct xchange_data *xdata)
+{
+ int ret_len, ret_val;
+ int i;
+
+ while (1) {
+ for (i = 0; i < 5; i++) {
+ /* Try to send USB interrupt message 5 times. */
+ ret_val = usb_interrupt_msg(
+ xdata->dev_entry->udev, xdata->pipe_in,
+ (void *)(xdata->rcv_pkt), PKT_LEN,
+ &ret_len, MSG_TO);
+ if (ret_val >= 0)
+ break;
+ }
+ if (ret_val < 0)
+ return ret_val;
+
+ if (CMD_CMP_EVT == xdata->evt_hdr->evt) {
+ if (xdata->cmd_hdr->opcode == xdata->cmd_cmp->opcode)
+ return ret_len;
+ }
+ }
+}
+
+static int download_data(struct xchange_data *xdata)
+{
+ struct download_cp *cmd_para;
+ struct download_rp *evt_para;
+ uint8_t *pcur;
+ int pkt_len, frag_num, frag_len;
+ int i, ret_val;
+
+ cmd_para = (struct download_cp *)xdata->req_para;
+ evt_para = (struct download_rp *)xdata->rsp_para;
+ pcur = xdata->fw_data;
+ pkt_len = CMD_HDR_LEN + sizeof(struct download_cp);
+ frag_num = xdata->fw_len / PATCH_SEG_MAX + 1;
+ frag_len = PATCH_SEG_MAX;
+
+ for (i = 0; i < frag_num; i++) {
+ cmd_para->index = i;
+ if (i == (frag_num - 1)) {
+ cmd_para->index |= DATA_END;
+ frag_len = xdata->fw_len % PATCH_SEG_MAX;
+ pkt_len -= (PATCH_SEG_MAX - frag_len);
+ }
+ xdata->cmd_hdr->opcode = cpu_to_le16(DOWNLOAD_OPCODE);
+ xdata->cmd_hdr->plen = sizeof(uint8_t) + frag_len;
+ xdata->pkt_len = pkt_len;
+ memcpy(cmd_para->data, pcur, frag_len);
+
+ ret_val = send_hci_cmd(xdata);
+ if (ret_val < 0)
+ return ret_val;
+
+ ret_val = rcv_hci_evt(xdata);
+ if (ret_val < 0)
+ return ret_val;
+ if (0 != evt_para->status)
+ return -1;
+
+ pcur += PATCH_SEG_MAX;
+ }
+
+ return xdata->fw_len;
+}
+
+static struct dev_data *dev_data_find(struct usb_interface *intf)
+{
+ struct dev_data *dev_entry;
+
+ list_for_each_entry(dev_entry, &dev_data_list, list_node) {
+ if (dev_entry->intf == intf)
+ return dev_entry;
+ }
+
+ return NULL;
+}
+
+static void init_xdata(struct xchange_data *xdata, struct dev_data *dev_entry)
+{
+ memset(xdata, 0, sizeof(struct xchange_data));
+ xdata->dev_entry = dev_entry;
+ xdata->pipe_in = usb_rcvintpipe(dev_entry->udev, INTR_EP);
+ xdata->pipe_out = usb_sndctrlpipe(dev_entry->udev, CTRL_EP);
+ xdata->cmd_hdr = (struct hci_command_hdr *)(xdata->send_pkt);
+ xdata->evt_hdr = (struct hci_event_hdr *)(xdata->rcv_pkt);
+ xdata->cmd_cmp = (struct hci_ev_cmd_complete *)(xdata->rcv_pkt +
+ EVT_HDR_LEN);
+ xdata->req_para = xdata->send_pkt + CMD_HDR_LEN;
+ xdata->rsp_para = xdata->rcv_pkt + EVT_HDR_LEN + CMD_CMP_LEN;
+}
+
+static int check_fw_version(struct xchange_data *xdata)
+{
+ struct hci_rp_read_local_version *read_ver_rsp;
+ struct patch_info *patch_entry;
+ int ret_val;
+
+ xdata->cmd_hdr->opcode = cpu_to_le16(HCI_OP_READ_LOCAL_VERSION);
+ xdata->cmd_hdr->plen = 0;
+ xdata->pkt_len = CMD_HDR_LEN;
+
+ ret_val = send_hci_cmd(xdata);
+ if (ret_val < 0)
+ goto version_end;
+
+ ret_val = rcv_hci_evt(xdata);
+ if (ret_val < 0)
+ goto version_end;
+
+ patch_entry = xdata->dev_entry->patch_entry;
+ read_ver_rsp = (struct hci_rp_read_local_version *)(xdata->rsp_para);
+ BT_DBG("check_fw_version : read_ver_rsp->lmp_subver = 0x%x",
+ le16_to_cpu(read_ver_rsp->lmp_subver));
+ if (patch_entry->lmp_sub != le16_to_cpu(read_ver_rsp->lmp_subver))
+ return 1;
+
+ ret_val = 0;
+version_end:
+ return ret_val;
+}
+
+static void bt_fw_cb(const struct firmware *firmware, void *context)
+{
+ struct dev_data *dev_entry = context;
+
+ dev_entry->fw = firmware;
+ if (!firmware)
+ pr_err("In callback routine, firmware file not available\n");
+ complete(&dev_entry->firmware_loading_complete);
+}
+
+static int load_firmware(struct dev_data *dev_entry, uint8_t **buff)
+{
+#if LOAD_CONFIG
+ const struct firmware *fw;
+#endif
+ struct usb_device *udev;
+ struct patch_info *patch_entry;
+ char *fw_name;
+ int fw_len = 0, ret_val;
+
+ udev = dev_entry->udev;
+ init_completion(&dev_entry->firmware_loading_complete);
+ patch_entry = dev_entry->patch_entry;
+ fw_name = patch_entry->patch_name;
+ BT_DBG("Reading firmware file %s", fw_name);
+ ret_val = request_firmware_nowait(THIS_MODULE, 1, fw_name, &udev->dev,
+ GFP_KERNEL, dev_entry, bt_fw_cb);
+ if (ret_val < 0)
+ goto fw_fail;
+
+ wait_for_completion(&dev_entry->firmware_loading_complete);
+ if (!dev_entry->fw)
+ goto fw_fail;
+ *buff = kzalloc(dev_entry->fw->size, GFP_KERNEL);
+ if (NULL == *buff)
+ goto alloc_fail;
+ memcpy(*buff, dev_entry->fw->data, dev_entry->fw->size);
+ fw_len = dev_entry->fw->size;
+
+#if LOAD_CONFIG
+ release_firmware(dev_entry->fw);
+ fw_name = patch_entry->config_name;
+ ret_val = request_firmware(&fw, fw_name, &udev->dev);
+ if (ret_val < 0) {
+ fw_len = 0;
+ kfree(*buff);
+ *buff = NULL;
+ goto fw_fail;
+ }
+
+ *buff = krealloc(*buff, fw_len + fw->size, GFP_KERNEL);
+ if (NULL == *buff) {
+ fw_len = 0;
+ release_firmware(fw);
+ goto fw_fail;
+ }
+ memcpy(*buff + fw_len, fw->data, fw->size);
+ fw_len += fw->size;
+#endif
+
+alloc_fail:
+ release_firmware(dev_entry->fw);
+fw_fail:
+ return fw_len;
+}
+
+static int get_firmware(struct xchange_data *xdata)
+{
+ struct dev_data *dev_entry;
+ struct patch_info *patch_entry;
+
+ dev_entry = xdata->dev_entry;
+ patch_entry = dev_entry->patch_entry;
+ if (patch_entry->fw_len > 0) {
+ xdata->fw_data = kzalloc(patch_entry->fw_len, GFP_KERNEL);
+ if (NULL == xdata->fw_data)
+ return -ENOMEM;
+ memcpy(xdata->fw_data, patch_entry->fw_cache,
+ patch_entry->fw_len);
+ xdata->fw_len = patch_entry->fw_len;
+ } else {
+ xdata->fw_len = load_firmware(dev_entry, &xdata->fw_data);
+ if (xdata->fw_len <= 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+static int download_patch(struct usb_interface *intf)
+{
+ struct dev_data *dev_entry;
+ uint8_t *fw_buf;
+ int ret_val;
+
+ BT_DBG("download_patch start");
+ dev_entry = dev_data_find(intf);
+ if (NULL == dev_entry) {
+ ret_val = -1;
+ BT_DBG("NULL == dev_entry");
+ goto patch_end;
+ }
+
+ init_xdata(&dev_entry->xdata, dev_entry);
+ ret_val = check_fw_version(&dev_entry->xdata);
+ if (ret_val != 0)
+ goto patch_end;
+
+ ret_val = get_firmware(&dev_entry->xdata);
+ if (ret_val < 0) {
+ BT_DBG("get_firmware failed!");
+ goto patch_end;
+ }
+ fw_buf = dev_entry->xdata.fw_data;
+
+ ret_val = download_data(&dev_entry->xdata);
+ if (ret_val < 0) {
+ BT_DBG("download_data failed!");
+ goto patch_fail;
+ }
+
+ ret_val = check_fw_version(&dev_entry->xdata);
+ if (ret_val <= 0) {
+ ret_val = -1;
+ goto patch_fail;
+ }
+
+ ret_val = 0;
+patch_fail:
+ kfree(fw_buf);
+patch_end:
+ BT_DBG("Rtk patch end %d", ret_val);
+ return ret_val;
+}
+
+static int btusb_open(struct hci_dev *hdev)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ int err;
+
+ BT_DBG("%s", hdev->name);
+
+ err = usb_autopm_get_interface(data->intf);
+ if (err < 0)
+ return err;
+
+ data->intf->needs_remote_wakeup = 1;
+ BT_DBG("%s start pm_usage_cnt(0x%x)", __func__,
+ atomic_read(&(data->intf->pm_usage_cnt)));
+
+ /*******************************/
+ if (0 == atomic_read(&hdev->promisc)) {
+ BT_DBG("btusb_open hdev->promisc == 0");
+ err = -1;
+ }
+ err = download_patch(data->intf);
+ if (err < 0)
+ goto failed;
+ /*******************************/
+
+ if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
+ goto done;
+
+ if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
+ goto done;
+
+ err = btusb_submit_intr_urb(hdev, GFP_KERNEL);
+ if (err < 0)
+ goto failed;
+
+ err = btusb_submit_bulk_urb(hdev, GFP_KERNEL);
+ if (err < 0) {
+ mdelay(URB_CANCELING_DELAY_MS); /* Added by Realtek */
+ usb_kill_anchored_urbs(&data->intr_anchor);
+ goto failed;
+ }
+
+ set_bit(BTUSB_BULK_RUNNING, &data->flags);
+ btusb_submit_bulk_urb(hdev, GFP_KERNEL);
+
+done:
+ usb_autopm_put_interface(data->intf);
+ BT_DBG("%s end pm_usage_cnt(0x%x)", __func__,
+ atomic_read(&(data->intf->pm_usage_cnt)));
+
+ return 0;
+
+failed:
+ clear_bit(BTUSB_INTR_RUNNING, &data->flags);
+ clear_bit(HCI_RUNNING, &hdev->flags);
+ usb_autopm_put_interface(data->intf);
+ BT_DBG("%s failed pm_usage_cnt(0x%x)", __func__,
+ atomic_read(&(data->intf->pm_usage_cnt)));
+ return err;
+}
+
+static int btusb_close(struct hci_dev *hdev)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ int i, err;
+
+ if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
+ return 0;
+
+ BT_DBG("btusb_close");
+ /*******************************/
+ for (i = 0; i < NUM_REASSEMBLY; i++) {
+ if (hdev->reassembly[i]) {
+ kfree_skb(hdev->reassembly[i]);
+ hdev->reassembly[i] = NULL;
+ BT_DBG("%s free ressembly i =%d", __func__, i);
+ }
+ }
+ /*******************************/
+ cancel_work_sync(&data->work);
+ cancel_work_sync(&data->waker);
+
+ clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+ clear_bit(BTUSB_BULK_RUNNING, &data->flags);
+ clear_bit(BTUSB_INTR_RUNNING, &data->flags);
+
+ btusb_stop_traffic(data);
+ err = usb_autopm_get_interface(data->intf);
+ if (err < 0)
+ goto failed;
+
+ data->intf->needs_remote_wakeup = 0;
+ usb_autopm_put_interface(data->intf);
+
+failed:
+ mdelay(URB_CANCELING_DELAY_MS); /* Added by Realtek */
+ usb_scuttle_anchored_urbs(&data->deferred);
+ return 0;
+}
+
+static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ struct usb_interface *intf = data->isoc;
+ struct usb_endpoint_descriptor *ep_desc;
+ int i, err;
+
+ if (!data->isoc)
+ return -ENODEV;
+
+ err = usb_set_interface(data->udev, 1, altsetting);
+ if (err < 0) {
+ BT_ERR("%s setting interface failed (%d)", hdev->name, -err);
+ return err;
+ }
+
+ data->isoc_altsetting = altsetting;
+
+ data->isoc_tx_ep = NULL;
+ data->isoc_rx_ep = NULL;
+
+ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
+ ep_desc = &intf->cur_altsetting->endpoint[i].desc;
+
+ if (!data->isoc_tx_ep && usb_endpoint_is_isoc_out(ep_desc)) {
+ data->isoc_tx_ep = ep_desc;
+ continue;
+ }
+
+ if (!data->isoc_rx_ep && usb_endpoint_is_isoc_in(ep_desc)) {
+ data->isoc_rx_ep = ep_desc;
+ continue;
+ }
+ }
+
+ if (!data->isoc_tx_ep || !data->isoc_rx_ep) {
+ BT_ERR("%s invalid SCO descriptors", hdev->name);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void btusb_work(struct work_struct *work)
+{
+ struct btusb_data *data = container_of(work, struct btusb_data, work);
+ struct hci_dev *hdev = data->hdev;
+ int err;
+
+ if (hdev->conn_hash.sco_num > 0) {
+ if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) {
+ err = usb_autopm_get_interface(data->isoc ? data->isoc :
+ data->intf);
+ if (err < 0) {
+ clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+ /* Delay added by Realtek */
+ mdelay(URB_CANCELING_DELAY_MS);
+ usb_kill_anchored_urbs(&data->isoc_anchor);
+ return;
+ }
+
+ set_bit(BTUSB_DID_ISO_RESUME, &data->flags);
+ }
+ if (data->isoc_altsetting != 2) {
+ clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+ mdelay(URB_CANCELING_DELAY_MS); /* Added by Realtek */
+ usb_kill_anchored_urbs(&data->isoc_anchor);
+
+ if (__set_isoc_interface(hdev, 2) < 0)
+ return;
+ }
+
+ if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
+ if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
+ clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+ else
+ btusb_submit_isoc_urb(hdev, GFP_KERNEL);
+ }
+ } else {
+ clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+ mdelay(URB_CANCELING_DELAY_MS); /* Added by Realtek */
+ usb_kill_anchored_urbs(&data->isoc_anchor);
+
+ __set_isoc_interface(hdev, 0);
+ if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags))
+ usb_autopm_put_interface(data->isoc ? data->isoc :
+ data->intf);
+ }
+}
+
+static struct patch_info *get_patch_entry(struct usb_device *udev)
+{
+ struct patch_info *patch_entry;
+ uint16_t pid;
+
+ patch_entry = patch_table;
+ pid = le16_to_cpu(udev->descriptor.idProduct);
+ while (pid != patch_entry->prod_id) {
+ if (0 == patch_entry->prod_id)
+ break;
+ patch_entry++;
+ }
+
+ return patch_entry;
+}
+
+static int rtkbt_pm_notify(struct notifier_block *notifier, ulong pm_event,
+ void *unused)
+{
+ struct dev_data *dev_entry;
+ struct patch_info *patch_entry;
+ struct usb_device *udev;
+
+ dev_entry = container_of(notifier, struct dev_data, pm_notifier);
+ patch_entry = dev_entry->patch_entry;
+ udev = dev_entry->udev;
+ BT_DBG("rtkbt_pm_notify pm_event =%ld", pm_event);
+ switch (pm_event) {
+ case PM_SUSPEND_PREPARE:
+ case PM_HIBERNATION_PREPARE:
+ patch_entry->fw_len = load_firmware(dev_entry,
+ &patch_entry->fw_cache);
+ if (patch_entry->fw_len <= 0) {
+ BT_DBG("rtkbt_pm_notify return NOTIFY_BAD");
+ return NOTIFY_BAD;
+ }
+
+ if (!device_may_wakeup(&udev->dev)) {
+ dev_entry->intf->needs_binding = 1;
+ BT_DBG("remote wakeup not support, set intf->needs_binding = 1");
+ }
+ break;
+ case PM_POST_SUSPEND:
+ case PM_POST_HIBERNATION:
+ case PM_POST_RESTORE:
+ if (patch_entry->fw_len > 0) {
+ kfree(patch_entry->fw_cache);
+ patch_entry->fw_cache = NULL;
+ patch_entry->fw_len = 0;
+ }
+#if BTUSB_RPM
+ usb_disable_autosuspend(udev);
+ usb_enable_autosuspend(udev);
+ pm_runtime_set_autosuspend_delay(&(udev->dev), 2000);
+#endif
+ break;
+
+ default:
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static int patch_add(struct usb_interface *intf)
+{
+ struct dev_data *dev_entry;
+ struct usb_device *udev;
+
+ BT_DBG("patch_add");
+ dev_entry = dev_data_find(intf);
+ if (NULL != dev_entry)
+ return -1;
+
+ udev = interface_to_usbdev(intf);
+#if BTUSB_RPM
+ BT_DBG("auto suspend is enabled");
+ usb_enable_autosuspend(udev);
+ pm_runtime_set_autosuspend_delay(&(udev->dev), 2000);
+#endif
+
+ dev_entry = kzalloc(sizeof(struct dev_data), GFP_KERNEL);
+ dev_entry->intf = intf;
+ dev_entry->udev = udev;
+ dev_entry->pm_notifier.notifier_call = rtkbt_pm_notify;
+ dev_entry->patch_entry = get_patch_entry(udev);
+ list_add(&dev_entry->list_node, &dev_data_list);
+ register_pm_notifier(&dev_entry->pm_notifier);
+
+ return 0;
+}
+
+static int btusb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_endpoint_descriptor *ep_desc;
+ struct btusb_data *data;
+ struct hci_dev *hdev;
+ int i, err, flag1, flag2;
+ struct usb_device *udev;
+ udev = interface_to_usbdev(intf);
+
+ BT_DBG("Realtek Bluetooth USB driver ver %s", VERSION);
+
+ /* interface numbers are hardcoded in the spec */
+ if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
+ return -ENODEV;
+
+ /*******************************/
+ flag1 = device_can_wakeup(&udev->dev);
+ flag2 = device_may_wakeup(&udev->dev);
+ BT_DBG("btusb_probe 1 ========== can_wakeup =%x flag2 =%x",
+ flag1, flag2);
+ device_wakeup_disable(&udev->dev);
+ flag1 = device_can_wakeup(&udev->dev);
+ flag2 = device_may_wakeup(&udev->dev);
+ BT_DBG("wakeup_disable ========== can_wakeup =%x flag2 =%x",
+ flag1, flag2);
+ err = patch_add(intf);
+ if (err < 0)
+ return -1;
+ /*******************************/
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+
+ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
+ ep_desc = &intf->cur_altsetting->endpoint[i].desc;
+
+ if (!data->intr_ep && usb_endpoint_is_int_in(ep_desc)) {
+ data->intr_ep = ep_desc;
+ continue;
+ }
+
+ if (!data->bulk_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) {
+ data->bulk_tx_ep = ep_desc;
+ continue;
+ }
+
+ if (!data->bulk_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) {
+ data->bulk_rx_ep = ep_desc;
+ continue;
+ }
+ }
+
+ if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) {
+ kfree(data);
+ return -ENODEV;
+ }
+
+ data->cmdreq_type = USB_TYPE_CLASS;
+
+ data->udev = interface_to_usbdev(intf);
+ data->intf = intf;
+
+ spin_lock_init(&data->lock);
+
+ INIT_WORK(&data->work, btusb_work);
+ INIT_WORK(&data->waker, btusb_waker);
+ spin_lock_init(&data->txlock);
+
+ init_usb_anchor(&data->tx_anchor);
+ init_usb_anchor(&data->intr_anchor);
+ init_usb_anchor(&data->bulk_anchor);
+ init_usb_anchor(&data->isoc_anchor);
+ init_usb_anchor(&data->deferred);
+
+ hdev = hci_alloc_dev();
+ if (!hdev) {
+ kfree(data);
+ return -ENOMEM;
+ }
+
+ HDEV_BUS = HCI_USB;
+
+ data->hdev = hdev;
+
+ SET_HCIDEV_DEV(hdev, &intf->dev);
+
+ hdev->open = btusb_open;
+ hdev->close = btusb_close;
+ hdev->flush = btusb_flush;
+ hdev->send = btusb_send_frame;
+ hdev->notify = btusb_notify;
+
+
+ hci_set_drvdata(hdev, data);
+
+ /* Interface numbers are hardcoded in the specification */
+ data->isoc = usb_ifnum_to_if(data->udev, 1);
+
+ if (data->isoc) {
+ err = usb_driver_claim_interface(&btusb_driver,
+ data->isoc, data);
+ if (err < 0) {
+ hci_free_dev(hdev);
+ kfree(data);
+ return err;
+ }
+ }
+
+ err = hci_register_dev(hdev);
+ if (err < 0) {
+ hci_free_dev(hdev);
+ kfree(data);
+ return err;
+ }
+
+ usb_set_intfdata(intf, data);
+
+ return 0;
+}
+
+static void patch_remove(struct usb_interface *intf)
+{
+ struct dev_data *dev_entry;
+ struct usb_device *udev;
+
+ udev = interface_to_usbdev(intf);
+#if BTUSB_RPM
+ usb_disable_autosuspend(udev);
+#endif
+
+ dev_entry = dev_data_find(intf);
+ if (NULL == dev_entry)
+ return;
+
+ BT_DBG("patch_remove");
+ list_del(&dev_entry->list_node);
+ unregister_pm_notifier(&dev_entry->pm_notifier);
+ kfree(dev_entry);
+}
+
+static void btusb_disconnect(struct usb_interface *intf)
+{
+ struct btusb_data *data = usb_get_intfdata(intf);
+ struct hci_dev *hdev;
+ struct usb_device *udev;
+ udev = interface_to_usbdev(intf);
+
+ if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
+ return;
+
+ if (!data)
+ return;
+
+ BT_DBG("btusb_disconnect");
+ /*******************************/
+ patch_remove(intf);
+ /*******************************/
+
+ hdev = data->hdev;
+
+ usb_set_intfdata(data->intf, NULL);
+
+ if (data->isoc)
+ usb_set_intfdata(data->isoc, NULL);
+
+ hci_unregister_dev(hdev);
+
+ if (intf == data->isoc)
+ usb_driver_release_interface(&btusb_driver, data->intf);
+ else if (data->isoc)
+ usb_driver_release_interface(&btusb_driver, data->isoc);
+
+ hci_free_dev(hdev);
+ kfree(data);
+}
+
+#ifdef CONFIG_PM
+static int set_btoff(struct usb_interface *intf)
+{
+ struct dev_data *dev_entry;
+ int ret_val;
+
+ BT_DBG("set_btoff");
+ dev_entry = dev_data_find(intf);
+ if (NULL == dev_entry)
+ return -1;
+
+ init_xdata(&dev_entry->xdata, dev_entry);
+ dev_entry->xdata.cmd_hdr->opcode = cpu_to_le16(BTOFF_OPCODE);
+ dev_entry->xdata.cmd_hdr->plen = 1;
+ dev_entry->xdata.pkt_len = CMD_HDR_LEN + 1;
+ dev_entry->xdata.send_pkt[CMD_HDR_LEN] = 1;
+
+ ret_val = send_hci_cmd(&dev_entry->xdata);
+ if (ret_val < 0)
+ return ret_val;
+
+ ret_val = rcv_hci_evt(&dev_entry->xdata);
+ if (ret_val < 0)
+ return ret_val;
+
+ BT_DBG("set_btoff done");
+ return 0;
+}
+
+static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct btusb_data *data = usb_get_intfdata(intf);
+
+ if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
+ return 0;
+
+ /*******************************/
+ BT_DBG("btusb_suspend message.event = 0x%x, data->suspend_count =%d",
+ message.event, data->suspend_count);
+ if (!test_bit(HCI_RUNNING, &data->hdev->flags)) {
+ BT_DBG("btusb_suspend-----bt is off");
+ set_btoff(data->intf);
+ }
+ /*******************************/
+
+ if (data->suspend_count++)
+ return 0;
+
+ spin_lock_irq(&data->txlock);
+ if (!((message.event & PM_EVENT_AUTO) && data->tx_in_flight)) {
+ set_bit(BTUSB_SUSPENDING, &data->flags);
+ spin_unlock_irq(&data->txlock);
+ } else {
+ spin_unlock_irq(&data->txlock);
+ data->suspend_count--;
+ return -EBUSY;
+ }
+
+ cancel_work_sync(&data->work);
+
+ btusb_stop_traffic(data);
+ mdelay(URB_CANCELING_DELAY_MS); /* Added by Realtek */
+ usb_kill_anchored_urbs(&data->tx_anchor);
+
+ return 0;
+}
+
+static void play_deferred(struct btusb_data *data)
+{
+ struct urb *urb;
+ int err;
+
+ while ((urb = usb_get_from_anchor(&data->deferred))) {
+
+ /************************************/
+ usb_anchor_urb(urb, &data->tx_anchor);
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0) {
+ BT_ERR("play_deferred urb %p submission failed", urb);
+ kfree(urb->setup_packet);
+ usb_unanchor_urb(urb);
+ } else {
+ usb_mark_last_busy(data->udev);
+ }
+ usb_free_urb(urb);
+ /************************************/
+ data->tx_in_flight++;
+ }
+ mdelay(URB_CANCELING_DELAY_MS); /* Added by Realtek */
+ usb_scuttle_anchored_urbs(&data->deferred);
+}
+
+static int btusb_resume(struct usb_interface *intf)
+{
+ struct btusb_data *data = usb_get_intfdata(intf);
+ struct hci_dev *hdev = data->hdev;
+ int err = 0;
+
+ if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
+ return 0;
+
+
+ /*******************************/
+ BT_DBG("btusb_resume data->suspend_count =%d", data->suspend_count);
+
+ if (!test_bit(HCI_RUNNING, &hdev->flags)) {
+ BT_DBG("btusb_resume-----bt is off, download patch");
+ download_patch(intf);
+ } else {
+ BT_DBG("btusb_resume,----bt is on");
+ }
+ /*******************************/
+ if (--data->suspend_count)
+ return 0;
+
+ if (test_bit(BTUSB_INTR_RUNNING, &data->flags)) {
+ err = btusb_submit_intr_urb(hdev, GFP_NOIO);
+ if (err < 0) {
+ clear_bit(BTUSB_INTR_RUNNING, &data->flags);
+ goto failed;
+ }
+ }
+
+ if (test_bit(BTUSB_BULK_RUNNING, &data->flags)) {
+ err = btusb_submit_bulk_urb(hdev, GFP_NOIO);
+ if (err < 0) {
+ clear_bit(BTUSB_BULK_RUNNING, &data->flags);
+ goto failed;
+ }
+
+ btusb_submit_bulk_urb(hdev, GFP_NOIO);
+ }
+
+ if (test_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
+ if (btusb_submit_isoc_urb(hdev, GFP_NOIO) < 0)
+ clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+ else
+ btusb_submit_isoc_urb(hdev, GFP_NOIO);
+ }
+
+ spin_lock_irq(&data->txlock);
+ play_deferred(data);
+ clear_bit(BTUSB_SUSPENDING, &data->flags);
+ spin_unlock_irq(&data->txlock);
+ schedule_work(&data->work);
+
+ return 0;
+
+failed:
+ mdelay(URB_CANCELING_DELAY_MS); /* Added by Realtek */
+ usb_scuttle_anchored_urbs(&data->deferred);
+/* done: */
+ spin_lock_irq(&data->txlock);
+ clear_bit(BTUSB_SUSPENDING, &data->flags);
+ spin_unlock_irq(&data->txlock);
+
+ return err;
+}
+#endif
+
+static struct usb_driver btusb_driver = {
+ .name = "rtk_btusb",
+ .probe = btusb_probe,
+ .disconnect = btusb_disconnect,
+#ifdef CONFIG_PM
+ .suspend = btusb_suspend,
+ .resume = btusb_resume,
+#endif
+ .id_table = btusb_table,
+ .supports_autosuspend = 1,
+};
+
+
+module_usb_driver(btusb_driver);
+
+MODULE_AUTHOR("Edward Bian <edward_bian-kXabqFNEczNtrwSWzY7KCg@public.gmane.org>");
+MODULE_DESCRIPTION("Realtek Bluetooth USB driver ver " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("rtl_bt/rtl8723a.bin");
diff --git a/drivers/bluetooth/rtk_btusb.h b/drivers/bluetooth/rtk_btusb.h
new file mode 100644
index 0000000..0c55dd6
--- /dev/null
+++ b/drivers/bluetooth/rtk_btusb.h
@@ -0,0 +1,102 @@
+/*
+ *
+ * Realtek Bluetooth USB driver
+ *
+ * Copyright (C) 2012-2013 Edward Bian <edward_bian-kXabqFNEczNtrwSWzY7KCg@public.gmane.org>
+ *
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef RTK_BTUSB_H
+#define RTK_BTUSB_H
+
+#define HDEV_BUS (hdev->bus)
+#define USB_RPM 1
+
+#define BTUSB_RPM 0 /*1 SS enable; 0 SS disable */
+#define LOAD_CONFIG 0
+#define URB_CANCELING_DELAY_MS 10 /* Added by Realtek */
+
+#define BTUSB_MAX_ISOC_FRAMES 10
+#define BTUSB_INTR_RUNNING 0
+#define BTUSB_BULK_RUNNING 1
+#define BTUSB_ISOC_RUNNING 2
+#define BTUSB_SUSPENDING 3
+#define BTUSB_DID_ISO_RESUME 4
+
+#define CMD_CMP_EVT 0x0e
+#define PKT_LEN 300
+#define MSG_TO 1000
+#define PATCH_SEG_MAX 252
+#define DATA_END 0x80
+#define DOWNLOAD_OPCODE 0xfc20
+#define BTOFF_OPCODE 0xfc28
+#define CMD_HDR_LEN sizeof(struct hci_command_hdr)
+#define EVT_HDR_LEN sizeof(struct hci_event_hdr)
+#define CMD_CMP_LEN sizeof(struct hci_ev_cmd_complete)
+
+enum rtk_endpoit {
+ CTRL_EP = 0,
+ INTR_EP = 1,
+ BULK_EP = 2,
+ ISOC_EP = 3
+};
+
+struct patch_info {
+ uint16_t prod_id;
+ uint16_t lmp_sub;
+ char *patch_name;
+ char *config_name;
+ uint8_t *fw_cache;
+ int fw_len;
+};
+
+struct xchange_data {
+ struct dev_data *dev_entry;
+ int pipe_in, pipe_out;
+ uint8_t send_pkt[PKT_LEN];
+ uint8_t rcv_pkt[PKT_LEN];
+ struct hci_command_hdr *cmd_hdr;
+ struct hci_event_hdr *evt_hdr;
+ struct hci_ev_cmd_complete *cmd_cmp;
+ uint8_t *req_para, *rsp_para;
+ uint8_t *fw_data;
+ int pkt_len, fw_len;
+};
+
+struct dev_data {
+ struct list_head list_node;
+ struct usb_interface *intf;
+ struct usb_device *udev;
+ struct notifier_block pm_notifier;
+ struct patch_info *patch_entry;
+ struct xchange_data xdata;
+ struct completion firmware_loading_complete;
+ const struct firmware *fw;
+};
+
+struct download_cp {
+ uint8_t index;
+ uint8_t data[PATCH_SEG_MAX];
+} __packed;
+
+struct download_rp {
+ uint8_t status;
+ uint8_t index;
+} __packed;
+
+#endif
--
1.8.1.4
^ permalink raw reply related
* [RFC/RFT PATCH 1/2 V2] btusb: Modify code for use with a similar driver
From: Larry Finger @ 2013-04-09 0:57 UTC (permalink / raw)
To: linville
Cc: linux-wireless, Larry Finger, netdev, marcel, gustavo,
johan.hedberg, linux-bluetooth, champion_chen
In-Reply-To: <1365469068-4548-1-git-send-email-Larry.Finger@lwfinger.net>
This patch exports some routines contained within this driver so that
they can be used by similar device that uses many of the same routines,
but which has a few special requirements that prevent using btusb in
its entirety.
To facilitate this usage, a new file btusb.h is created.
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
drivers/bluetooth/btusb.c | 79 ++++++++++--------------------------------
drivers/bluetooth/btusb.h | 88 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 107 insertions(+), 60 deletions(-)
create mode 100644 drivers/bluetooth/btusb.h
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 2cc5f77..5365cd1 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -27,6 +27,8 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
+#include "btusb.h"
+
#define VERSION "0.6"
static bool ignore_dga;
@@ -39,15 +41,6 @@ static bool reset = 1;
static struct usb_driver btusb_driver;
-#define BTUSB_IGNORE 0x01
-#define BTUSB_DIGIANSWER 0x02
-#define BTUSB_CSR 0x04
-#define BTUSB_SNIFFER 0x08
-#define BTUSB_BCM92035 0x10
-#define BTUSB_BROKEN_ISOC 0x20
-#define BTUSB_WRONG_SCO_MTU 0x40
-#define BTUSB_ATH3012 0x80
-
static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
@@ -209,48 +202,6 @@ static struct usb_device_id blacklist_table[] = {
{ } /* Terminating entry */
};
-#define BTUSB_MAX_ISOC_FRAMES 10
-
-#define BTUSB_INTR_RUNNING 0
-#define BTUSB_BULK_RUNNING 1
-#define BTUSB_ISOC_RUNNING 2
-#define BTUSB_SUSPENDING 3
-#define BTUSB_DID_ISO_RESUME 4
-
-struct btusb_data {
- struct hci_dev *hdev;
- struct usb_device *udev;
- struct usb_interface *intf;
- struct usb_interface *isoc;
-
- spinlock_t lock;
-
- unsigned long flags;
-
- struct work_struct work;
- struct work_struct waker;
-
- struct usb_anchor tx_anchor;
- struct usb_anchor intr_anchor;
- struct usb_anchor bulk_anchor;
- struct usb_anchor isoc_anchor;
- struct usb_anchor deferred;
- int tx_in_flight;
- spinlock_t txlock;
-
- struct usb_endpoint_descriptor *intr_ep;
- struct usb_endpoint_descriptor *bulk_tx_ep;
- struct usb_endpoint_descriptor *bulk_rx_ep;
- struct usb_endpoint_descriptor *isoc_tx_ep;
- struct usb_endpoint_descriptor *isoc_rx_ep;
-
- __u8 cmdreq_type;
-
- unsigned int sco_num;
- int isoc_altsetting;
- int suspend_count;
-};
-
static int inc_tx(struct btusb_data *data)
{
unsigned long flags;
@@ -305,7 +256,7 @@ static void btusb_intr_complete(struct urb *urb)
}
}
-static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
+int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
{
struct btusb_data *data = hci_get_drvdata(hdev);
struct urb *urb;
@@ -352,6 +303,7 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
return err;
}
+EXPORT_SYMBOL_GPL(btusb_submit_intr_urb);
static void btusb_bulk_complete(struct urb *urb)
{
@@ -393,7 +345,7 @@ static void btusb_bulk_complete(struct urb *urb)
}
}
-static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
+int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
{
struct btusb_data *data = hci_get_drvdata(hdev);
struct urb *urb;
@@ -438,8 +390,9 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
return err;
}
+EXPORT_SYMBOL_GPL(btusb_submit_bulk_urb);
-static void btusb_isoc_complete(struct urb *urb)
+void btusb_isoc_complete(struct urb *urb)
{
struct hci_dev *hdev = urb->context;
struct btusb_data *data = hci_get_drvdata(hdev);
@@ -507,7 +460,7 @@ static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
urb->number_of_packets = i;
}
-static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
+int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
{
struct btusb_data *data = hci_get_drvdata(hdev);
struct urb *urb;
@@ -557,6 +510,7 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
return err;
}
+EXPORT_SYMBOL_GPL(btusb_submit_isoc_urb);
static void btusb_tx_complete(struct urb *urb)
{
@@ -650,12 +604,13 @@ failed:
return err;
}
-static void btusb_stop_traffic(struct btusb_data *data)
+void btusb_stop_traffic(struct btusb_data *data)
{
usb_kill_anchored_urbs(&data->intr_anchor);
usb_kill_anchored_urbs(&data->bulk_anchor);
usb_kill_anchored_urbs(&data->isoc_anchor);
}
+EXPORT_SYMBOL(btusb_stop_traffic);
static int btusb_close(struct hci_dev *hdev)
{
@@ -687,7 +642,7 @@ failed:
return 0;
}
-static int btusb_flush(struct hci_dev *hdev)
+int btusb_flush(struct hci_dev *hdev)
{
struct btusb_data *data = hci_get_drvdata(hdev);
@@ -697,8 +652,9 @@ static int btusb_flush(struct hci_dev *hdev)
return 0;
}
+EXPORT_SYMBOL_GPL(btusb_flush);
-static int btusb_send_frame(struct sk_buff *skb)
+int btusb_send_frame(struct sk_buff *skb)
{
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
struct btusb_data *data = hci_get_drvdata(hdev);
@@ -808,8 +764,9 @@ done:
usb_free_urb(urb);
return err;
}
+EXPORT_SYMBOL_GPL(btusb_send_frame);
-static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
+void btusb_notify(struct hci_dev *hdev, unsigned int evt)
{
struct btusb_data *data = hci_get_drvdata(hdev);
@@ -820,6 +777,7 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
schedule_work(&data->work);
}
}
+EXPORT_SYMBOL_GPL(btusb_notify);
static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
{
@@ -914,7 +872,7 @@ static void btusb_work(struct work_struct *work)
}
}
-static void btusb_waker(struct work_struct *work)
+void btusb_waker(struct work_struct *work)
{
struct btusb_data *data = container_of(work, struct btusb_data, waker);
int err;
@@ -925,6 +883,7 @@ static void btusb_waker(struct work_struct *work)
usb_autopm_put_interface(data->intf);
}
+EXPORT_SYMBOL_GPL(btusb_waker);
static int btusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
diff --git a/drivers/bluetooth/btusb.h b/drivers/bluetooth/btusb.h
new file mode 100644
index 0000000..d9d7181
--- /dev/null
+++ b/drivers/bluetooth/btusb.h
@@ -0,0 +1,88 @@
+/*
+ *
+ * Generic Bluetooth USB driver
+ *
+ * Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef BTUSB_H
+#define BTUSB_H
+
+#define BTUSB_IGNORE 0x01
+#define BTUSB_DIGIANSWER 0x02
+#define BTUSB_CSR 0x04
+#define BTUSB_SNIFFER 0x08
+#define BTUSB_BCM92035 0x10
+#define BTUSB_BROKEN_ISOC 0x20
+#define BTUSB_WRONG_SCO_MTU 0x40
+#define BTUSB_ATH3012 0x80
+
+#define BTUSB_MAX_ISOC_FRAMES 10
+
+#define BTUSB_INTR_RUNNING 0
+#define BTUSB_BULK_RUNNING 1
+#define BTUSB_ISOC_RUNNING 2
+#define BTUSB_SUSPENDING 3
+#define BTUSB_DID_ISO_RESUME 4
+
+struct btusb_data {
+ struct hci_dev *hdev;
+ struct usb_device *udev;
+ struct usb_interface *intf;
+ struct usb_interface *isoc;
+
+ spinlock_t lock;
+
+ unsigned long flags;
+
+ struct work_struct work;
+ struct work_struct waker;
+
+ struct usb_anchor tx_anchor;
+ struct usb_anchor intr_anchor;
+ struct usb_anchor bulk_anchor;
+ struct usb_anchor isoc_anchor;
+ struct usb_anchor deferred;
+ int tx_in_flight;
+ spinlock_t txlock;
+
+ struct usb_endpoint_descriptor *intr_ep;
+ struct usb_endpoint_descriptor *bulk_tx_ep;
+ struct usb_endpoint_descriptor *bulk_rx_ep;
+ struct usb_endpoint_descriptor *isoc_tx_ep;
+ struct usb_endpoint_descriptor *isoc_rx_ep;
+
+ __u8 cmdreq_type;
+
+ unsigned int sco_num;
+ int isoc_altsetting;
+ int suspend_count;
+};
+
+int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags);
+int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags);
+void btusb_isoc_complete(struct urb *urb);
+int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags);
+void btusb_stop_traffic(struct btusb_data *data);
+int btusb_flush(struct hci_dev *hdev);
+int btusb_send_frame(struct sk_buff *skb);
+void btusb_notify(struct hci_dev *hdev, unsigned int evt);
+void btusb_waker(struct work_struct *work);
+
+#endif
--
1.8.1.4
^ permalink raw reply related
* Re: [PATCH] tcp: assign the sock correctly to an outgoing SYNACK packet
From: Casey Schaufler @ 2013-04-09 0:59 UTC (permalink / raw)
To: Eric Dumazet
Cc: David Miller, pmoore, netdev, mvadkert, selinux,
linux-security-module, Casey Schaufler
In-Reply-To: <1365467636.3887.67.camel@edumazet-glaptop>
On 4/8/2013 5:33 PM, Eric Dumazet wrote:
> On Mon, 2013-04-08 at 16:40 -0700, Casey Schaufler wrote:
>
>> OK, let's do the math.
>>
>> First off, it's 4 bytes, not 8. It replaces the secmark.
>> Your increased memory usage is going to be
>>
>> 4 bytes/packet * M packets/second * N seconds
>>
>> Where M is the rate at which you're processing packets and
>> N is the length of time it takes to process a packet.
>>
>> Let's pretend we have an embedded system that does nothing but send
>> 128 byte packets on a 10Gb port. That's 10M packets/second. If it
>> takes a full second to process a packet the overhead is 40MB for that
>> second. I have it on good authority that packets can be processed
>> in considerably less time than that. The real number is more like
>> 0.05 seconds. That means your actual overhead is more like 1MB.
>>
>> These are dumbed down calculations. I am not a memory usage expert.
>> I am convinced that "real" calculations are going to get similar
>> numbers. I am, of course, willing to be swayed by evidence that I
>> am wrong.
>>
>> Compare that to the overhead associated with using CIPSO on packets
>> that never leave the box.
> Maths are not that simple,
I am willing to accept that. I am willing to be
educated. I would be interested to see what the
"real" maths are, and how far off my dumb version
might actually be.
> and its not about size of sk_buff, since the
> number of in-flight skb should be quite small.
The reason we're told that there can't be a blob
pointer in the sk_buff is that it increases the size
of the sk_buff. Yes, it *is* about the size.
> Its the time to init this memory for _every_ packet.
Which is a function of the size, no?
> sizeof(sk_buff) is 0xf8, very close to cross the 256 bytes limit.
0xf8 + 0x4 = 0xfc
248 + 4 = 252
> Add a single _byte_ and it becomes a matter of adding a _cache_ line,
> and thats 25 % cost, assuming 64bytes cache lines.
I don't see that with adding 4 bytes. Again, I'm willing to be
educated if I'm wrong.
> So instead of processing 10M packets per second, we would process 9M
> packets per second, or maybe less.
>
> Yes, 256 bytes per sk_buff, this is the current insane situation.
> (Not counting the struct skb_shared_info, adding at least one additional
> cache line)
Sorry, but I don't see what's insane with either the
current 248 byte sk_buff or a 252 byte sk_buff.
As always, I am willing to be educated.
Thank you.
^ permalink raw reply
* Re: [PATCH] tcp: assign the sock correctly to an outgoing SYNACK packet
From: Eric Dumazet @ 2013-04-09 1:09 UTC (permalink / raw)
To: Casey Schaufler
Cc: David Miller, pmoore, netdev, mvadkert, selinux,
linux-security-module
In-Reply-To: <5163680F.4030200@schaufler-ca.com>
On Mon, 2013-04-08 at 17:59 -0700, Casey Schaufler wrote:
> I don't see that with adding 4 bytes. Again, I'm willing to be
> educated if I'm wrong.
Feel free to add 4 bytes without having the 'align to 8 bytes' problem
on 64 bit arches. Show us your patch.
^ permalink raw reply
* Re: [PATCH] tcp: assign the sock correctly to an outgoing SYNACK packet
From: Casey Schaufler @ 2013-04-09 1:24 UTC (permalink / raw)
To: Eric Dumazet
Cc: David Miller, pmoore, netdev, mvadkert, selinux,
linux-security-module, Casey Schaufler
In-Reply-To: <1365469759.3887.69.camel@edumazet-glaptop>
On 4/8/2013 6:09 PM, Eric Dumazet wrote:
> On Mon, 2013-04-08 at 17:59 -0700, Casey Schaufler wrote:
>
>> I don't see that with adding 4 bytes. Again, I'm willing to be
>> educated if I'm wrong.
> Feel free to add 4 bytes without having the 'align to 8 bytes' problem
> on 64 bit arches. Show us your patch.
Recall that it's replacing an existing 4 byte value with an 8 byte value.
My compiler days were quite short and long ago, but it would seem that
an 8 byte value ought not have an 'align to 8 bytes' problem.
Again, I'm willing to be educated.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" 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 1/4] Add packet recirculation
From: Jesse Gross @ 2013-04-09 1:46 UTC (permalink / raw)
To: Simon Horman
Cc: dev@openvswitch.org, netdev, Ravi K, Isaku Yamahata, Ben Pfaff
In-Reply-To: <1365403431-18102-2-git-send-email-horms@verge.net.au>
On Sun, Apr 7, 2013 at 11:43 PM, Simon Horman <horms@verge.net.au> wrote:
> diff --git a/datapath/actions.c b/datapath/actions.c
> index e9634fe..7b0f022 100644
> --- a/datapath/actions.c
> +++ b/datapath/actions.c
> @@ -617,6 +617,9 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
> case OVS_ACTION_ATTR_SAMPLE:
> err = sample(dp, skb, a);
> break;
> +
> + case OVS_ACTION_ATTR_RECIRCULATE:
> + return 1;
I think that if we've had a previous output action with the port
stored in prev_port then this will cause the packet to not actually be
output.
> diff --git a/datapath/datapath.c b/datapath/datapath.c
> index e8be795..ab39dd7 100644
> --- a/datapath/datapath.c
> +++ b/datapath/datapath.c
> void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
[...]
> + if (IS_ERR_OR_NULL(skb)) {
> + break;
> + } else if (unlikely(!limit--)) {
Should this be a predecrement?
> + kfree_skb(skb);
Should we log some kind of rate limited warning here?
> + return;
In the first case we use break to exit the loop and here we use
return. Both should have the same effect so it might be nice to make
them the same.
> @@ -901,6 +913,9 @@ static int validate_and_copy_actions__(const struct nlattr *attr,
> skip_copy = true;
> break;
>
> + case OVS_ACTION_ATTR_RECIRCULATE:
> + break;
I think we might want to jump out the loop here to better model how
the actions are actually executed.
> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
> index e4a2f75..31255f6 100644
> --- a/lib/dpif-netdev.c
> +++ b/lib/dpif-netdev.c
> dp_netdev_port_input(struct dp_netdev *dp, struct dp_netdev_port *port,
> struct ofpbuf *packet)
[...]
> + } else {
> + dp->n_missed++;
> + dp_netdev_output_userspace(dp, packet, DPIF_UC_MISS, &key, NULL);
> + recirculate = false;
> + }
> + } while (recirculate && limit--);
I have the same question about predecrement here.
> @@ -1163,6 +1190,7 @@ dp_netdev_sample(struct dp_netdev *dp,
> const struct nlattr *subactions = NULL;
> const struct nlattr *a;
> size_t left;
> + uint32_t skb_mark;
I don't think it's right to have a new (and uninitialized) copy of
skb_mark here. We should have the same one all the way through, like
we do in the kernel.
> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> index 47830c1..5129da1 100644
> --- a/ofproto/ofproto-dpif.c
> +++ b/ofproto/ofproto-dpif.c
I'm still working on more detailed comments for this. However, I'm
concerned about whether the behavior for revalidation and stats is
correct.
^ permalink raw reply
* [PATCH -next] netrom: fix invalid use of sizeof in nr_recvmsg()
From: Wei Yongjun @ 2013-04-09 2:07 UTC (permalink / raw)
To: ralf, minipli, davem; +Cc: yongjun_wei, linux-hams, netdev
From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
sizeof() when applied to a pointer typed expression gives the size of the
pointer, not that of the pointed data.
Introduced by commit 3ce5ef(netrom: fix info leak via msg_name in nr_recvmsg)
Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
---
net/netrom/af_netrom.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 7fcb307..103bd70 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -1173,7 +1173,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock,
}
if (sax != NULL) {
- memset(sax, 0, sizeof(sax));
+ memset(sax, 0, sizeof(*sax));
sax->sax25_family = AF_NETROM;
skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call,
AX25_ADDR_LEN);
^ permalink raw reply related
* Re: [PATCH -next] netrom: fix invalid use of sizeof in nr_recvmsg()
From: David Miller @ 2013-04-09 2:49 UTC (permalink / raw)
To: weiyj.lk; +Cc: ralf, minipli, yongjun_wei, linux-hams, netdev, minipli
In-Reply-To: <CAPgLHd-yEmt_BJ52uZNsCA_-w85VhnN_HbfjG1QLVvR5kp7Xvw@mail.gmail.com>
From: Wei Yongjun <weiyj.lk@gmail.com>
Date: Tue, 9 Apr 2013 10:07:19 +0800
> From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
>
> sizeof() when applied to a pointer typed expression gives the size of the
> pointer, not that of the pointed data.
> Introduced by commit 3ce5ef(netrom: fix info leak via msg_name in nr_recvmsg)
>
> Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
Any particular reason you're:
1) Targetting the wrong tree. This was a bug fix that went into
'net', therefore targetting -next is not correct. This fix
need to go into 'net'.
2) Not even bothering to CC: the person whose change you are
correcting?
Anyways, applied to 'net', thanks.
^ 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