* Re: [patch net-next 0/2] team: introduce random mode
From: David Miller @ 2013-03-01 21:26 UTC (permalink / raw)
To: jiri; +Cc: netdev, edumazet, fbl
In-Reply-To: <1362133566-1382-1-git-send-email-jiri@resnulli.us>
From: Jiri Pirko <jiri@resnulli.us>
Date: Fri, 1 Mar 2013 11:26:04 +0100
> Jiri Pirko (2):
> team: introduce two default team_modeop functions and use them in
> modes
> team: introduce random mode
Looks fine, please resubmit when net-next opens back up.
^ permalink raw reply
* Re: [PATCH v2 net-next 0/4] Provide default fdb operation to allow mac filter setting
From: David Miller @ 2013-03-01 21:26 UTC (permalink / raw)
To: vyasevic; +Cc: netdev, john.r.fastabend
In-Reply-To: <1362151906-20993-1-git-send-email-vyasevic@redhat.com>
From: Vlad Yasevich <vyasevic@redhat.com>
Date: Fri, 1 Mar 2013 10:31:42 -0500
> This is a short series that now allows mac filter programming on any
> card that support IFF_UNICAST_FLT by using the existing FDB interface.
>
> Some existing drivers that had FDB functionality usually supported
> it only in SR-IOV mode. Since that's not always enabled, and
> we want to take advantage of IFF_UNICAST_FLT support, these drivers
> have been converted to call the default handler when not in SRIOV mode.
These changes look great, please resubmit them once I open net-next
back up.
Thanks.
^ permalink raw reply
* Re: [RFC PATCH 0/5] net: low latency Ethernet device polling
From: David Miller @ 2013-03-01 21:24 UTC (permalink / raw)
To: eliezer.tamir
Cc: linux-kernel, netdev, jesse.brandeburg, e1000-devel, willemb,
andi, hpa, eliezer
In-Reply-To: <20130227175549.10611.82188.stgit@gitlad.jf.intel.com>
From: Eliezer Tamir <eliezer.tamir@linux.jf.intel.com>
Date: Wed, 27 Feb 2013 09:55:49 -0800
> This patchset adds the ability for the socket layer code to poll directly
> on an Ethernet device's RX queue. This eliminates the cost of the interrupt
> and context switch and with proper tuning allows us to get very close
> to the HW latency.
>
> This is a follow up to Jesse Brandeburg's Kernel Plumbers talk from last year
> http://www.linuxplumbersconf.org/2012/wp-content/uploads/2012/09/2012-lpc-Low-Latency-Sockets-slides-brandeburg.pdf
I just wanted to say that I like this work a lot.
It proves a lot of things I try to impress upon people who talk about
how RDMA is such a "must have" because the software stack can't
possibly give anything near HW latency.
Obviously such arguments are complete bullshit as is shown by these
changes.
This is exactly the kind of approach that makes sense rather than
trying to put entire TCP stacks in the network card firmware.
Thanks again for doing this work and I look forward to applying
this stuff once all the kinks are worked out. The folks in the
Intel NIC group continue to impress me.
^ permalink raw reply
* Re: [PATCH resubmit] ax88179_178a: ASIX AX88179_178A USB 3.0/2.0 to gigabit ethernet adapter driver
From: David Miller @ 2013-03-01 21:15 UTC (permalink / raw)
To: freddy; +Cc: netdev, linux-usb, linux-kernel, louis
In-Reply-To: <1361966518-3755-1-git-send-email-freddy@asix.com.tw>
From: Freddy Xin <freddy@asix.com.tw>
Date: Wed, 27 Feb 2013 20:01:58 +0800
> + eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1),
> + GFP_KERNEL);
> + if (!eeprom_buff)
> + return -ENOMEM;
> +
> + /* ax88179/178A returns 2 bytes from eeprom on read */
> + for (i = first_word; i <= last_word; i++) {
> + ret = __ax88179_read_cmd(dev, AX_ACCESS_EEPROM, i, 1, 2,
> + &eeprom_buff[i - first_word],
> + 0);
> + if (ret < 0)
> + return -EIO;
In this -EIO error path we will leak eeprom_buff, you must free it in
all possible exit cases of this function after the allocation succeeds.
> + data->rxctl = (__force __le16)(AX_RX_CTL_START | AX_RX_CTL_AB |
> + AX_RX_CTL_IPE);
You're not storying a __le16 in data->rxctl, you're storing the bits
in cpu endianness. So make it a plain u16 instead and get rid of
these pointless casts.
> +static int __init asix_init(void)
> +{
> + return usb_register(&asix_driver);
> +}
> +module_init(asix_init);
> +
> +static void __exit asix_exit(void)
> +{
> + usb_deregister(&asix_driver);
> +}
> +module_exit(asix_exit);
You can replace all of this with a simple:
module_usb_driver(asix_driver);
^ permalink raw reply
* Re: [PATCH v2 net-next] ipv[4|6]: correct dropwatch false positive in local_deliver_finish
From: Neil Horman @ 2013-03-01 21:05 UTC (permalink / raw)
To: David Miller; +Cc: eric.dumazet, netdev, reich
In-Reply-To: <20130301.155709.1482599990846126981.davem@davemloft.net>
On Fri, Mar 01, 2013 at 03:57:09PM -0500, David Miller wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Fri, 01 Mar 2013 09:56:44 -0800
>
> > On Fri, 2013-03-01 at 12:44 -0500, Neil Horman wrote:
> >> I had a report recently of a user trying to use dropwatch to localise some frame
> >> loss, and they were getting false positives. Turned out they were using a user
> >> space SCTP stack that used raw sockets to grab frames. When we don't have a
> >> registered protocol for a given packet, we record it as a drop, even if a raw
> >> socket receieves the frame. We should only record the drop in the event a raw
> >> socket doesnt exist to receive the frames
> >>
> >> Tested by the reported successfully
> >>
> >> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> >> Reported-by: William Reich <reich@ulticom.com>
> >> Tested-by: William Reich <reich@ulticom.com>
> >> CC: "David S. Miller" <davem@davemloft.net>
> >> CC: William Reich <reich@ulticom.com>
> >> CC: eric.dumazet@gmail.com
> >> ---
> >> net/ipv4/ip_input.c | 6 ++++--
> >> net/ipv6/ip6_input.c | 6 ++++--
> >> 2 files changed, 8 insertions(+), 4 deletions(-)
> >
> > Thanks !
> >
> > Acked-by: Eric Dumazet <edumazet@google.com>
>
> This seems like a reasonable bug fix so I'm going to apply this to
> 'net', thanks everyone.
>
Copy that, thanks Dave!
Neil
^ permalink raw reply
* Re: [patch] sctp: use the passed in gfp flags instead GFP_KERNEL
From: David Miller @ 2013-03-01 21:00 UTC (permalink / raw)
To: dan.carpenter
Cc: vyasevich, sri, nhorman, linux-sctp, netdev, kernel-janitors
In-Reply-To: <20130301052743.GD2669@longonot.mountain>
From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Fri, 1 Mar 2013 08:27:43 +0300
> This patch doesn't change how the code works because in the current
> kernel gfp is always GFP_KERNEL. But gfp was obviously intended
> instead of GFP_KERNEL.
>
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH v2 1/1 net-next] fec: net: put tx to napi poll function to fix dead lock
From: David Miller @ 2013-03-01 20:58 UTC (permalink / raw)
To: Frank.Li; +Cc: lznuaa, shawn.guo, B38611, linux-arm-kernel, netdev, s.hauer
In-Reply-To: <1362109034-25805-1-git-send-email-Frank.Li@freescale.com>
From: Frank Li <Frank.Li@freescale.com>
Date: Fri, 1 Mar 2013 11:37:14 +0800
> @@ -566,27 +554,47 @@ fec_timeout(struct net_device *ndev)
> netif_wake_queue(ndev);
> }
>
> -static void
> +static int
> fec_enet_tx(struct net_device *ndev)
The return value of this function is never tested, get rid of it.
^ permalink raw reply
* Re: pull request: wireless 2013-03-01
From: David Miller @ 2013-03-01 20:57 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20130301192332.GE27114@tuxdriver.com>
From: "John W. Linville" <linville@tuxdriver.com>
Date: Fri, 1 Mar 2013 14:23:33 -0500
> This is another flurry of fixes intended for the 3.9 stream...
>
> A mac80211 pull from Johannes:
>
> "Seth fixes a stupid bug I introduced into one of his earlier patches,
> Chun-Yeow fixes mesh forwarding and Felix fixes monitor mode. I myself
> fixed a small locking issue and, the biggest change here, removed some
> nl80211 information with which sometimes the per wiphy information was
> getting too large for the typical 4k-minus-overhead. In my -next tree I
> have a patch to allow splitting that and add back the information
> removed now."
>
> An iwlwifi pull from Johannes:
>
> "I have a fix for a pretty important bug regarding DMA mapping, that
> could cause the DMA engine to overwrite data we wanted to send to it, so
> that the next time we send it it would be bad. This particularly affects
> calibration results. Other than that, three little fixes for the MVM
> driver."
>
> But wait, there's more!
>
> Avinash Patil fixes an incorrectly timed delay in mwifiex.
>
> Bing Zhao prevents a crash in SD8688 caused by failing to properly
> set a flag before issuing a command.
>
> Felix Fietkau is the big here this time, providing a trio of minor
> ath9k fixes and correcting the advertised interface combinations for
> rt2x00 when mesh support is disabled.
>
> Finally, Hauke Mehrtens gives us a patch that correctlin initializes
> a spin lock in the bcma code.
>
> Please let me know if there are problems!
Pulled, thanks John.
^ permalink raw reply
* Re: [PATCH v2 net-next] ipv[4|6]: correct dropwatch false positive in local_deliver_finish
From: David Miller @ 2013-03-01 20:57 UTC (permalink / raw)
To: eric.dumazet; +Cc: nhorman, netdev, reich
In-Reply-To: <1362160604.15793.57.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 01 Mar 2013 09:56:44 -0800
> On Fri, 2013-03-01 at 12:44 -0500, Neil Horman wrote:
>> I had a report recently of a user trying to use dropwatch to localise some frame
>> loss, and they were getting false positives. Turned out they were using a user
>> space SCTP stack that used raw sockets to grab frames. When we don't have a
>> registered protocol for a given packet, we record it as a drop, even if a raw
>> socket receieves the frame. We should only record the drop in the event a raw
>> socket doesnt exist to receive the frames
>>
>> Tested by the reported successfully
>>
>> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
>> Reported-by: William Reich <reich@ulticom.com>
>> Tested-by: William Reich <reich@ulticom.com>
>> CC: "David S. Miller" <davem@davemloft.net>
>> CC: William Reich <reich@ulticom.com>
>> CC: eric.dumazet@gmail.com
>> ---
>> net/ipv4/ip_input.c | 6 ++++--
>> net/ipv6/ip6_input.c | 6 ++++--
>> 2 files changed, 8 insertions(+), 4 deletions(-)
>
> Thanks !
>
> Acked-by: Eric Dumazet <edumazet@google.com>
This seems like a reasonable bug fix so I'm going to apply this to
'net', thanks everyone.
^ permalink raw reply
* Re: [PATCH] lglock: add read-preference local-global rwlock
From: Srivatsa S. Bhat @ 2013-03-01 20:06 UTC (permalink / raw)
To: Tejun Heo
Cc: Lai Jiangshan, Lai Jiangshan, Michel Lespinasse, linux-doc,
peterz, fweisbec, linux-kernel, namhyung, mingo, linux-arch,
linux, xiaoguangrong, wangyun, paulmck, nikunj, linux-pm, rusty,
rostedt, rjw, vincent.guittot, tglx, linux-arm-kernel, netdev,
oleg, sbw, akpm, linuxppc-dev
In-Reply-To: <20130301175349.GC2481@mtj.dyndns.org>
On 03/01/2013 11:23 PM, Tejun Heo wrote:
> Hey, guys and Oleg (yes, I'm singling you out ;p because you're that
> awesome.)
>
> On Sat, Mar 02, 2013 at 01:44:02AM +0800, Lai Jiangshan wrote:
>> Performance:
>> We only focus on the performance of the read site. this read site's fast path
>> is just preempt_disable() + __this_cpu_read/inc() + arch_spin_trylock(),
>> It has only one heavy memory operation. it will be expected fast.
>>
>> We test three locks.
>> 1) traditional rwlock WITHOUT remote competition nor cache-bouncing.(opt-rwlock)
>> 2) this lock(lgrwlock)
>> 3) V6 percpu-rwlock by "Srivatsa S. Bhat". (percpu-rwlock)
>> (https://lkml.org/lkml/2013/2/18/186)
>>
>> nested=1(no nested) nested=2 nested=4
>> opt-rwlock 517181 1009200 2010027
>> lgrwlock 452897 700026 1201415
>> percpu-rwlock 1192955 1451343 1951757
>
> On the first glance, the numbers look pretty good and I kinda really
> like the fact that if this works out we don't have to introduce yet
> another percpu synchronization construct and get to reuse lglock.
>
> So, Oleg, can you please see whether you can find holes in this one?
>
> Srivatsa, I know you spent a lot of time on percpu_rwlock but as you
> wrote before Lai's work can be seen as continuation of yours, and if
> we get to extend what's already there instead of introducing something
> completely new, there's no reason not to
Yep, I agree!
> (and my apologies for not
> noticing the possibility of extending lglock before).
No problem at all! You gave so many invaluable suggestions to make this
whole thing work in the first place! Now, if we can reuse the existing
stuff and extend it to what we want, then its just even better! :-)
> So, if this can
> work, it would be awesome if you guys can work together.
Absolutely!
> Lai might
> not be very good at communicating in english yet but he's really good
> at spotting patterns in complex code and playing with them.
>
That sounds great! :-)
I'll soon take a closer look at his code and the comparisons he posted,
and work towards taking this effort forward.
Thank you very much!
Regards,
Srivatsa S. Bhat
^ permalink raw reply
* Re: [PATCH v6 04/46] percpu_rwlock: Implement the core design of Per-CPU Reader-Writer Locks
From: Srivatsa S. Bhat @ 2013-03-01 19:59 UTC (permalink / raw)
To: Tejun Heo
Cc: Lai Jiangshan, Michel Lespinasse, linux-doc, peterz, fweisbec,
linux-kernel, namhyung, mingo, linux-arch, linux, xiaoguangrong,
wangyun, paulmck, nikunj, linux-pm, rusty, rostedt, rjw,
vincent.guittot, tglx, linux-arm-kernel, netdev, oleg, sbw, akpm,
linuxppc-dev
In-Reply-To: <20130301181054.GD2481@mtj.dyndns.org>
Hi Tejun,
On 03/01/2013 11:40 PM, Tejun Heo wrote:
> Hello, Srivatsa.
>
> On Thu, Feb 28, 2013 at 02:49:53AM +0530, Srivatsa S. Bhat wrote:
>> Don't get me wrong - I'll whole-heartedly acknowledge and appreciate if
>> _your_ code is better than mine. I just don't like the idea of somebody
>> plagiarizing my ideas/code (or even others' ideas for that matter).
>> However, I sincerely apologize in advance if I misunderstood/misjudged your
>> intentions; I just wanted to voice my concerns out loud at this point,
>> considering the bad feeling I got by looking at your responses collectively.
>
> Although I don't know Lai personally, from my experience working with
> him past several months on workqueue, I strongly doubt he has dark
> urterior intenions. The biggest problem probably is that his
> communication in English isn't very fluent yet and thus doesn't carry
> the underlying intentions or tones very well and he tends to bombard
> patches in quick succession without much explanation inbetween (during
> 3.8 cycle, I was receiving several workqueue patchsets days apart
> trying to solve the same problem with completely different approaches
> way before the discussion on the previous postings reach any kind of
> consensus). A lot of that also probably comes from communication
> problems.
>
> Anyways, I really don't think he's trying to take claim of your work.
> At least for now, you kinda need to speculate what he's trying to do
> and then confirm that back to him, but once you get used to that part,
> he's pretty nice to work with and I'm sure his communication will
> improve in time (I think it has gotten a lot better than only some
> months ago).
>
Thank you so much for helping clear the air, Tejun! I'm truly sorry again
for having drawn the wrong conclusions based on gaps in our communication.
It was a mistake on my part and I would like to request Lai to kindly
forgive me. I'm looking forward to working with Lai effectively, going
forward.
Thank you!
Regards,
Srivatsa S. Bhat
^ permalink raw reply
* Re: [PATCH v6 04/46] percpu_rwlock: Implement the core design of Per-CPU Reader-Writer Locks
From: Srivatsa S. Bhat @ 2013-03-01 19:47 UTC (permalink / raw)
To: Lai Jiangshan
Cc: Lai Jiangshan, Michel Lespinasse, linux-doc, peterz, fweisbec,
linux-kernel, namhyung, mingo, linux-arch, linux, xiaoguangrong,
wangyun, paulmck, nikunj, linux-pm, rusty, rostedt, rjw,
vincent.guittot, tglx, linux-arm-kernel, netdev, oleg, sbw, tj,
akpm, linuxppc-dev
In-Reply-To: <5130EA6B.6030901@cn.fujitsu.com>
On 03/01/2013 11:20 PM, Lai Jiangshan wrote:
> On 28/02/13 05:19, Srivatsa S. Bhat wrote:
>> On 02/27/2013 06:03 AM, Lai Jiangshan wrote:
>>> On Wed, Feb 27, 2013 at 3:30 AM, Srivatsa S. Bhat
>>> <srivatsa.bhat@linux.vnet.ibm.com> wrote:
>>>> On 02/26/2013 09:55 PM, Lai Jiangshan wrote:
>>>>> On Tue, Feb 26, 2013 at 10:22 PM, Srivatsa S. Bhat
>>>>> <srivatsa.bhat@linux.vnet.ibm.com> wrote:
>>>>>>
>>>>>> Hi Lai,
>>>>>>
>>>>>> I'm really not convinced that piggy-backing on lglocks would help
>>>>>> us in any way. But still, let me try to address some of the points
>>>>>> you raised...
>>>>>>
>>>>>> On 02/26/2013 06:29 PM, Lai Jiangshan wrote:
>>>>>>> On Tue, Feb 26, 2013 at 5:02 PM, Srivatsa S. Bhat
>>>>>>> <srivatsa.bhat@linux.vnet.ibm.com> wrote:
>>>>>>>> On 02/26/2013 05:47 AM, Lai Jiangshan wrote:
>>>>>>>>> On Tue, Feb 26, 2013 at 3:26 AM, Srivatsa S. Bhat
>>>>>>>>> <srivatsa.bhat@linux.vnet.ibm.com> wrote:
>>>>>>>>>> Hi Lai,
>>>>>>>>>>
>>>>>>>>>> On 02/25/2013 09:23 PM, Lai Jiangshan wrote:
>>>>>>>>>>> Hi, Srivatsa,
>>>>>>>>>>>
>>>>>>>>>>> The target of the whole patchset is nice for me.
>>>>>>>>>>
>>>>>>>>>> Cool! Thanks :-)
>>>>>>>>>>
>>>>>>>> [...]
>>>>>>>>
>>>>>>>> Unfortunately, I see quite a few issues with the code above. IIUC, the
>>>>>>>> writer and the reader both increment the same counters. So how will the
>>>>>>>> unlock() code in the reader path know when to unlock which of the locks?
>>>>>>>
>>>>>>> The same as your code, the reader(which nested in write C.S.) just dec
>>>>>>> the counters.
>>>>>>
>>>>>> And that works fine in my case because the writer and the reader update
>>>>>> _two_ _different_ counters.
>>>>>
>>>>> I can't find any magic in your code, they are the same counter.
>>>>>
>>>>> /*
>>>>> * It is desirable to allow the writer to acquire the percpu-rwlock
>>>>> * for read (if necessary), without deadlocking or getting complaints
>>>>> * from lockdep. To achieve that, just increment the reader_refcnt of
>>>>> * this CPU - that way, any attempt by the writer to acquire the
>>>>> * percpu-rwlock for read, will get treated as a case of nested percpu
>>>>> * reader, which is safe, from a locking perspective.
>>>>> */
>>>>> this_cpu_inc(pcpu_rwlock->rw_state->reader_refcnt);
>>>>>
>>>>
>>>> Whoa! Hold on, were you really referring to _this_ increment when you said
>>>> that, in your patch you would increment the refcnt at the writer? Then I guess
>>>> there is a major disconnect in our conversations. (I had assumed that you were
>>>> referring to the update of writer_signal, and were just trying to have a single
>>>> refcnt instead of reader_refcnt and writer_signal).
>>>
>>> https://github.com/laijs/linux/commit/53e5053d5b724bea7c538b11743d0f420d98f38d
>>>
>>> Sorry the name "fallback_reader_refcnt" misled you.
>>>
>> [...]
>>
>>>>> All I was considered is "nested reader is seldom", so I always
>>>>> fallback to rwlock when nested.
>>>>> If you like, I can add 6 lines of code, the overhead is
>>>>> 1 spin_try_lock()(fast path) + N __this_cpu_inc()
>>>>>
>>>>
>>>> I'm assuming that calculation is no longer valid, considering that
>>>> we just discussed how the per-cpu refcnt that you were using is quite
>>>> unnecessary and can be removed.
>>>>
>>>> IIUC, the overhead with your code, as per above discussion would be:
>>>> 1 spin_try_lock() [non-nested] + N read_lock(global_rwlock).
>>>
>>> https://github.com/laijs/linux/commit/46334544bb7961550b7065e015da76f6dab21f16
>>>
>>> Again, I'm so sorry the name "fallback_reader_refcnt" misled you.
>>>
>>
>> At this juncture I really have to admit that I don't understand your
>> intentions at all. What are you really trying to prove? Without giving
>> a single good reason why my code is inferior, why are you even bringing
>> up the discussion about a complete rewrite of the synchronization code?
>> http://article.gmane.org/gmane.linux.kernel.cross-arch/17103
>> http://article.gmane.org/gmane.linux.power-management.general/31345
>>
>> I'm beginning to add 2 + 2 together based on the kinds of questions you
>> have been asking...
>>
>> You posted a patch in this thread and started a discussion around it without
>> even establishing a strong reason to do so. Now you point me to your git
>> tree where your patches have even more traces of ideas being borrowed from
>> my patchset (apart from my own ideas/code, there are traces of others' ideas
>> being borrowed too - for example, it was Oleg who originally proposed the
>> idea of splitting up the counter into 2 parts and I'm seeing that it is
>> slowly crawling into your code with no sign of appropriate credits).
>> http://article.gmane.org/gmane.linux.network/260288
>>
>> And in reply to my mail pointing out the performance implications of the
>> global read_lock at the reader side in your code, you said you'll come up
>> with a comparison between that and my patchset.
>> http://article.gmane.org/gmane.linux.network/260288
>> The issue has been well-documented in my patch description of patch 4.
>> http://article.gmane.org/gmane.linux.kernel/1443258
>>
>> Are you really trying to pit bits and pieces of my own ideas/versions
>> against one another and claiming them as your own?
>>
>> You projected the work involved in handling the locking issues pertaining
>> to CPU_DYING notifiers etc as a TODO, despite the fact that I had explicitly
>> noted in my cover letter that I had audited and taken care of all of them.
>> http://article.gmane.org/gmane.linux.documentation/9727
>> http://article.gmane.org/gmane.linux.documentation/9520
>>
>> You failed to acknowledge (on purpose?) that I had done a tree-wide
>> conversion despite the fact that you were replying to the very thread which
>> had the 46 patches which did exactly that (and I had also mentioned it
>> explicitly in my cover letter).
>> http://article.gmane.org/gmane.linux.documentation/9727
>> http://article.gmane.org/gmane.linux.documentation/9520
>>
>> You then started probing more and more about the technique I used to do
>> the tree-wide conversion.
>> http://article.gmane.org/gmane.linux.kernel.cross-arch/17111
>>
>> You also retorted saying you did go through my patch descriptions, so
>> its not like you have missed reading them.
>> http://article.gmane.org/gmane.linux.power-management.general/31345
>>
>> Each of these when considered individually, might appear like innocuous and
>> honest attempts at evaluating my code. But when put together, I'm beginning
>> to sense a whole different angle to it altogether, as if you are trying
>> to spin your own patch series, complete with the locking framework _and_
>> the tree-wide conversion, heavily borrowed from mine. At the beginning of
>> this discussion, I predicted that the lglock version that you are proposing
>> would end up being either less efficient than my version or look very similar
>> to my version. http://article.gmane.org/gmane.linux.kernel/1447139
>>
>> I thought it was just the former till now, but its not hard to see how it
>> is getting closer to becoming the latter too. So yeah, I'm not amused.
>>
>> Maybe (and hopefully) you are just trying out different ideas on your own,
>> and I'm just being paranoid. I really hope that is the case. If you are just
>> trying to review my code, then please stop sending patches with borrowed ideas
>> with your sole Signed-off-by, and purposefully ignoring the work already done
>> in my patchset, because it is really starting to look suspicious, at least
>> to me.
>>
>> Don't get me wrong - I'll whole-heartedly acknowledge and appreciate if
>> _your_ code is better than mine. I just don't like the idea of somebody
>> plagiarizing my ideas/code (or even others' ideas for that matter).
>> However, I sincerely apologize in advance if I misunderstood/misjudged your
>> intentions; I just wanted to voice my concerns out loud at this point,
>> considering the bad feeling I got by looking at your responses collectively.
>>
>
> Hi, Srivatsa
>
> I'm sorry, big apology to you.
> I'm bad in communication and I did be wrong.
> I tended to improve the codes but in false direction.
>
OK, in that case, I'm extremely sorry too, for jumping on you like that.
I hope you'll forgive me for the uneasiness it caused.
Now that I understand that you were simply trying to help, I would like to
express my gratitude for your time, effort and inputs in improving the design
of the stop-machine replacement.
I'm looking forward to working with you on this as well as future endeavours,
so I sincerely hope that we can put this unfortunate incident behind us and
collaborate effectively with renewed mutual trust and good-will.
Thank you very much!
Regards,
Srivatsa S. Bhat
^ permalink raw reply
* Re: [net-next (TAKE 2) 0/4] IPv6 over Firewire
From: Stephan Gatzka @ 2013-03-01 19:44 UTC (permalink / raw)
To: stephan.gatzka; +Cc: YOSHIFUJI Hideaki, netdev, linux1394-devel, davem, stefanr
In-Reply-To: <511A9BFC.9010907@gmail.com>
Hi Yoshfuji,
> Nevertheless, there is some hope that I can try out your patch set
> during this week and find some insight why IPv6 does not work with
MacOS X.
Unfortunately, until now I did not find some time to try out your IPv6
over firewire implementation. But now I did.
I just fired a ping6 from my Linux box running your kernel.
Using a FireSpy device I sniffed directly on the firewire line and
dumped the ndisc packets. They look pretty well, I can't see any
problems. The only thing I can't really judge about is the ICMPv6
checksum. But wireshark says the checksum is correct.
The packets send from MacOS X also look good, but yes, their
(recalculated) checksum might be wrong. The wireshark running on my
receiving linux box does not agree with the checksum send by MacOS X.
Now I would also assume that MacOS X is wrong. To proof that you can
test your code against MacOS X with CHECKSUM_UNNECESSARY. I would assume
that your implementation will work then. Unfortunately I no longer have
the MacOS laptop available.
Regards,
Stephan
^ permalink raw reply
* Re: pull request: wireless 2013-03-01
From: John W. Linville @ 2013-03-01 19:37 UTC (permalink / raw)
To: davem; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20130301192332.GE27114@tuxdriver.com>
[-- Attachment #1: Type: text/plain, Size: 37106 bytes --]
Ooops! Forgot signature...
On Fri, Mar 01, 2013 at 02:23:32PM -0500, John W. Linville wrote:
> Dave,
>
> This is another flurry of fixes intended for the 3.9 stream...
>
> A mac80211 pull from Johannes:
>
> "Seth fixes a stupid bug I introduced into one of his earlier patches,
> Chun-Yeow fixes mesh forwarding and Felix fixes monitor mode. I myself
> fixed a small locking issue and, the biggest change here, removed some
> nl80211 information with which sometimes the per wiphy information was
> getting too large for the typical 4k-minus-overhead. In my -next tree I
> have a patch to allow splitting that and add back the information
> removed now."
>
> An iwlwifi pull from Johannes:
>
> "I have a fix for a pretty important bug regarding DMA mapping, that
> could cause the DMA engine to overwrite data we wanted to send to it, so
> that the next time we send it it would be bad. This particularly affects
> calibration results. Other than that, three little fixes for the MVM
> driver."
>
> But wait, there's more!
>
> Avinash Patil fixes an incorrectly timed delay in mwifiex.
>
> Bing Zhao prevents a crash in SD8688 caused by failing to properly
> set a flag before issuing a command.
>
> Felix Fietkau is the big here this time, providing a trio of minor
> ath9k fixes and correcting the advertised interface combinations for
> rt2x00 when mesh support is disabled.
>
> Finally, Hauke Mehrtens gives us a patch that correctlin initializes
> a spin lock in the bcma code.
>
> Please let me know if there are problems!
>
> Thanks,
>
> John
>
> ---
>
> The following changes since commit 32fcafbcd1c9f6c7013016a22a5369b4acb93577:
>
> net/phy: micrel: Disable asymmetric pause for KSZ9021 (2013-02-28 15:37:30 -0500)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git for-davem
>
> for you to fetch changes up to 98b7ff9a4977e4f4f451c30288b197ad79e5ab7f:
>
> Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless into for-davem (2013-03-01 13:52:03 -0500)
>
> ----------------------------------------------------------------
>
> Avinash Patil (1):
> mwifiex: correct sleep delay counter
>
> Bing Zhao (1):
> libertas: fix crash for SD8688
>
> Chun-Yeow Yeoh (1):
> mac80211: fix the problem of forwarding from DS to DS in Mesh
>
> Dor Shaish (1):
> iwlwifi: mvm: Remove testing of static PIC in PhyDB
>
> Felix Fietkau (6):
> mac80211: fix idle handling in monitor mode
> mac80211: fix monitor mode channel reporting
> ath9k: fix RSSI dummy marker value
> ath9k_htc: fix signal strength handling issues
> ath9k_hw: improve reset reliability after errors
> rt2x00: error in configurations with mesh support disabled
>
> Hauke Mehrtens (1):
> bcma: init spin lock
>
> Johannes Berg (6):
> mac80211: fix tim_lock locking
> nl80211: remove radar information
> nl80211: remove TCP WoWLAN information
> iwlwifi: always copy first 16 bytes of commands
> iwlwifi: mvm: fix AP/GO mode station removal
> iwlwifi: fix wakeup status query and packet reporting
>
> John W. Linville (2):
> Merge branch 'for-john' of git://git.kernel.org/.../iwlwifi/iwlwifi-fixes
> Merge branch 'master' of git://git.kernel.org/.../linville/wireless into for-davem
>
> Seth Forshee (1):
> mac80211: Ensure off-channel frames don't get queued
>
> drivers/bcma/driver_pci_host.c | 2 +
> drivers/net/wireless/ath/ath9k/common.h | 2 +-
> drivers/net/wireless/ath/ath9k/htc.h | 1 +
> drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 18 +++--
> drivers/net/wireless/ath/ath9k/hw.c | 4 +-
> drivers/net/wireless/iwlwifi/iwl-devtrace.h | 10 +--
> drivers/net/wireless/iwlwifi/iwl-phy-db.c | 16 ----
> drivers/net/wireless/iwlwifi/mvm/d3.c | 104 +++++++++++++++++++-------
> drivers/net/wireless/iwlwifi/mvm/mac80211.c | 19 +++--
> drivers/net/wireless/iwlwifi/mvm/mvm.h | 4 +
> drivers/net/wireless/iwlwifi/pcie/internal.h | 9 +++
> drivers/net/wireless/iwlwifi/pcie/tx.c | 75 ++++++++++++++-----
> drivers/net/wireless/libertas/if_sdio.c | 6 +-
> drivers/net/wireless/mwifiex/pcie.c | 2 +-
> drivers/net/wireless/rt2x00/rt2x00dev.c | 8 +-
> net/mac80211/cfg.c | 12 ++-
> net/mac80211/iface.c | 2 +-
> net/mac80211/tx.c | 77 ++++++++++++-------
> net/wireless/nl80211.c | 61 +--------------
> 19 files changed, 258 insertions(+), 174 deletions(-)
>
> diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c
> index d3bde6c..30629a3 100644
> --- a/drivers/bcma/driver_pci_host.c
> +++ b/drivers/bcma/driver_pci_host.c
> @@ -404,6 +404,8 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
> return;
> }
>
> + spin_lock_init(&pc_host->cfgspace_lock);
> +
> pc->host_controller = pc_host;
> pc_host->pci_controller.io_resource = &pc_host->io_resource;
> pc_host->pci_controller.mem_resource = &pc_host->mem_resource;
> diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
> index 5f845be..050ca4a 100644
> --- a/drivers/net/wireless/ath/ath9k/common.h
> +++ b/drivers/net/wireless/ath/ath9k/common.h
> @@ -27,7 +27,7 @@
> #define WME_MAX_BA WME_BA_BMP_SIZE
> #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA)
>
> -#define ATH_RSSI_DUMMY_MARKER 0x127
> +#define ATH_RSSI_DUMMY_MARKER 127
> #define ATH_RSSI_LPF_LEN 10
> #define RSSI_LPF_THRESHOLD -20
> #define ATH_RSSI_EP_MULTIPLIER (1<<7)
> diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
> index 96bfb18..d3b099d 100644
> --- a/drivers/net/wireless/ath/ath9k/htc.h
> +++ b/drivers/net/wireless/ath/ath9k/htc.h
> @@ -22,6 +22,7 @@
> #include <linux/firmware.h>
> #include <linux/skbuff.h>
> #include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
> #include <linux/leds.h>
> #include <linux/slab.h>
> #include <net/mac80211.h>
> diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> index 3ad1fd0..bd8251c 100644
> --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
> @@ -1067,15 +1067,19 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
>
> last_rssi = priv->rx.last_rssi;
>
> - if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
> - rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi,
> - ATH_RSSI_EP_MULTIPLIER);
> + if (ieee80211_is_beacon(hdr->frame_control) &&
> + !is_zero_ether_addr(common->curbssid) &&
> + ether_addr_equal(hdr->addr3, common->curbssid)) {
> + s8 rssi = rxbuf->rxstatus.rs_rssi;
>
> - if (rxbuf->rxstatus.rs_rssi < 0)
> - rxbuf->rxstatus.rs_rssi = 0;
> + if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
> + rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
>
> - if (ieee80211_is_beacon(fc))
> - priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi;
> + if (rssi < 0)
> + rssi = 0;
> +
> + priv->ah->stats.avgbrssi = rssi;
> + }
>
> rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
> rx_status->band = hw->conf.channel->band;
> diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
> index 2a2ae40..07e2526 100644
> --- a/drivers/net/wireless/ath/ath9k/hw.c
> +++ b/drivers/net/wireless/ath/ath9k/hw.c
> @@ -1463,7 +1463,9 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah,
> reset_type = ATH9K_RESET_POWER_ON;
> else
> reset_type = ATH9K_RESET_COLD;
> - }
> + } else if (ah->chip_fullsleep || REG_READ(ah, AR_Q_TXE) ||
> + (REG_READ(ah, AR_CR) & AR_CR_RXE))
> + reset_type = ATH9K_RESET_COLD;
>
> if (!ath9k_hw_set_reset_reg(ah, reset_type))
> return false;
> diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
> index 9a0f45e..10f0179 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h
> +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
> @@ -349,25 +349,23 @@ TRACE_EVENT(iwlwifi_dev_rx_data,
> TRACE_EVENT(iwlwifi_dev_hcmd,
> TP_PROTO(const struct device *dev,
> struct iwl_host_cmd *cmd, u16 total_size,
> - const void *hdr, size_t hdr_len),
> - TP_ARGS(dev, cmd, total_size, hdr, hdr_len),
> + struct iwl_cmd_header *hdr),
> + TP_ARGS(dev, cmd, total_size, hdr),
> TP_STRUCT__entry(
> DEV_ENTRY
> __dynamic_array(u8, hcmd, total_size)
> __field(u32, flags)
> ),
> TP_fast_assign(
> - int i, offset = hdr_len;
> + int i, offset = sizeof(*hdr);
>
> DEV_ASSIGN;
> __entry->flags = cmd->flags;
> - memcpy(__get_dynamic_array(hcmd), hdr, hdr_len);
> + memcpy(__get_dynamic_array(hcmd), hdr, sizeof(*hdr));
>
> for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
> if (!cmd->len[i])
> continue;
> - if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
> - continue;
> memcpy((u8 *)__get_dynamic_array(hcmd) + offset,
> cmd->data[i], cmd->len[i]);
> offset += cmd->len[i];
> diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/drivers/net/wireless/iwlwifi/iwl-phy-db.c
> index 14fc8d3..3392011 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-phy-db.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.c
> @@ -136,12 +136,6 @@ struct iwl_calib_res_notif_phy_db {
> u8 data[];
> } __packed;
>
> -#define IWL_PHY_DB_STATIC_PIC cpu_to_le32(0x21436587)
> -static inline void iwl_phy_db_test_pic(__le32 pic)
> -{
> - WARN_ON(IWL_PHY_DB_STATIC_PIC != pic);
> -}
> -
> struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans)
> {
> struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db),
> @@ -260,11 +254,6 @@ int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt,
> (size - CHANNEL_NUM_SIZE) / phy_db->channel_num;
> }
>
> - /* Test PIC */
> - if (type != IWL_PHY_DB_CFG)
> - iwl_phy_db_test_pic(*(((__le32 *)phy_db_notif->data) +
> - (size / sizeof(__le32)) - 1));
> -
> IWL_DEBUG_INFO(phy_db->trans,
> "%s(%d): [PHYDB]SET: Type %d , Size: %d\n",
> __func__, __LINE__, type, size);
> @@ -372,11 +361,6 @@ int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db,
> *size = entry->size;
> }
>
> - /* Test PIC */
> - if (type != IWL_PHY_DB_CFG)
> - iwl_phy_db_test_pic(*(((__le32 *)*data) +
> - (*size / sizeof(__le32)) - 1));
> -
> IWL_DEBUG_INFO(phy_db->trans,
> "%s(%d): [PHYDB] GET: Type %d , Size: %d\n",
> __func__, __LINE__, type, *size);
> diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
> index c64d864..994c8c2 100644
> --- a/drivers/net/wireless/iwlwifi/mvm/d3.c
> +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
> @@ -61,6 +61,7 @@
> *
> *****************************************************************************/
>
> +#include <linux/etherdevice.h>
> #include <net/cfg80211.h>
> #include <net/ipv6.h>
> #include "iwl-modparams.h"
> @@ -192,6 +193,11 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
> sizeof(wkc), &wkc);
> data->error = ret != 0;
>
> + mvm->ptk_ivlen = key->iv_len;
> + mvm->ptk_icvlen = key->icv_len;
> + mvm->gtk_ivlen = key->iv_len;
> + mvm->gtk_icvlen = key->icv_len;
> +
> /* don't upload key again */
> goto out_unlock;
> }
> @@ -304,9 +310,13 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
> */
> if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
> key->hw_key_idx = 0;
> + mvm->ptk_ivlen = key->iv_len;
> + mvm->ptk_icvlen = key->icv_len;
> } else {
> data->gtk_key_idx++;
> key->hw_key_idx = data->gtk_key_idx;
> + mvm->gtk_ivlen = key->iv_len;
> + mvm->gtk_icvlen = key->icv_len;
> }
>
> ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, true);
> @@ -649,6 +659,11 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
> /* We reprogram keys and shouldn't allocate new key indices */
> memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
>
> + mvm->ptk_ivlen = 0;
> + mvm->ptk_icvlen = 0;
> + mvm->ptk_ivlen = 0;
> + mvm->ptk_icvlen = 0;
> +
> /*
> * The D3 firmware still hardcodes the AP station ID for the
> * BSS we're associated with as 0. As a result, we have to move
> @@ -783,7 +798,6 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
> struct iwl_wowlan_status *status;
> u32 reasons;
> int ret, len;
> - bool pkt8023 = false;
> struct sk_buff *pkt = NULL;
>
> iwl_trans_read_mem_bytes(mvm->trans, base,
> @@ -824,7 +838,8 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
> status = (void *)cmd.resp_pkt->data;
>
> if (len - sizeof(struct iwl_cmd_header) !=
> - sizeof(*status) + le32_to_cpu(status->wake_packet_bufsize)) {
> + sizeof(*status) +
> + ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4)) {
> IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
> goto out;
> }
> @@ -836,61 +851,96 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
> goto report;
> }
>
> - if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET) {
> + if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET)
> wakeup.magic_pkt = true;
> - pkt8023 = true;
> - }
>
> - if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) {
> + if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN)
> wakeup.pattern_idx =
> le16_to_cpu(status->pattern_number);
> - pkt8023 = true;
> - }
>
> if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON |
> IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH))
> wakeup.disconnect = true;
>
> - if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE) {
> + if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE)
> wakeup.gtk_rekey_failure = true;
> - pkt8023 = true;
> - }
>
> - if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED) {
> + if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED)
> wakeup.rfkill_release = true;
> - pkt8023 = true;
> - }
>
> - if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST) {
> + if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST)
> wakeup.eap_identity_req = true;
> - pkt8023 = true;
> - }
>
> - if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) {
> + if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE)
> wakeup.four_way_handshake = true;
> - pkt8023 = true;
> - }
>
> if (status->wake_packet_bufsize) {
> - u32 pktsize = le32_to_cpu(status->wake_packet_bufsize);
> - u32 pktlen = le32_to_cpu(status->wake_packet_length);
> + int pktsize = le32_to_cpu(status->wake_packet_bufsize);
> + int pktlen = le32_to_cpu(status->wake_packet_length);
> + const u8 *pktdata = status->wake_packet;
> + struct ieee80211_hdr *hdr = (void *)pktdata;
> + int truncated = pktlen - pktsize;
> +
> + /* this would be a firmware bug */
> + if (WARN_ON_ONCE(truncated < 0))
> + truncated = 0;
> +
> + if (ieee80211_is_data(hdr->frame_control)) {
> + int hdrlen = ieee80211_hdrlen(hdr->frame_control);
> + int ivlen = 0, icvlen = 4; /* also FCS */
>
> - if (pkt8023) {
> pkt = alloc_skb(pktsize, GFP_KERNEL);
> if (!pkt)
> goto report;
> - memcpy(skb_put(pkt, pktsize), status->wake_packet,
> - pktsize);
> +
> + memcpy(skb_put(pkt, hdrlen), pktdata, hdrlen);
> + pktdata += hdrlen;
> + pktsize -= hdrlen;
> +
> + if (ieee80211_has_protected(hdr->frame_control)) {
> + if (is_multicast_ether_addr(hdr->addr1)) {
> + ivlen = mvm->gtk_ivlen;
> + icvlen += mvm->gtk_icvlen;
> + } else {
> + ivlen = mvm->ptk_ivlen;
> + icvlen += mvm->ptk_icvlen;
> + }
> + }
> +
> + /* if truncated, FCS/ICV is (partially) gone */
> + if (truncated >= icvlen) {
> + icvlen = 0;
> + truncated -= icvlen;
> + } else {
> + icvlen -= truncated;
> + truncated = 0;
> + }
> +
> + pktsize -= ivlen + icvlen;
> + pktdata += ivlen;
> +
> + memcpy(skb_put(pkt, pktsize), pktdata, pktsize);
> +
> if (ieee80211_data_to_8023(pkt, vif->addr, vif->type))
> goto report;
> wakeup.packet = pkt->data;
> wakeup.packet_present_len = pkt->len;
> - wakeup.packet_len = pkt->len - (pktlen - pktsize);
> + wakeup.packet_len = pkt->len - truncated;
> wakeup.packet_80211 = false;
> } else {
> + int fcslen = 4;
> +
> + if (truncated >= 4) {
> + truncated -= 4;
> + fcslen = 0;
> + } else {
> + fcslen -= truncated;
> + truncated = 0;
> + }
> + pktsize -= fcslen;
> wakeup.packet = status->wake_packet;
> wakeup.packet_present_len = pktsize;
> - wakeup.packet_len = pktlen;
> + wakeup.packet_len = pktlen - truncated;
> wakeup.packet_80211 = true;
> }
> }
> diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
> index e8264e1..7e169b0 100644
> --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
> +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
> @@ -557,11 +557,9 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
> return ret;
> }
>
> -static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
> - struct ieee80211_vif *vif)
> +static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
> + struct ieee80211_vif *vif)
> {
> - struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
> - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
> u32 tfd_msk = 0, ac;
>
> for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
> @@ -594,12 +592,21 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
> */
> flush_work(&mvm->sta_drained_wk);
> }
> +}
> +
> +static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
> + struct ieee80211_vif *vif)
> +{
> + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
> + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
> +
> + iwl_mvm_prepare_mac_removal(mvm, vif);
>
> mutex_lock(&mvm->mutex);
>
> /*
> * For AP/GO interface, the tear down of the resources allocated to the
> - * interface should be handled as part of the bss_info_changed flow.
> + * interface is be handled as part of the stop_ap flow.
> */
> if (vif->type == NL80211_IFTYPE_AP) {
> iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta);
> @@ -763,6 +770,8 @@ static void iwl_mvm_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
> struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
> struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
>
> + iwl_mvm_prepare_mac_removal(mvm, vif);
> +
> mutex_lock(&mvm->mutex);
>
> mvmvif->ap_active = false;
> diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
> index 4e339cc..537711b 100644
> --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
> +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
> @@ -327,6 +327,10 @@ struct iwl_mvm {
> struct led_classdev led;
>
> struct ieee80211_vif *p2p_device_vif;
> +
> +#ifdef CONFIG_PM_SLEEP
> + int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen;
> +#endif
> };
>
> /* Extract MVM priv from op_mode and _hw */
> diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
> index aa2a39a..3d62e80 100644
> --- a/drivers/net/wireless/iwlwifi/pcie/internal.h
> +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
> @@ -182,6 +182,15 @@ struct iwl_queue {
> #define TFD_TX_CMD_SLOTS 256
> #define TFD_CMD_SLOTS 32
>
> +/*
> + * The FH will write back to the first TB only, so we need
> + * to copy some data into the buffer regardless of whether
> + * it should be mapped or not. This indicates how much to
> + * copy, even for HCMDs it must be big enough to fit the
> + * DRAM scratch from the TX cmd, at least 16 bytes.
> + */
> +#define IWL_HCMD_MIN_COPY_SIZE 16
> +
> struct iwl_pcie_txq_entry {
> struct iwl_device_cmd *cmd;
> struct iwl_device_cmd *copy_cmd;
> diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
> index 8e9e321..8b625a7 100644
> --- a/drivers/net/wireless/iwlwifi/pcie/tx.c
> +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
> @@ -1152,10 +1152,12 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
> void *dup_buf = NULL;
> dma_addr_t phys_addr;
> int idx;
> - u16 copy_size, cmd_size;
> + u16 copy_size, cmd_size, dma_size;
> bool had_nocopy = false;
> int i;
> u32 cmd_pos;
> + const u8 *cmddata[IWL_MAX_CMD_TFDS];
> + u16 cmdlen[IWL_MAX_CMD_TFDS];
>
> copy_size = sizeof(out_cmd->hdr);
> cmd_size = sizeof(out_cmd->hdr);
> @@ -1164,8 +1166,23 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
> BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1);
>
> for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
> + cmddata[i] = cmd->data[i];
> + cmdlen[i] = cmd->len[i];
> +
> if (!cmd->len[i])
> continue;
> +
> + /* need at least IWL_HCMD_MIN_COPY_SIZE copied */
> + if (copy_size < IWL_HCMD_MIN_COPY_SIZE) {
> + int copy = IWL_HCMD_MIN_COPY_SIZE - copy_size;
> +
> + if (copy > cmdlen[i])
> + copy = cmdlen[i];
> + cmdlen[i] -= copy;
> + cmddata[i] += copy;
> + copy_size += copy;
> + }
> +
> if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) {
> had_nocopy = true;
> if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) {
> @@ -1185,7 +1202,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
> goto free_dup_buf;
> }
>
> - dup_buf = kmemdup(cmd->data[i], cmd->len[i],
> + dup_buf = kmemdup(cmddata[i], cmdlen[i],
> GFP_ATOMIC);
> if (!dup_buf)
> return -ENOMEM;
> @@ -1195,7 +1212,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
> idx = -EINVAL;
> goto free_dup_buf;
> }
> - copy_size += cmd->len[i];
> + copy_size += cmdlen[i];
> }
> cmd_size += cmd->len[i];
> }
> @@ -1242,14 +1259,31 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
>
> /* and copy the data that needs to be copied */
> cmd_pos = offsetof(struct iwl_device_cmd, payload);
> + copy_size = sizeof(out_cmd->hdr);
> for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
> - if (!cmd->len[i])
> + int copy = 0;
> +
> + if (!cmd->len)
> continue;
> - if (cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
> - IWL_HCMD_DFL_DUP))
> - break;
> - memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]);
> - cmd_pos += cmd->len[i];
> +
> + /* need at least IWL_HCMD_MIN_COPY_SIZE copied */
> + if (copy_size < IWL_HCMD_MIN_COPY_SIZE) {
> + copy = IWL_HCMD_MIN_COPY_SIZE - copy_size;
> +
> + if (copy > cmd->len[i])
> + copy = cmd->len[i];
> + }
> +
> + /* copy everything if not nocopy/dup */
> + if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
> + IWL_HCMD_DFL_DUP)))
> + copy = cmd->len[i];
> +
> + if (copy) {
> + memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy);
> + cmd_pos += copy;
> + copy_size += copy;
> + }
> }
>
> WARN_ON_ONCE(txq->entries[idx].copy_cmd);
> @@ -1275,7 +1309,14 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
> out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
> cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue);
>
> - phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size,
> + /*
> + * If the entire command is smaller than IWL_HCMD_MIN_COPY_SIZE, we must
> + * still map at least that many bytes for the hardware to write back to.
> + * We have enough space, so that's not a problem.
> + */
> + dma_size = max_t(u16, copy_size, IWL_HCMD_MIN_COPY_SIZE);
> +
> + phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, dma_size,
> DMA_BIDIRECTIONAL);
> if (unlikely(dma_mapping_error(trans->dev, phys_addr))) {
> idx = -ENOMEM;
> @@ -1283,14 +1324,15 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
> }
>
> dma_unmap_addr_set(out_meta, mapping, phys_addr);
> - dma_unmap_len_set(out_meta, len, copy_size);
> + dma_unmap_len_set(out_meta, len, dma_size);
>
> iwl_pcie_txq_build_tfd(trans, txq, phys_addr, copy_size, 1);
>
> + /* map the remaining (adjusted) nocopy/dup fragments */
> for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
> - const void *data = cmd->data[i];
> + const void *data = cmddata[i];
>
> - if (!cmd->len[i])
> + if (!cmdlen[i])
> continue;
> if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
> IWL_HCMD_DFL_DUP)))
> @@ -1298,7 +1340,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
> if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP)
> data = dup_buf;
> phys_addr = dma_map_single(trans->dev, (void *)data,
> - cmd->len[i], DMA_BIDIRECTIONAL);
> + cmdlen[i], DMA_BIDIRECTIONAL);
> if (dma_mapping_error(trans->dev, phys_addr)) {
> iwl_pcie_tfd_unmap(trans, out_meta,
> &txq->tfds[q->write_ptr],
> @@ -1307,7 +1349,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
> goto out;
> }
>
> - iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmd->len[i], 0);
> + iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], 0);
> }
>
> out_meta->flags = cmd->flags;
> @@ -1317,8 +1359,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
>
> txq->need_update = 1;
>
> - trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size,
> - &out_cmd->hdr, copy_size);
> + trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr);
>
> /* start timer if queue currently empty */
> if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout)
> diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
> index 739309e..4557833 100644
> --- a/drivers/net/wireless/libertas/if_sdio.c
> +++ b/drivers/net/wireless/libertas/if_sdio.c
> @@ -825,6 +825,11 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card)
>
> sdio_release_host(func);
>
> + /* Set fw_ready before queuing any commands so that
> + * lbs_thread won't block from sending them to firmware.
> + */
> + priv->fw_ready = 1;
> +
> /*
> * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
> */
> @@ -839,7 +844,6 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card)
> netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n");
> }
>
> - priv->fw_ready = 1;
> wake_up(&card->pwron_waitq);
>
> if (!card->started) {
> diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
> index 35c7972..5c395e2 100644
> --- a/drivers/net/wireless/mwifiex/pcie.c
> +++ b/drivers/net/wireless/mwifiex/pcie.c
> @@ -302,7 +302,7 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
> i++;
> usleep_range(10, 20);
> /* 50ms max wait */
> - if (i == 50000)
> + if (i == 5000)
> break;
> }
>
> diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
> index 1031db6..189744d 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
> @@ -1236,8 +1236,10 @@ static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev)
> */
> if_limit = &rt2x00dev->if_limits_ap;
> if_limit->max = rt2x00dev->ops->max_ap_intf;
> - if_limit->types = BIT(NL80211_IFTYPE_AP) |
> - BIT(NL80211_IFTYPE_MESH_POINT);
> + if_limit->types = BIT(NL80211_IFTYPE_AP);
> +#ifdef CONFIG_MAC80211_MESH
> + if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT);
> +#endif
>
> /*
> * Build up AP interface combinations structure.
> @@ -1309,7 +1311,9 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
> rt2x00dev->hw->wiphy->interface_modes |=
> BIT(NL80211_IFTYPE_ADHOC) |
> BIT(NL80211_IFTYPE_AP) |
> +#ifdef CONFIG_MAC80211_MESH
> BIT(NL80211_IFTYPE_MESH_POINT) |
> +#endif
> BIT(NL80211_IFTYPE_WDS);
>
> rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
> diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
> index 09d96a8..808f5fc 100644
> --- a/net/mac80211/cfg.c
> +++ b/net/mac80211/cfg.c
> @@ -3285,13 +3285,19 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
> struct cfg80211_chan_def *chandef)
> {
> struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
> + struct ieee80211_local *local = wiphy_priv(wiphy);
> struct ieee80211_chanctx_conf *chanctx_conf;
> int ret = -ENODATA;
>
> rcu_read_lock();
> - chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
> - if (chanctx_conf) {
> - *chandef = chanctx_conf->def;
> + if (local->use_chanctx) {
> + chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
> + if (chanctx_conf) {
> + *chandef = chanctx_conf->def;
> + ret = 0;
> + }
> + } else if (local->open_count == local->monitors) {
> + *chandef = local->monitor_chandef;
> ret = 0;
> }
> rcu_read_unlock();
> diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
> index 2c059e5..640afab 100644
> --- a/net/mac80211/iface.c
> +++ b/net/mac80211/iface.c
> @@ -107,7 +107,7 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)
>
> lockdep_assert_held(&local->mtx);
>
> - active = !list_empty(&local->chanctx_list);
> + active = !list_empty(&local->chanctx_list) || local->monitors;
>
> if (!local->ops->remain_on_channel) {
> list_for_each_entry(roc, &local->roc_list, list) {
> diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
> index 5b9602b..c592a41 100644
> --- a/net/mac80211/tx.c
> +++ b/net/mac80211/tx.c
> @@ -1231,34 +1231,40 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
> if (local->queue_stop_reasons[q] ||
> (!txpending && !skb_queue_empty(&local->pending[q]))) {
> if (unlikely(info->flags &
> - IEEE80211_TX_INTFL_OFFCHAN_TX_OK &&
> - local->queue_stop_reasons[q] &
> - ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL))) {
> + IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) {
> + if (local->queue_stop_reasons[q] &
> + ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) {
> + /*
> + * Drop off-channel frames if queues
> + * are stopped for any reason other
> + * than off-channel operation. Never
> + * queue them.
> + */
> + spin_unlock_irqrestore(
> + &local->queue_stop_reason_lock,
> + flags);
> + ieee80211_purge_tx_queue(&local->hw,
> + skbs);
> + return true;
> + }
> + } else {
> +
> /*
> - * Drop off-channel frames if queues are stopped
> - * for any reason other than off-channel
> - * operation. Never queue them.
> + * Since queue is stopped, queue up frames for
> + * later transmission from the tx-pending
> + * tasklet when the queue is woken again.
> */
> - spin_unlock_irqrestore(
> - &local->queue_stop_reason_lock, flags);
> - ieee80211_purge_tx_queue(&local->hw, skbs);
> - return true;
> + if (txpending)
> + skb_queue_splice_init(skbs,
> + &local->pending[q]);
> + else
> + skb_queue_splice_tail_init(skbs,
> + &local->pending[q]);
> +
> + spin_unlock_irqrestore(&local->queue_stop_reason_lock,
> + flags);
> + return false;
> }
> -
> - /*
> - * Since queue is stopped, queue up frames for later
> - * transmission from the tx-pending tasklet when the
> - * queue is woken again.
> - */
> - if (txpending)
> - skb_queue_splice_init(skbs, &local->pending[q]);
> - else
> - skb_queue_splice_tail_init(skbs,
> - &local->pending[q]);
> -
> - spin_unlock_irqrestore(&local->queue_stop_reason_lock,
> - flags);
> - return false;
> }
> spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
>
> @@ -1844,9 +1850,24 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
> }
>
> if (!is_multicast_ether_addr(skb->data)) {
> + struct sta_info *next_hop;
> + bool mpp_lookup = true;
> +
> mpath = mesh_path_lookup(sdata, skb->data);
> - if (!mpath)
> + if (mpath) {
> + mpp_lookup = false;
> + next_hop = rcu_dereference(mpath->next_hop);
> + if (!next_hop ||
> + !(mpath->flags & (MESH_PATH_ACTIVE |
> + MESH_PATH_RESOLVING)))
> + mpp_lookup = true;
> + }
> +
> + if (mpp_lookup)
> mppath = mpp_path_lookup(sdata, skb->data);
> +
> + if (mppath && mpath)
> + mesh_path_del(mpath->sdata, mpath->dst);
> }
>
> /*
> @@ -2360,9 +2381,9 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
> if (local->tim_in_locked_section) {
> __ieee80211_beacon_add_tim(sdata, ps, skb);
> } else {
> - spin_lock(&local->tim_lock);
> + spin_lock_bh(&local->tim_lock);
> __ieee80211_beacon_add_tim(sdata, ps, skb);
> - spin_unlock(&local->tim_lock);
> + spin_unlock_bh(&local->tim_lock);
> }
>
> return 0;
> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index 35545cc..e652d05 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -554,16 +554,9 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
> if ((chan->flags & IEEE80211_CHAN_NO_IBSS) &&
> nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS))
> goto nla_put_failure;
> - if (chan->flags & IEEE80211_CHAN_RADAR) {
> - u32 time = elapsed_jiffies_msecs(chan->dfs_state_entered);
> - if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
> - goto nla_put_failure;
> - if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE,
> - chan->dfs_state))
> - goto nla_put_failure;
> - if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, time))
> - goto nla_put_failure;
> - }
> + if ((chan->flags & IEEE80211_CHAN_RADAR) &&
> + nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
> + goto nla_put_failure;
> if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) &&
> nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS))
> goto nla_put_failure;
> @@ -900,9 +893,6 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy,
> nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
> c->max_interfaces))
> goto nla_put_failure;
> - if (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
> - c->radar_detect_widths))
> - goto nla_put_failure;
>
> nla_nest_end(msg, nl_combi);
> }
> @@ -914,48 +904,6 @@ nla_put_failure:
> return -ENOBUFS;
> }
>
> -#ifdef CONFIG_PM
> -static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev,
> - struct sk_buff *msg)
> -{
> - const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan.tcp;
> - struct nlattr *nl_tcp;
> -
> - if (!tcp)
> - return 0;
> -
> - nl_tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION);
> - if (!nl_tcp)
> - return -ENOBUFS;
> -
> - if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
> - tcp->data_payload_max))
> - return -ENOBUFS;
> -
> - if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
> - tcp->data_payload_max))
> - return -ENOBUFS;
> -
> - if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ))
> - return -ENOBUFS;
> -
> - if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
> - sizeof(*tcp->tok), tcp->tok))
> - return -ENOBUFS;
> -
> - if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
> - tcp->data_interval_max))
> - return -ENOBUFS;
> -
> - if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
> - tcp->wake_payload_max))
> - return -ENOBUFS;
> -
> - nla_nest_end(msg, nl_tcp);
> - return 0;
> -}
> -#endif
> -
> static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags,
> struct cfg80211_registered_device *dev)
> {
> @@ -1330,9 +1278,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
> goto nla_put_failure;
> }
>
> - if (nl80211_send_wowlan_tcp_caps(dev, msg))
> - goto nla_put_failure;
> -
> nla_nest_end(msg, nl_wowlan);
> }
> #endif
> --
> John W. Linville Someday the world will need a hero, and you
> linville@tuxdriver.com might be all we have. Be ready.
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* pull request: wireless 2013-03-01
From: John W. Linville @ 2013-03-01 19:23 UTC (permalink / raw)
To: davem; +Cc: linux-wireless, netdev, linux-kernel
Dave,
This is another flurry of fixes intended for the 3.9 stream...
A mac80211 pull from Johannes:
"Seth fixes a stupid bug I introduced into one of his earlier patches,
Chun-Yeow fixes mesh forwarding and Felix fixes monitor mode. I myself
fixed a small locking issue and, the biggest change here, removed some
nl80211 information with which sometimes the per wiphy information was
getting too large for the typical 4k-minus-overhead. In my -next tree I
have a patch to allow splitting that and add back the information
removed now."
An iwlwifi pull from Johannes:
"I have a fix for a pretty important bug regarding DMA mapping, that
could cause the DMA engine to overwrite data we wanted to send to it, so
that the next time we send it it would be bad. This particularly affects
calibration results. Other than that, three little fixes for the MVM
driver."
But wait, there's more!
Avinash Patil fixes an incorrectly timed delay in mwifiex.
Bing Zhao prevents a crash in SD8688 caused by failing to properly
set a flag before issuing a command.
Felix Fietkau is the big here this time, providing a trio of minor
ath9k fixes and correcting the advertised interface combinations for
rt2x00 when mesh support is disabled.
Finally, Hauke Mehrtens gives us a patch that correctlin initializes
a spin lock in the bcma code.
Please let me know if there are problems!
Thanks,
John
---
The following changes since commit 32fcafbcd1c9f6c7013016a22a5369b4acb93577:
net/phy: micrel: Disable asymmetric pause for KSZ9021 (2013-02-28 15:37:30 -0500)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git for-davem
for you to fetch changes up to 98b7ff9a4977e4f4f451c30288b197ad79e5ab7f:
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless into for-davem (2013-03-01 13:52:03 -0500)
----------------------------------------------------------------
Avinash Patil (1):
mwifiex: correct sleep delay counter
Bing Zhao (1):
libertas: fix crash for SD8688
Chun-Yeow Yeoh (1):
mac80211: fix the problem of forwarding from DS to DS in Mesh
Dor Shaish (1):
iwlwifi: mvm: Remove testing of static PIC in PhyDB
Felix Fietkau (6):
mac80211: fix idle handling in monitor mode
mac80211: fix monitor mode channel reporting
ath9k: fix RSSI dummy marker value
ath9k_htc: fix signal strength handling issues
ath9k_hw: improve reset reliability after errors
rt2x00: error in configurations with mesh support disabled
Hauke Mehrtens (1):
bcma: init spin lock
Johannes Berg (6):
mac80211: fix tim_lock locking
nl80211: remove radar information
nl80211: remove TCP WoWLAN information
iwlwifi: always copy first 16 bytes of commands
iwlwifi: mvm: fix AP/GO mode station removal
iwlwifi: fix wakeup status query and packet reporting
John W. Linville (2):
Merge branch 'for-john' of git://git.kernel.org/.../iwlwifi/iwlwifi-fixes
Merge branch 'master' of git://git.kernel.org/.../linville/wireless into for-davem
Seth Forshee (1):
mac80211: Ensure off-channel frames don't get queued
drivers/bcma/driver_pci_host.c | 2 +
drivers/net/wireless/ath/ath9k/common.h | 2 +-
drivers/net/wireless/ath/ath9k/htc.h | 1 +
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 18 +++--
drivers/net/wireless/ath/ath9k/hw.c | 4 +-
drivers/net/wireless/iwlwifi/iwl-devtrace.h | 10 +--
drivers/net/wireless/iwlwifi/iwl-phy-db.c | 16 ----
drivers/net/wireless/iwlwifi/mvm/d3.c | 104 +++++++++++++++++++-------
drivers/net/wireless/iwlwifi/mvm/mac80211.c | 19 +++--
drivers/net/wireless/iwlwifi/mvm/mvm.h | 4 +
drivers/net/wireless/iwlwifi/pcie/internal.h | 9 +++
drivers/net/wireless/iwlwifi/pcie/tx.c | 75 ++++++++++++++-----
drivers/net/wireless/libertas/if_sdio.c | 6 +-
drivers/net/wireless/mwifiex/pcie.c | 2 +-
drivers/net/wireless/rt2x00/rt2x00dev.c | 8 +-
net/mac80211/cfg.c | 12 ++-
net/mac80211/iface.c | 2 +-
net/mac80211/tx.c | 77 ++++++++++++-------
net/wireless/nl80211.c | 61 +--------------
19 files changed, 258 insertions(+), 174 deletions(-)
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c
index d3bde6c..30629a3 100644
--- a/drivers/bcma/driver_pci_host.c
+++ b/drivers/bcma/driver_pci_host.c
@@ -404,6 +404,8 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
return;
}
+ spin_lock_init(&pc_host->cfgspace_lock);
+
pc->host_controller = pc_host;
pc_host->pci_controller.io_resource = &pc_host->io_resource;
pc_host->pci_controller.mem_resource = &pc_host->mem_resource;
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index 5f845be..050ca4a 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -27,7 +27,7 @@
#define WME_MAX_BA WME_BA_BMP_SIZE
#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA)
-#define ATH_RSSI_DUMMY_MARKER 0x127
+#define ATH_RSSI_DUMMY_MARKER 127
#define ATH_RSSI_LPF_LEN 10
#define RSSI_LPF_THRESHOLD -20
#define ATH_RSSI_EP_MULTIPLIER (1<<7)
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 96bfb18..d3b099d 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -22,6 +22,7 @@
#include <linux/firmware.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
#include <linux/leds.h>
#include <linux/slab.h>
#include <net/mac80211.h>
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 3ad1fd0..bd8251c 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -1067,15 +1067,19 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
last_rssi = priv->rx.last_rssi;
- if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
- rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi,
- ATH_RSSI_EP_MULTIPLIER);
+ if (ieee80211_is_beacon(hdr->frame_control) &&
+ !is_zero_ether_addr(common->curbssid) &&
+ ether_addr_equal(hdr->addr3, common->curbssid)) {
+ s8 rssi = rxbuf->rxstatus.rs_rssi;
- if (rxbuf->rxstatus.rs_rssi < 0)
- rxbuf->rxstatus.rs_rssi = 0;
+ if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
+ rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
- if (ieee80211_is_beacon(fc))
- priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi;
+ if (rssi < 0)
+ rssi = 0;
+
+ priv->ah->stats.avgbrssi = rssi;
+ }
rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
rx_status->band = hw->conf.channel->band;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 2a2ae40..07e2526 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1463,7 +1463,9 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah,
reset_type = ATH9K_RESET_POWER_ON;
else
reset_type = ATH9K_RESET_COLD;
- }
+ } else if (ah->chip_fullsleep || REG_READ(ah, AR_Q_TXE) ||
+ (REG_READ(ah, AR_CR) & AR_CR_RXE))
+ reset_type = ATH9K_RESET_COLD;
if (!ath9k_hw_set_reset_reg(ah, reset_type))
return false;
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
index 9a0f45e..10f0179 100644
--- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h
+++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
@@ -349,25 +349,23 @@ TRACE_EVENT(iwlwifi_dev_rx_data,
TRACE_EVENT(iwlwifi_dev_hcmd,
TP_PROTO(const struct device *dev,
struct iwl_host_cmd *cmd, u16 total_size,
- const void *hdr, size_t hdr_len),
- TP_ARGS(dev, cmd, total_size, hdr, hdr_len),
+ struct iwl_cmd_header *hdr),
+ TP_ARGS(dev, cmd, total_size, hdr),
TP_STRUCT__entry(
DEV_ENTRY
__dynamic_array(u8, hcmd, total_size)
__field(u32, flags)
),
TP_fast_assign(
- int i, offset = hdr_len;
+ int i, offset = sizeof(*hdr);
DEV_ASSIGN;
__entry->flags = cmd->flags;
- memcpy(__get_dynamic_array(hcmd), hdr, hdr_len);
+ memcpy(__get_dynamic_array(hcmd), hdr, sizeof(*hdr));
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
if (!cmd->len[i])
continue;
- if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
- continue;
memcpy((u8 *)__get_dynamic_array(hcmd) + offset,
cmd->data[i], cmd->len[i]);
offset += cmd->len[i];
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/drivers/net/wireless/iwlwifi/iwl-phy-db.c
index 14fc8d3..3392011 100644
--- a/drivers/net/wireless/iwlwifi/iwl-phy-db.c
+++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.c
@@ -136,12 +136,6 @@ struct iwl_calib_res_notif_phy_db {
u8 data[];
} __packed;
-#define IWL_PHY_DB_STATIC_PIC cpu_to_le32(0x21436587)
-static inline void iwl_phy_db_test_pic(__le32 pic)
-{
- WARN_ON(IWL_PHY_DB_STATIC_PIC != pic);
-}
-
struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans)
{
struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db),
@@ -260,11 +254,6 @@ int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt,
(size - CHANNEL_NUM_SIZE) / phy_db->channel_num;
}
- /* Test PIC */
- if (type != IWL_PHY_DB_CFG)
- iwl_phy_db_test_pic(*(((__le32 *)phy_db_notif->data) +
- (size / sizeof(__le32)) - 1));
-
IWL_DEBUG_INFO(phy_db->trans,
"%s(%d): [PHYDB]SET: Type %d , Size: %d\n",
__func__, __LINE__, type, size);
@@ -372,11 +361,6 @@ int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db,
*size = entry->size;
}
- /* Test PIC */
- if (type != IWL_PHY_DB_CFG)
- iwl_phy_db_test_pic(*(((__le32 *)*data) +
- (*size / sizeof(__le32)) - 1));
-
IWL_DEBUG_INFO(phy_db->trans,
"%s(%d): [PHYDB] GET: Type %d , Size: %d\n",
__func__, __LINE__, type, *size);
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index c64d864..994c8c2 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -61,6 +61,7 @@
*
*****************************************************************************/
+#include <linux/etherdevice.h>
#include <net/cfg80211.h>
#include <net/ipv6.h>
#include "iwl-modparams.h"
@@ -192,6 +193,11 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
sizeof(wkc), &wkc);
data->error = ret != 0;
+ mvm->ptk_ivlen = key->iv_len;
+ mvm->ptk_icvlen = key->icv_len;
+ mvm->gtk_ivlen = key->iv_len;
+ mvm->gtk_icvlen = key->icv_len;
+
/* don't upload key again */
goto out_unlock;
}
@@ -304,9 +310,13 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
*/
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
key->hw_key_idx = 0;
+ mvm->ptk_ivlen = key->iv_len;
+ mvm->ptk_icvlen = key->icv_len;
} else {
data->gtk_key_idx++;
key->hw_key_idx = data->gtk_key_idx;
+ mvm->gtk_ivlen = key->iv_len;
+ mvm->gtk_icvlen = key->icv_len;
}
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, true);
@@ -649,6 +659,11 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
/* We reprogram keys and shouldn't allocate new key indices */
memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
+ mvm->ptk_ivlen = 0;
+ mvm->ptk_icvlen = 0;
+ mvm->ptk_ivlen = 0;
+ mvm->ptk_icvlen = 0;
+
/*
* The D3 firmware still hardcodes the AP station ID for the
* BSS we're associated with as 0. As a result, we have to move
@@ -783,7 +798,6 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
struct iwl_wowlan_status *status;
u32 reasons;
int ret, len;
- bool pkt8023 = false;
struct sk_buff *pkt = NULL;
iwl_trans_read_mem_bytes(mvm->trans, base,
@@ -824,7 +838,8 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
status = (void *)cmd.resp_pkt->data;
if (len - sizeof(struct iwl_cmd_header) !=
- sizeof(*status) + le32_to_cpu(status->wake_packet_bufsize)) {
+ sizeof(*status) +
+ ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4)) {
IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
goto out;
}
@@ -836,61 +851,96 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
goto report;
}
- if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET) {
+ if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET)
wakeup.magic_pkt = true;
- pkt8023 = true;
- }
- if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) {
+ if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN)
wakeup.pattern_idx =
le16_to_cpu(status->pattern_number);
- pkt8023 = true;
- }
if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON |
IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH))
wakeup.disconnect = true;
- if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE) {
+ if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE)
wakeup.gtk_rekey_failure = true;
- pkt8023 = true;
- }
- if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED) {
+ if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED)
wakeup.rfkill_release = true;
- pkt8023 = true;
- }
- if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST) {
+ if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST)
wakeup.eap_identity_req = true;
- pkt8023 = true;
- }
- if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) {
+ if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE)
wakeup.four_way_handshake = true;
- pkt8023 = true;
- }
if (status->wake_packet_bufsize) {
- u32 pktsize = le32_to_cpu(status->wake_packet_bufsize);
- u32 pktlen = le32_to_cpu(status->wake_packet_length);
+ int pktsize = le32_to_cpu(status->wake_packet_bufsize);
+ int pktlen = le32_to_cpu(status->wake_packet_length);
+ const u8 *pktdata = status->wake_packet;
+ struct ieee80211_hdr *hdr = (void *)pktdata;
+ int truncated = pktlen - pktsize;
+
+ /* this would be a firmware bug */
+ if (WARN_ON_ONCE(truncated < 0))
+ truncated = 0;
+
+ if (ieee80211_is_data(hdr->frame_control)) {
+ int hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ int ivlen = 0, icvlen = 4; /* also FCS */
- if (pkt8023) {
pkt = alloc_skb(pktsize, GFP_KERNEL);
if (!pkt)
goto report;
- memcpy(skb_put(pkt, pktsize), status->wake_packet,
- pktsize);
+
+ memcpy(skb_put(pkt, hdrlen), pktdata, hdrlen);
+ pktdata += hdrlen;
+ pktsize -= hdrlen;
+
+ if (ieee80211_has_protected(hdr->frame_control)) {
+ if (is_multicast_ether_addr(hdr->addr1)) {
+ ivlen = mvm->gtk_ivlen;
+ icvlen += mvm->gtk_icvlen;
+ } else {
+ ivlen = mvm->ptk_ivlen;
+ icvlen += mvm->ptk_icvlen;
+ }
+ }
+
+ /* if truncated, FCS/ICV is (partially) gone */
+ if (truncated >= icvlen) {
+ icvlen = 0;
+ truncated -= icvlen;
+ } else {
+ icvlen -= truncated;
+ truncated = 0;
+ }
+
+ pktsize -= ivlen + icvlen;
+ pktdata += ivlen;
+
+ memcpy(skb_put(pkt, pktsize), pktdata, pktsize);
+
if (ieee80211_data_to_8023(pkt, vif->addr, vif->type))
goto report;
wakeup.packet = pkt->data;
wakeup.packet_present_len = pkt->len;
- wakeup.packet_len = pkt->len - (pktlen - pktsize);
+ wakeup.packet_len = pkt->len - truncated;
wakeup.packet_80211 = false;
} else {
+ int fcslen = 4;
+
+ if (truncated >= 4) {
+ truncated -= 4;
+ fcslen = 0;
+ } else {
+ fcslen -= truncated;
+ truncated = 0;
+ }
+ pktsize -= fcslen;
wakeup.packet = status->wake_packet;
wakeup.packet_present_len = pktsize;
- wakeup.packet_len = pktlen;
+ wakeup.packet_len = pktlen - truncated;
wakeup.packet_80211 = true;
}
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index e8264e1..7e169b0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -557,11 +557,9 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
return ret;
}
-static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u32 tfd_msk = 0, ac;
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
@@ -594,12 +592,21 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
*/
flush_work(&mvm->sta_drained_wk);
}
+}
+
+static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+ iwl_mvm_prepare_mac_removal(mvm, vif);
mutex_lock(&mvm->mutex);
/*
* For AP/GO interface, the tear down of the resources allocated to the
- * interface should be handled as part of the bss_info_changed flow.
+ * interface is be handled as part of the stop_ap flow.
*/
if (vif->type == NL80211_IFTYPE_AP) {
iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta);
@@ -763,6 +770,8 @@ static void iwl_mvm_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ iwl_mvm_prepare_mac_removal(mvm, vif);
+
mutex_lock(&mvm->mutex);
mvmvif->ap_active = false;
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 4e339cc..537711b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -327,6 +327,10 @@ struct iwl_mvm {
struct led_classdev led;
struct ieee80211_vif *p2p_device_vif;
+
+#ifdef CONFIG_PM_SLEEP
+ int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen;
+#endif
};
/* Extract MVM priv from op_mode and _hw */
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index aa2a39a..3d62e80 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -182,6 +182,15 @@ struct iwl_queue {
#define TFD_TX_CMD_SLOTS 256
#define TFD_CMD_SLOTS 32
+/*
+ * The FH will write back to the first TB only, so we need
+ * to copy some data into the buffer regardless of whether
+ * it should be mapped or not. This indicates how much to
+ * copy, even for HCMDs it must be big enough to fit the
+ * DRAM scratch from the TX cmd, at least 16 bytes.
+ */
+#define IWL_HCMD_MIN_COPY_SIZE 16
+
struct iwl_pcie_txq_entry {
struct iwl_device_cmd *cmd;
struct iwl_device_cmd *copy_cmd;
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 8e9e321..8b625a7 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -1152,10 +1152,12 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
void *dup_buf = NULL;
dma_addr_t phys_addr;
int idx;
- u16 copy_size, cmd_size;
+ u16 copy_size, cmd_size, dma_size;
bool had_nocopy = false;
int i;
u32 cmd_pos;
+ const u8 *cmddata[IWL_MAX_CMD_TFDS];
+ u16 cmdlen[IWL_MAX_CMD_TFDS];
copy_size = sizeof(out_cmd->hdr);
cmd_size = sizeof(out_cmd->hdr);
@@ -1164,8 +1166,23 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1);
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+ cmddata[i] = cmd->data[i];
+ cmdlen[i] = cmd->len[i];
+
if (!cmd->len[i])
continue;
+
+ /* need at least IWL_HCMD_MIN_COPY_SIZE copied */
+ if (copy_size < IWL_HCMD_MIN_COPY_SIZE) {
+ int copy = IWL_HCMD_MIN_COPY_SIZE - copy_size;
+
+ if (copy > cmdlen[i])
+ copy = cmdlen[i];
+ cmdlen[i] -= copy;
+ cmddata[i] += copy;
+ copy_size += copy;
+ }
+
if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) {
had_nocopy = true;
if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) {
@@ -1185,7 +1202,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
goto free_dup_buf;
}
- dup_buf = kmemdup(cmd->data[i], cmd->len[i],
+ dup_buf = kmemdup(cmddata[i], cmdlen[i],
GFP_ATOMIC);
if (!dup_buf)
return -ENOMEM;
@@ -1195,7 +1212,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
idx = -EINVAL;
goto free_dup_buf;
}
- copy_size += cmd->len[i];
+ copy_size += cmdlen[i];
}
cmd_size += cmd->len[i];
}
@@ -1242,14 +1259,31 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
/* and copy the data that needs to be copied */
cmd_pos = offsetof(struct iwl_device_cmd, payload);
+ copy_size = sizeof(out_cmd->hdr);
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
- if (!cmd->len[i])
+ int copy = 0;
+
+ if (!cmd->len)
continue;
- if (cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
- IWL_HCMD_DFL_DUP))
- break;
- memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]);
- cmd_pos += cmd->len[i];
+
+ /* need at least IWL_HCMD_MIN_COPY_SIZE copied */
+ if (copy_size < IWL_HCMD_MIN_COPY_SIZE) {
+ copy = IWL_HCMD_MIN_COPY_SIZE - copy_size;
+
+ if (copy > cmd->len[i])
+ copy = cmd->len[i];
+ }
+
+ /* copy everything if not nocopy/dup */
+ if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
+ IWL_HCMD_DFL_DUP)))
+ copy = cmd->len[i];
+
+ if (copy) {
+ memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy);
+ cmd_pos += copy;
+ copy_size += copy;
+ }
}
WARN_ON_ONCE(txq->entries[idx].copy_cmd);
@@ -1275,7 +1309,14 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue);
- phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size,
+ /*
+ * If the entire command is smaller than IWL_HCMD_MIN_COPY_SIZE, we must
+ * still map at least that many bytes for the hardware to write back to.
+ * We have enough space, so that's not a problem.
+ */
+ dma_size = max_t(u16, copy_size, IWL_HCMD_MIN_COPY_SIZE);
+
+ phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, dma_size,
DMA_BIDIRECTIONAL);
if (unlikely(dma_mapping_error(trans->dev, phys_addr))) {
idx = -ENOMEM;
@@ -1283,14 +1324,15 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
}
dma_unmap_addr_set(out_meta, mapping, phys_addr);
- dma_unmap_len_set(out_meta, len, copy_size);
+ dma_unmap_len_set(out_meta, len, dma_size);
iwl_pcie_txq_build_tfd(trans, txq, phys_addr, copy_size, 1);
+ /* map the remaining (adjusted) nocopy/dup fragments */
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
- const void *data = cmd->data[i];
+ const void *data = cmddata[i];
- if (!cmd->len[i])
+ if (!cmdlen[i])
continue;
if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
IWL_HCMD_DFL_DUP)))
@@ -1298,7 +1340,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP)
data = dup_buf;
phys_addr = dma_map_single(trans->dev, (void *)data,
- cmd->len[i], DMA_BIDIRECTIONAL);
+ cmdlen[i], DMA_BIDIRECTIONAL);
if (dma_mapping_error(trans->dev, phys_addr)) {
iwl_pcie_tfd_unmap(trans, out_meta,
&txq->tfds[q->write_ptr],
@@ -1307,7 +1349,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
goto out;
}
- iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmd->len[i], 0);
+ iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], 0);
}
out_meta->flags = cmd->flags;
@@ -1317,8 +1359,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
txq->need_update = 1;
- trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size,
- &out_cmd->hdr, copy_size);
+ trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr);
/* start timer if queue currently empty */
if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout)
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 739309e..4557833 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -825,6 +825,11 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card)
sdio_release_host(func);
+ /* Set fw_ready before queuing any commands so that
+ * lbs_thread won't block from sending them to firmware.
+ */
+ priv->fw_ready = 1;
+
/*
* FUNC_INIT is required for SD8688 WLAN/BT multiple functions
*/
@@ -839,7 +844,6 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card)
netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n");
}
- priv->fw_ready = 1;
wake_up(&card->pwron_waitq);
if (!card->started) {
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 35c7972..5c395e2 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -302,7 +302,7 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
i++;
usleep_range(10, 20);
/* 50ms max wait */
- if (i == 50000)
+ if (i == 5000)
break;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 1031db6..189744d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1236,8 +1236,10 @@ static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev)
*/
if_limit = &rt2x00dev->if_limits_ap;
if_limit->max = rt2x00dev->ops->max_ap_intf;
- if_limit->types = BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_MESH_POINT);
+ if_limit->types = BIT(NL80211_IFTYPE_AP);
+#ifdef CONFIG_MAC80211_MESH
+ if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT);
+#endif
/*
* Build up AP interface combinations structure.
@@ -1309,7 +1311,9 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
rt2x00dev->hw->wiphy->interface_modes |=
BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_AP) |
+#ifdef CONFIG_MAC80211_MESH
BIT(NL80211_IFTYPE_MESH_POINT) |
+#endif
BIT(NL80211_IFTYPE_WDS);
rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 09d96a8..808f5fc 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3285,13 +3285,19 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+ struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_chanctx_conf *chanctx_conf;
int ret = -ENODATA;
rcu_read_lock();
- chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
- if (chanctx_conf) {
- *chandef = chanctx_conf->def;
+ if (local->use_chanctx) {
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (chanctx_conf) {
+ *chandef = chanctx_conf->def;
+ ret = 0;
+ }
+ } else if (local->open_count == local->monitors) {
+ *chandef = local->monitor_chandef;
ret = 0;
}
rcu_read_unlock();
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 2c059e5..640afab 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -107,7 +107,7 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)
lockdep_assert_held(&local->mtx);
- active = !list_empty(&local->chanctx_list);
+ active = !list_empty(&local->chanctx_list) || local->monitors;
if (!local->ops->remain_on_channel) {
list_for_each_entry(roc, &local->roc_list, list) {
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 5b9602b..c592a41 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1231,34 +1231,40 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
if (local->queue_stop_reasons[q] ||
(!txpending && !skb_queue_empty(&local->pending[q]))) {
if (unlikely(info->flags &
- IEEE80211_TX_INTFL_OFFCHAN_TX_OK &&
- local->queue_stop_reasons[q] &
- ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL))) {
+ IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) {
+ if (local->queue_stop_reasons[q] &
+ ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) {
+ /*
+ * Drop off-channel frames if queues
+ * are stopped for any reason other
+ * than off-channel operation. Never
+ * queue them.
+ */
+ spin_unlock_irqrestore(
+ &local->queue_stop_reason_lock,
+ flags);
+ ieee80211_purge_tx_queue(&local->hw,
+ skbs);
+ return true;
+ }
+ } else {
+
/*
- * Drop off-channel frames if queues are stopped
- * for any reason other than off-channel
- * operation. Never queue them.
+ * Since queue is stopped, queue up frames for
+ * later transmission from the tx-pending
+ * tasklet when the queue is woken again.
*/
- spin_unlock_irqrestore(
- &local->queue_stop_reason_lock, flags);
- ieee80211_purge_tx_queue(&local->hw, skbs);
- return true;
+ if (txpending)
+ skb_queue_splice_init(skbs,
+ &local->pending[q]);
+ else
+ skb_queue_splice_tail_init(skbs,
+ &local->pending[q]);
+
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock,
+ flags);
+ return false;
}
-
- /*
- * Since queue is stopped, queue up frames for later
- * transmission from the tx-pending tasklet when the
- * queue is woken again.
- */
- if (txpending)
- skb_queue_splice_init(skbs, &local->pending[q]);
- else
- skb_queue_splice_tail_init(skbs,
- &local->pending[q]);
-
- spin_unlock_irqrestore(&local->queue_stop_reason_lock,
- flags);
- return false;
}
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
@@ -1844,9 +1850,24 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
}
if (!is_multicast_ether_addr(skb->data)) {
+ struct sta_info *next_hop;
+ bool mpp_lookup = true;
+
mpath = mesh_path_lookup(sdata, skb->data);
- if (!mpath)
+ if (mpath) {
+ mpp_lookup = false;
+ next_hop = rcu_dereference(mpath->next_hop);
+ if (!next_hop ||
+ !(mpath->flags & (MESH_PATH_ACTIVE |
+ MESH_PATH_RESOLVING)))
+ mpp_lookup = true;
+ }
+
+ if (mpp_lookup)
mppath = mpp_path_lookup(sdata, skb->data);
+
+ if (mppath && mpath)
+ mesh_path_del(mpath->sdata, mpath->dst);
}
/*
@@ -2360,9 +2381,9 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
if (local->tim_in_locked_section) {
__ieee80211_beacon_add_tim(sdata, ps, skb);
} else {
- spin_lock(&local->tim_lock);
+ spin_lock_bh(&local->tim_lock);
__ieee80211_beacon_add_tim(sdata, ps, skb);
- spin_unlock(&local->tim_lock);
+ spin_unlock_bh(&local->tim_lock);
}
return 0;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 35545cc..e652d05 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -554,16 +554,9 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
if ((chan->flags & IEEE80211_CHAN_NO_IBSS) &&
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS))
goto nla_put_failure;
- if (chan->flags & IEEE80211_CHAN_RADAR) {
- u32 time = elapsed_jiffies_msecs(chan->dfs_state_entered);
- if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
- goto nla_put_failure;
- if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE,
- chan->dfs_state))
- goto nla_put_failure;
- if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, time))
- goto nla_put_failure;
- }
+ if ((chan->flags & IEEE80211_CHAN_RADAR) &&
+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
+ goto nla_put_failure;
if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) &&
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS))
goto nla_put_failure;
@@ -900,9 +893,6 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy,
nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
c->max_interfaces))
goto nla_put_failure;
- if (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
- c->radar_detect_widths))
- goto nla_put_failure;
nla_nest_end(msg, nl_combi);
}
@@ -914,48 +904,6 @@ nla_put_failure:
return -ENOBUFS;
}
-#ifdef CONFIG_PM
-static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev,
- struct sk_buff *msg)
-{
- const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan.tcp;
- struct nlattr *nl_tcp;
-
- if (!tcp)
- return 0;
-
- nl_tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION);
- if (!nl_tcp)
- return -ENOBUFS;
-
- if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
- tcp->data_payload_max))
- return -ENOBUFS;
-
- if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
- tcp->data_payload_max))
- return -ENOBUFS;
-
- if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ))
- return -ENOBUFS;
-
- if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
- sizeof(*tcp->tok), tcp->tok))
- return -ENOBUFS;
-
- if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
- tcp->data_interval_max))
- return -ENOBUFS;
-
- if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
- tcp->wake_payload_max))
- return -ENOBUFS;
-
- nla_nest_end(msg, nl_tcp);
- return 0;
-}
-#endif
-
static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags,
struct cfg80211_registered_device *dev)
{
@@ -1330,9 +1278,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
goto nla_put_failure;
}
- if (nl80211_send_wowlan_tcp_caps(dev, msg))
- goto nla_put_failure;
-
nla_nest_end(msg, nl_wowlan);
}
#endif
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply related
* Re: [PATCH] l2tp: Restore socket refcount when sendmsg succeeds
From: David Miller @ 2013-03-01 19:12 UTC (permalink / raw)
To: g.nault; +Cc: jchapman, linux-kernel, netdev
In-Reply-To: <20130301150202.GA3649@alphalink.fr>
From: Guillaume Nault <g.nault@alphalink.fr>
Date: Fri, 1 Mar 2013 16:02:02 +0100
> The sendmsg() syscall handler for PPPoL2TP doesn't decrease the socket
> reference counter after successful transmissions. Any successful
> sendmsg() call from userspace will then increase the reference counter
> forever, thus preventing the kernel's session and tunnel data from
> being freed later on.
>
> The problem only happens when writing directly on L2TP sockets.
> PPP sockets attached to L2TP are unaffected as the PPP subsystem
> uses pppol2tp_xmit() which symmetrically increase/decrease reference
> counters.
>
> This patch adds the missing call to sock_put() before returning from
> pppol2tp_sendmsg().
>
> Cc: <stable@vger.kernel.org>
> Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
Looking at how this code works, it is such a terrible design. This
whole reference counting issue exists purely because
pppol2tp_sock_to_session() grabs the 'sk' reference.
In all but one case, it need not do this.
The socket system calls have an implicit reference to 'sk' via
socket->sk. If you can get into the system call and socket->sk
is non-NULL then 'sk' is NOT going anywhere.
And all of these system call handlers have this pattern:
session = pppol2tp_sock_to_session(sk);
...
sock_put(sk);
The only case where the reference count is really needed is that
sequence in pppol2tp_release().
Long term the right thing to do here is stop having this session
grabber function take the 'sk' reference. Then in pppol2tp_release
we'll grab a reference explicitly. At all the other call sites we
then blast aweay all of the sock_put(sk) paths.
Anyways, for now I'll apply this patch and queue it up for -stable,
thanks.
^ permalink raw reply
* Re: [PATCH] lglock: add read-preference local-global rwlock
From: Oleg Nesterov @ 2013-03-01 18:28 UTC (permalink / raw)
To: Lai Jiangshan
Cc: Srivatsa S. Bhat, Lai Jiangshan, Michel Lespinasse, linux-doc,
peterz, fweisbec, linux-kernel, namhyung, mingo, linux-arch,
linux, xiaoguangrong, wangyun, paulmck, nikunj, linux-pm, rusty,
rostedt, rjw, vincent.guittot, tglx, linux-arm-kernel, netdev,
sbw, tj, akpm, linuxppc-dev
In-Reply-To: <5130E8E2.50206@cn.fujitsu.com>
Lai, I didn't read this discussion except the code posted by Michel.
I'll try to read this patch carefully later, but I'd like to ask
a couple of questions.
This version looks more complex than Michel's, why? Just curious, I
am trying to understand what I missed. See
http://marc.info/?l=linux-kernel&m=136196350213593
And I can't understand FALLBACK_BASE...
OK, suppose that CPU_0 does _write_unlock() and releases ->fallback_rwlock.
CPU_1 does _read_lock(), and ...
> +void lg_rwlock_local_read_lock(struct lgrwlock *lgrw)
> +{
> + struct lglock *lg = &lgrw->lglock;
> +
> + preempt_disable();
> + rwlock_acquire_read(&lg->lock_dep_map, 0, 0, _RET_IP_);
> + if (likely(!__this_cpu_read(*lgrw->reader_refcnt))) {
> + if (!arch_spin_trylock(this_cpu_ptr(lg->lock))) {
_trylock() fails,
> + read_lock(&lgrw->fallback_rwlock);
> + __this_cpu_add(*lgrw->reader_refcnt, FALLBACK_BASE);
so we take ->fallback_rwlock and ->reader_refcnt == FALLBACK_BASE.
CPU_0 does lg_global_unlock(lgrw->lglock) and finishes _write_unlock().
Interrupt handler on CPU_1 does _read_lock() notices ->reader_refcnt != 0
and simply does this_cpu_inc(), so reader_refcnt == FALLBACK_BASE + 1.
Then irq does _read_unlock(), and
> +void lg_rwlock_local_read_unlock(struct lgrwlock *lgrw)
> +{
> + switch (__this_cpu_dec_return(*lgrw->reader_refcnt)) {
> + case 0:
> + lg_local_unlock(&lgrw->lglock);
> + return;
> + case FALLBACK_BASE:
> + __this_cpu_sub(*lgrw->reader_refcnt, FALLBACK_BASE);
> + read_unlock(&lgrw->fallback_rwlock);
hits this case?
Doesn't look right, but most probably I missed something.
Oleg.
^ permalink raw reply
* Re: [PATCH v6 04/46] percpu_rwlock: Implement the core design of Per-CPU Reader-Writer Locks
From: Tejun Heo @ 2013-03-01 18:10 UTC (permalink / raw)
To: Srivatsa S. Bhat
Cc: Lai Jiangshan, Michel Lespinasse, linux-doc, peterz, fweisbec,
linux-kernel, namhyung, mingo, linux-arch, linux, xiaoguangrong,
wangyun, paulmck, nikunj, linux-pm, rusty, rostedt, rjw,
vincent.guittot, tglx, linux-arm-kernel, netdev, oleg, sbw, akpm,
linuxppc-dev
In-Reply-To: <512E7879.20109@linux.vnet.ibm.com>
Hello, Srivatsa.
On Thu, Feb 28, 2013 at 02:49:53AM +0530, Srivatsa S. Bhat wrote:
> Don't get me wrong - I'll whole-heartedly acknowledge and appreciate if
> _your_ code is better than mine. I just don't like the idea of somebody
> plagiarizing my ideas/code (or even others' ideas for that matter).
> However, I sincerely apologize in advance if I misunderstood/misjudged your
> intentions; I just wanted to voice my concerns out loud at this point,
> considering the bad feeling I got by looking at your responses collectively.
Although I don't know Lai personally, from my experience working with
him past several months on workqueue, I strongly doubt he has dark
urterior intenions. The biggest problem probably is that his
communication in English isn't very fluent yet and thus doesn't carry
the underlying intentions or tones very well and he tends to bombard
patches in quick succession without much explanation inbetween (during
3.8 cycle, I was receiving several workqueue patchsets days apart
trying to solve the same problem with completely different approaches
way before the discussion on the previous postings reach any kind of
consensus). A lot of that also probably comes from communication
problems.
Anyways, I really don't think he's trying to take claim of your work.
At least for now, you kinda need to speculate what he's trying to do
and then confirm that back to him, but once you get used to that part,
he's pretty nice to work with and I'm sure his communication will
improve in time (I think it has gotten a lot better than only some
months ago).
Thanks!
--
tejun
^ permalink raw reply
* Re: [PATCH v2 net-next] ipv[4|6]: correct dropwatch false positive in local_deliver_finish
From: Eric Dumazet @ 2013-03-01 17:56 UTC (permalink / raw)
To: Neil Horman; +Cc: netdev, David S. Miller, William Reich
In-Reply-To: <1362159848-8530-1-git-send-email-nhorman@tuxdriver.com>
On Fri, 2013-03-01 at 12:44 -0500, Neil Horman wrote:
> I had a report recently of a user trying to use dropwatch to localise some frame
> loss, and they were getting false positives. Turned out they were using a user
> space SCTP stack that used raw sockets to grab frames. When we don't have a
> registered protocol for a given packet, we record it as a drop, even if a raw
> socket receieves the frame. We should only record the drop in the event a raw
> socket doesnt exist to receive the frames
>
> Tested by the reported successfully
>
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> Reported-by: William Reich <reich@ulticom.com>
> Tested-by: William Reich <reich@ulticom.com>
> CC: "David S. Miller" <davem@davemloft.net>
> CC: William Reich <reich@ulticom.com>
> CC: eric.dumazet@gmail.com
> ---
> net/ipv4/ip_input.c | 6 ++++--
> net/ipv6/ip6_input.c | 6 ++++--
> 2 files changed, 8 insertions(+), 4 deletions(-)
Thanks !
Acked-by: Eric Dumazet <edumazet@google.com>
^ permalink raw reply
* Re: [PATCH] lglock: add read-preference local-global rwlock
From: Tejun Heo @ 2013-03-01 17:53 UTC (permalink / raw)
To: Lai Jiangshan
Cc: Srivatsa S. Bhat, Lai Jiangshan, Michel Lespinasse, linux-doc,
peterz, fweisbec, linux-kernel, namhyung, mingo, linux-arch,
linux, xiaoguangrong, wangyun, paulmck, nikunj, linux-pm, rusty,
rostedt, rjw, vincent.guittot, tglx, linux-arm-kernel, netdev,
oleg, sbw, akpm, linuxppc-dev
In-Reply-To: <5130E8E2.50206@cn.fujitsu.com>
Hey, guys and Oleg (yes, I'm singling you out ;p because you're that
awesome.)
On Sat, Mar 02, 2013 at 01:44:02AM +0800, Lai Jiangshan wrote:
> Performance:
> We only focus on the performance of the read site. this read site's fast path
> is just preempt_disable() + __this_cpu_read/inc() + arch_spin_trylock(),
> It has only one heavy memory operation. it will be expected fast.
>
> We test three locks.
> 1) traditional rwlock WITHOUT remote competition nor cache-bouncing.(opt-rwlock)
> 2) this lock(lgrwlock)
> 3) V6 percpu-rwlock by "Srivatsa S. Bhat". (percpu-rwlock)
> (https://lkml.org/lkml/2013/2/18/186)
>
> nested=1(no nested) nested=2 nested=4
> opt-rwlock 517181 1009200 2010027
> lgrwlock 452897 700026 1201415
> percpu-rwlock 1192955 1451343 1951757
On the first glance, the numbers look pretty good and I kinda really
like the fact that if this works out we don't have to introduce yet
another percpu synchronization construct and get to reuse lglock.
So, Oleg, can you please see whether you can find holes in this one?
Srivatsa, I know you spent a lot of time on percpu_rwlock but as you
wrote before Lai's work can be seen as continuation of yours, and if
we get to extend what's already there instead of introducing something
completely new, there's no reason not to (and my apologies for not
noticing the possibility of extending lglock before). So, if this can
work, it would be awesome if you guys can work together. Lai might
not be very good at communicating in english yet but he's really good
at spotting patterns in complex code and playing with them.
Thanks!
--
tejun
^ permalink raw reply
* Re: [PATCH v6 04/46] percpu_rwlock: Implement the core design of Per-CPU Reader-Writer Locks
From: Lai Jiangshan @ 2013-03-01 17:50 UTC (permalink / raw)
To: Srivatsa S. Bhat
Cc: Lai Jiangshan, Michel Lespinasse, linux-doc, peterz, fweisbec,
linux-kernel, namhyung, mingo, linux-arch, linux, xiaoguangrong,
wangyun, paulmck, nikunj, linux-pm, rusty, rostedt, rjw,
vincent.guittot, tglx, linux-arm-kernel, netdev, oleg, sbw, tj,
akpm, linuxppc-dev
In-Reply-To: <512E7879.20109@linux.vnet.ibm.com>
On 28/02/13 05:19, Srivatsa S. Bhat wrote:
> On 02/27/2013 06:03 AM, Lai Jiangshan wrote:
>> On Wed, Feb 27, 2013 at 3:30 AM, Srivatsa S. Bhat
>> <srivatsa.bhat@linux.vnet.ibm.com> wrote:
>>> On 02/26/2013 09:55 PM, Lai Jiangshan wrote:
>>>> On Tue, Feb 26, 2013 at 10:22 PM, Srivatsa S. Bhat
>>>> <srivatsa.bhat@linux.vnet.ibm.com> wrote:
>>>>>
>>>>> Hi Lai,
>>>>>
>>>>> I'm really not convinced that piggy-backing on lglocks would help
>>>>> us in any way. But still, let me try to address some of the points
>>>>> you raised...
>>>>>
>>>>> On 02/26/2013 06:29 PM, Lai Jiangshan wrote:
>>>>>> On Tue, Feb 26, 2013 at 5:02 PM, Srivatsa S. Bhat
>>>>>> <srivatsa.bhat@linux.vnet.ibm.com> wrote:
>>>>>>> On 02/26/2013 05:47 AM, Lai Jiangshan wrote:
>>>>>>>> On Tue, Feb 26, 2013 at 3:26 AM, Srivatsa S. Bhat
>>>>>>>> <srivatsa.bhat@linux.vnet.ibm.com> wrote:
>>>>>>>>> Hi Lai,
>>>>>>>>>
>>>>>>>>> On 02/25/2013 09:23 PM, Lai Jiangshan wrote:
>>>>>>>>>> Hi, Srivatsa,
>>>>>>>>>>
>>>>>>>>>> The target of the whole patchset is nice for me.
>>>>>>>>>
>>>>>>>>> Cool! Thanks :-)
>>>>>>>>>
>>>>>>> [...]
>>>>>>>
>>>>>>> Unfortunately, I see quite a few issues with the code above. IIUC, the
>>>>>>> writer and the reader both increment the same counters. So how will the
>>>>>>> unlock() code in the reader path know when to unlock which of the locks?
>>>>>>
>>>>>> The same as your code, the reader(which nested in write C.S.) just dec
>>>>>> the counters.
>>>>>
>>>>> And that works fine in my case because the writer and the reader update
>>>>> _two_ _different_ counters.
>>>>
>>>> I can't find any magic in your code, they are the same counter.
>>>>
>>>> /*
>>>> * It is desirable to allow the writer to acquire the percpu-rwlock
>>>> * for read (if necessary), without deadlocking or getting complaints
>>>> * from lockdep. To achieve that, just increment the reader_refcnt of
>>>> * this CPU - that way, any attempt by the writer to acquire the
>>>> * percpu-rwlock for read, will get treated as a case of nested percpu
>>>> * reader, which is safe, from a locking perspective.
>>>> */
>>>> this_cpu_inc(pcpu_rwlock->rw_state->reader_refcnt);
>>>>
>>>
>>> Whoa! Hold on, were you really referring to _this_ increment when you said
>>> that, in your patch you would increment the refcnt at the writer? Then I guess
>>> there is a major disconnect in our conversations. (I had assumed that you were
>>> referring to the update of writer_signal, and were just trying to have a single
>>> refcnt instead of reader_refcnt and writer_signal).
>>
>> https://github.com/laijs/linux/commit/53e5053d5b724bea7c538b11743d0f420d98f38d
>>
>> Sorry the name "fallback_reader_refcnt" misled you.
>>
> [...]
>
>>>> All I was considered is "nested reader is seldom", so I always
>>>> fallback to rwlock when nested.
>>>> If you like, I can add 6 lines of code, the overhead is
>>>> 1 spin_try_lock()(fast path) + N __this_cpu_inc()
>>>>
>>>
>>> I'm assuming that calculation is no longer valid, considering that
>>> we just discussed how the per-cpu refcnt that you were using is quite
>>> unnecessary and can be removed.
>>>
>>> IIUC, the overhead with your code, as per above discussion would be:
>>> 1 spin_try_lock() [non-nested] + N read_lock(global_rwlock).
>>
>> https://github.com/laijs/linux/commit/46334544bb7961550b7065e015da76f6dab21f16
>>
>> Again, I'm so sorry the name "fallback_reader_refcnt" misled you.
>>
>
> At this juncture I really have to admit that I don't understand your
> intentions at all. What are you really trying to prove? Without giving
> a single good reason why my code is inferior, why are you even bringing
> up the discussion about a complete rewrite of the synchronization code?
> http://article.gmane.org/gmane.linux.kernel.cross-arch/17103
> http://article.gmane.org/gmane.linux.power-management.general/31345
>
> I'm beginning to add 2 + 2 together based on the kinds of questions you
> have been asking...
>
> You posted a patch in this thread and started a discussion around it without
> even establishing a strong reason to do so. Now you point me to your git
> tree where your patches have even more traces of ideas being borrowed from
> my patchset (apart from my own ideas/code, there are traces of others' ideas
> being borrowed too - for example, it was Oleg who originally proposed the
> idea of splitting up the counter into 2 parts and I'm seeing that it is
> slowly crawling into your code with no sign of appropriate credits).
> http://article.gmane.org/gmane.linux.network/260288
>
> And in reply to my mail pointing out the performance implications of the
> global read_lock at the reader side in your code, you said you'll come up
> with a comparison between that and my patchset.
> http://article.gmane.org/gmane.linux.network/260288
> The issue has been well-documented in my patch description of patch 4.
> http://article.gmane.org/gmane.linux.kernel/1443258
>
> Are you really trying to pit bits and pieces of my own ideas/versions
> against one another and claiming them as your own?
>
> You projected the work involved in handling the locking issues pertaining
> to CPU_DYING notifiers etc as a TODO, despite the fact that I had explicitly
> noted in my cover letter that I had audited and taken care of all of them.
> http://article.gmane.org/gmane.linux.documentation/9727
> http://article.gmane.org/gmane.linux.documentation/9520
>
> You failed to acknowledge (on purpose?) that I had done a tree-wide
> conversion despite the fact that you were replying to the very thread which
> had the 46 patches which did exactly that (and I had also mentioned it
> explicitly in my cover letter).
> http://article.gmane.org/gmane.linux.documentation/9727
> http://article.gmane.org/gmane.linux.documentation/9520
>
> You then started probing more and more about the technique I used to do
> the tree-wide conversion.
> http://article.gmane.org/gmane.linux.kernel.cross-arch/17111
>
> You also retorted saying you did go through my patch descriptions, so
> its not like you have missed reading them.
> http://article.gmane.org/gmane.linux.power-management.general/31345
>
> Each of these when considered individually, might appear like innocuous and
> honest attempts at evaluating my code. But when put together, I'm beginning
> to sense a whole different angle to it altogether, as if you are trying
> to spin your own patch series, complete with the locking framework _and_
> the tree-wide conversion, heavily borrowed from mine. At the beginning of
> this discussion, I predicted that the lglock version that you are proposing
> would end up being either less efficient than my version or look very similar
> to my version. http://article.gmane.org/gmane.linux.kernel/1447139
>
> I thought it was just the former till now, but its not hard to see how it
> is getting closer to becoming the latter too. So yeah, I'm not amused.
>
> Maybe (and hopefully) you are just trying out different ideas on your own,
> and I'm just being paranoid. I really hope that is the case. If you are just
> trying to review my code, then please stop sending patches with borrowed ideas
> with your sole Signed-off-by, and purposefully ignoring the work already done
> in my patchset, because it is really starting to look suspicious, at least
> to me.
>
> Don't get me wrong - I'll whole-heartedly acknowledge and appreciate if
> _your_ code is better than mine. I just don't like the idea of somebody
> plagiarizing my ideas/code (or even others' ideas for that matter).
> However, I sincerely apologize in advance if I misunderstood/misjudged your
> intentions; I just wanted to voice my concerns out loud at this point,
> considering the bad feeling I got by looking at your responses collectively.
>
Hi, Srivatsa
I'm sorry, big apology to you.
I'm bad in communication and I did be wrong.
I tended to improve the codes but in false direction.
Thanks,
Lai
^ permalink raw reply
* [PATCH v2 net-next] ipv[4|6]: correct dropwatch false positive in local_deliver_finish
From: Neil Horman @ 2013-03-01 17:44 UTC (permalink / raw)
To: netdev; +Cc: Neil Horman, David S. Miller, William Reich, eric.dumazet
I had a report recently of a user trying to use dropwatch to localise some frame
loss, and they were getting false positives. Turned out they were using a user
space SCTP stack that used raw sockets to grab frames. When we don't have a
registered protocol for a given packet, we record it as a drop, even if a raw
socket receieves the frame. We should only record the drop in the event a raw
socket doesnt exist to receive the frames
Tested by the reported successfully
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Reported-by: William Reich <reich@ulticom.com>
Tested-by: William Reich <reich@ulticom.com>
CC: "David S. Miller" <davem@davemloft.net>
CC: William Reich <reich@ulticom.com>
CC: eric.dumazet@gmail.com
---
net/ipv4/ip_input.c | 6 ++++--
net/ipv6/ip6_input.c | 6 ++++--
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 87abd3e..2bdf802 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -228,9 +228,11 @@ static int ip_local_deliver_finish(struct sk_buff *skb)
icmp_send(skb, ICMP_DEST_UNREACH,
ICMP_PROT_UNREACH, 0);
}
- } else
+ kfree_skb(skb);
+ } else {
IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS);
- kfree_skb(skb);
+ consume_skb(skb);
+ }
}
}
out:
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 5b10414..b1876e5 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -241,9 +241,11 @@ resubmit:
icmpv6_send(skb, ICMPV6_PARAMPROB,
ICMPV6_UNK_NEXTHDR, nhoff);
}
- } else
+ kfree_skb(skb);
+ } else {
IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS);
- kfree_skb(skb);
+ consume_skb(skb);
+ }
}
rcu_read_unlock();
return 0;
--
1.7.11.7
^ permalink raw reply related
* [PATCH] lglock: add read-preference local-global rwlock
From: Lai Jiangshan @ 2013-03-01 17:44 UTC (permalink / raw)
To: Srivatsa S. Bhat
Cc: Lai Jiangshan, Michel Lespinasse, linux-doc, peterz, fweisbec,
linux-kernel, namhyung, mingo, linux-arch, linux, xiaoguangrong,
wangyun, paulmck, nikunj, linux-pm, rusty, rostedt, rjw,
vincent.guittot, tglx, linux-arm-kernel, netdev, oleg, sbw, tj,
akpm, linuxppc-dev
In-Reply-To: <512E7879.20109@linux.vnet.ibm.com>
>From c63f2be9a4cf7106a521dda169a0e14f8e4f7e3b Mon Sep 17 00:00:00 2001
From: Lai Jiangshan <laijs@cn.fujitsu.com>
Date: Mon, 25 Feb 2013 23:14:27 +0800
Subject: [PATCH] lglock: add read-preference local-global rwlock
Current lglock is not read-preference, so it can't be used on some cases
which read-preference rwlock can do. Example, get_cpu_online_atomic().
Although we can use rwlock for these cases which needs read-preference.
but it leads to unnecessary cache-line bouncing even when there are no
writers present, which can slow down the system needlessly. It will be
worse when we have a lot of CPUs, it is not scale.
So we look forward to lglock. lglock is read-write-lock based on percpu locks,
but it is not read-preference due to its underlining percpu locks.
But what if we convert the percpu locks of lglock to use percpu rwlocks:
CPU 0 CPU 1
------ ------
1. spin_lock(&random_lock); read_lock(my_rwlock of CPU 1);
2. read_lock(my_rwlock of CPU 0); spin_lock(&random_lock);
Writer:
CPU 2:
------
for_each_online_cpu(cpu)
write_lock(my_rwlock of 'cpu');
Consider what happens if the writer begins his operation in between steps 1
and 2 at the reader side. It becomes evident that we end up in a (previously
non-existent) deadlock due to a circular locking dependency between the 3
entities, like this:
(holds Waiting for
random_lock) CPU 0 -------------> CPU 2 (holds my_rwlock of CPU 0
for write)
^ |
| |
Waiting| | Waiting
for | | for
| V
------ CPU 1 <------
(holds my_rwlock of
CPU 1 for read)
So obviously this "straight-forward" way of implementing percpu rwlocks is
deadlock-prone. So we can't implement read-preference local-global rwlock
like this.
The implement of this patch reuse current lglock as frontend to achieve
local-read-lock, and reuse global fallback rwlock as backend to achieve
read-preference, and use percpu reader counter to indicate 1) the depth
of the nested reader lockes and 2) whether the outmost lock is percpu lock
or fallback rwlock.
The algorithm is simple, in the read site:
If it is nested reader, just increase the counter
If it is the outmost reader,
1) try to lock its cpu's lock of the frontend lglock.
(reader count +=1 if success)
2) if the above step fails, read_lock(&fallback_rwlock).
(reader count += FALLBACK_BASE + 1)
Write site:
Do the lg_global_lock() of the frontend lglock.
And then write_lock(&fallback_rwlock).
Prof:
1) reader-writer exclusive:
The two steps of write site finished, no reader. Vice-verse.
2) read-preference:
before write site lock finished acquired, read site at least
wins at read_lock(&fallback_rwlock) for rwlock is read-preference.
read-preference also implies nestable.
3) read site functions are irqsafe(reentrance-safe)
If read site function is interrupted at any point and reenters read site
again, reentranced read site will not be mislead by the first read site if the
reader counter > 0, in this case, it means currently frontend(this cpu lock of
lglock) or backend(fallback rwlock) lock is held, it is safe to act as
nested reader.
if the reader counter=0, eentranced reader considers it is the
outmost read site, and it always successes after the write side release the lock.
(even the interrupted read-site has already hold the cpu lock of lglock
or the fallback_rwlock).
And reentranced read site only calls arch_spin_trylock(), read_lock()
and __this_cpu_op(), arch_spin_trylock(), read_lock() is already reentrance-safe.
Although __this_cpu_op() is not reentrance-safe, but the value of the counter
will be restored after the interrupted finished, so read site functions
are still reentrance-safe.
Performance:
We only focus on the performance of the read site. this read site's fast path
is just preempt_disable() + __this_cpu_read/inc() + arch_spin_trylock(),
It has only one heavy memory operation. it will be expected fast.
We test three locks.
1) traditional rwlock WITHOUT remote competition nor cache-bouncing.(opt-rwlock)
2) this lock(lgrwlock)
3) V6 percpu-rwlock by "Srivatsa S. Bhat". (percpu-rwlock)
(https://lkml.org/lkml/2013/2/18/186)
nested=1(no nested) nested=2 nested=4
opt-rwlock 517181 1009200 2010027
lgrwlock 452897 700026 1201415
percpu-rwlock 1192955 1451343 1951757
The value is the time(nano-second) of 10000 times of the operations:
{
read-lock
[nested read-lock]...
[nested read-unlock]...
read-unlock
}
If the way of this test is wrong nor bad, please correct me,
the code of test is here: https://gist.github.com/laijs/5066159
(i5 760, 64bit)
Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
---
include/linux/lglock.h | 35 ++++++++++++++++++++++++++++++++
kernel/lglock.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 87 insertions(+), 0 deletions(-)
diff --git a/include/linux/lglock.h b/include/linux/lglock.h
index 0d24e93..afb22bd 100644
--- a/include/linux/lglock.h
+++ b/include/linux/lglock.h
@@ -67,4 +67,39 @@ void lg_local_unlock_cpu(struct lglock *lg, int cpu);
void lg_global_lock(struct lglock *lg);
void lg_global_unlock(struct lglock *lg);
+struct lgrwlock {
+ unsigned long __percpu *reader_refcnt;
+ struct lglock lglock;
+ rwlock_t fallback_rwlock;
+};
+
+#define __DEFINE_LGRWLOCK_PERCPU_DATA(name) \
+ static DEFINE_PER_CPU(arch_spinlock_t, name ## _lock) \
+ = __ARCH_SPIN_LOCK_UNLOCKED; \
+ static DEFINE_PER_CPU(unsigned long, name ## _refcnt);
+
+#define __LGRWLOCK_INIT(name) \
+ { \
+ .reader_refcnt = &name ## _refcnt, \
+ .lglock = { .lock = &name ## _lock }, \
+ .fallback_rwlock = __RW_LOCK_UNLOCKED(name.fallback_rwlock)\
+ }
+
+#define DEFINE_LGRWLOCK(name) \
+ __DEFINE_LGRWLOCK_PERCPU_DATA(name) \
+ struct lgrwlock name = __LGRWLOCK_INIT(name)
+
+#define DEFINE_STATIC_LGRWLOCK(name) \
+ __DEFINE_LGRWLOCK_PERCPU_DATA(name) \
+ static struct lgrwlock name = __LGRWLOCK_INIT(name)
+
+static inline void lg_rwlock_init(struct lgrwlock *lgrw, char *name)
+{
+ lg_lock_init(&lgrw->lglock, name);
+}
+
+void lg_rwlock_local_read_lock(struct lgrwlock *lgrw);
+void lg_rwlock_local_read_unlock(struct lgrwlock *lgrw);
+void lg_rwlock_global_write_lock(struct lgrwlock *lgrw);
+void lg_rwlock_global_write_unlock(struct lgrwlock *lgrw);
#endif
diff --git a/kernel/lglock.c b/kernel/lglock.c
index 6535a66..6c60cf7 100644
--- a/kernel/lglock.c
+++ b/kernel/lglock.c
@@ -87,3 +87,55 @@ void lg_global_unlock(struct lglock *lg)
preempt_enable();
}
EXPORT_SYMBOL(lg_global_unlock);
+
+#define FALLBACK_BASE (1UL << 30)
+
+void lg_rwlock_local_read_lock(struct lgrwlock *lgrw)
+{
+ struct lglock *lg = &lgrw->lglock;
+
+ preempt_disable();
+ rwlock_acquire_read(&lg->lock_dep_map, 0, 0, _RET_IP_);
+ if (likely(!__this_cpu_read(*lgrw->reader_refcnt))) {
+ if (!arch_spin_trylock(this_cpu_ptr(lg->lock))) {
+ read_lock(&lgrw->fallback_rwlock);
+ __this_cpu_add(*lgrw->reader_refcnt, FALLBACK_BASE);
+ }
+ }
+
+ __this_cpu_inc(*lgrw->reader_refcnt);
+}
+EXPORT_SYMBOL(lg_rwlock_local_read_lock);
+
+void lg_rwlock_local_read_unlock(struct lgrwlock *lgrw)
+{
+ switch (__this_cpu_dec_return(*lgrw->reader_refcnt)) {
+ case 0:
+ lg_local_unlock(&lgrw->lglock);
+ return;
+ case FALLBACK_BASE:
+ __this_cpu_sub(*lgrw->reader_refcnt, FALLBACK_BASE);
+ read_unlock(&lgrw->fallback_rwlock);
+ break;
+ default:
+ break;
+ }
+
+ rwlock_release(&lg->lock_dep_map, 1, _RET_IP_);
+ preempt_enable();
+}
+EXPORT_SYMBOL(lg_rwlock_local_read_unlock);
+
+void lg_rwlock_global_write_lock(struct lgrwlock *lgrw)
+{
+ lg_global_lock(&lgrw->lglock);
+ write_lock(&lgrw->fallback_rwlock);
+}
+EXPORT_SYMBOL(lg_rwlock_global_write_lock);
+
+void lg_rwlock_global_write_unlock(struct lgrwlock *lgrw)
+{
+ write_unlock(&lgrw->fallback_rwlock);
+ lg_global_unlock(&lgrw->lglock);
+}
+EXPORT_SYMBOL(lg_rwlock_global_write_unlock);
--
1.7.7.6
^ permalink raw reply related
* Re: [PATCH] mv643xx_eth: Fix a possible deadlock upon ifdown
From: Alexander Holler @ 2013-03-01 17:30 UTC (permalink / raw)
To: Lennert Buytenhek; +Cc: Lubomir Rintel, netdev, linux-kernel, Lubomir Rintel
In-Reply-To: <20130104202509.GX27530@wantstofly.org>
Am 04.01.2013 21:25, schrieb Lennert Buytenhek:
> On Fri, Jan 04, 2013 at 03:07:02PM +0100, Lubomir Rintel wrote:
>
>> From: Lubomir Rintel <lubo.rintel@gooddata.com>
>>
>> =================================
>> [ INFO: inconsistent lock state ]
>> 3.7.0-6.luboskovo.fc19.armv5tel.kirkwood #1 Tainted: G W
>> ---------------------------------
>> inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
>> NetworkManager/337 [HC0[0]:SC0[0]:HE1:SE1] takes:
>> (_xmit_ETHER#2){+.?...}, at: [<bf07adfc>] txq_reclaim+0x54/0x264 [mv643xx_eth]
I get the same annoying warning when the MTU gets changed (through dhcp).
>
> Maybe I'm not reading it right, but I doubt that this is an actual
> deadlock or that the patch is needed.
>
> txq_reclaim() indeed doesn't disable BHs, but that's because it's
> always called in BH context. Almost always -- the only exception is
> txq_deinit(), called from ->ndo_stop(), but by that time we've
> already napi_disable()'d and netif_carrier_off()'d and free_irq()'d.
Agreed. I've just read me through that too and don't think a deadlock is
possible.
>
> How to explain that to lockdep, though, I don't know.
The patch helps with that. ;)
Regards,
Alexander
^ permalink raw reply
* RE: e1000e failed to check map error
From: Allan, Bruce W @ 2013-03-01 17:13 UTC (permalink / raw)
To: Dave Jones, netdev@vger.kernel.org
In-Reply-To: <20130301053007.GA14474@redhat.com>
> -----Original Message-----
> From: netdev-owner@vger.kernel.org [mailto:netdev-
> owner@vger.kernel.org] On Behalf Of Dave Jones
> Sent: Thursday, February 28, 2013 9:30 PM
> To: netdev@vger.kernel.org
> Subject: e1000e failed to check map error
>
> Linus' current tree shows this shortly after boot for me..
>
> WARNING: at lib/dma-debug.c:933 check_unmap+0x407/0x8a0()
Thanks for the report Dave. I'll look into it.
Bruce.
^ 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