[rt2x00-users] [PATCH 05/12] rt2x00: Introduce tasklets for interrupt handling
Gertjan van Wingerde
gwingerde at gmail.com
Sat Jan 15 11:40:22 EST 2011
On 01/14/11 23:53, Helmut Schaa wrote:
> Hi Gertjan,
>
> Am Freitag, 14. Januar 2011 schrieb Gertjan van Wingerde:
>> On 01/14/11 10:41, Helmut Schaa wrote:
>>> No functional changes, just preparation for moving interrupt handling to
>>> tasklets. The tasklets are disabled by default. Drivers making use of
>>> them need to enable the tasklets when the device state is set to IRQ_ON.
>>>
>>> Signed-off-by: Helmut Schaa <helmut.schaa at googlemail.com>
>>> ---
>>> drivers/net/wireless/rt2x00/rt2x00.h | 13 +++++++++++++
>>> drivers/net/wireless/rt2x00/rt2x00dev.c | 21 +++++++++++++++++++++
>>> 2 files changed, 34 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
>>> index 01a4788..2375722 100644
>>> --- a/drivers/net/wireless/rt2x00/rt2x00.h
>>> +++ b/drivers/net/wireless/rt2x00/rt2x00.h
>>> @@ -520,6 +520,10 @@ struct rt2x00lib_ops {
>>> * TX status tasklet handler.
>>> */
>>> void (*txstatus_tasklet) (unsigned long data);
>>> + void (*pretbtt_tasklet) (unsigned long data);
>>> + void (*tbtt_tasklet) (unsigned long data);
>>> + void (*rxdone_tasklet) (unsigned long data);
>>> + void (*autowake_tasklet) (unsigned long data);
>>>
>>> /*
>>> * Device init handlers.
>>> @@ -906,6 +910,15 @@ struct rt2x00_dev {
>>> * Tasklet for processing tx status reports (rt2800pci).
>>> */
>>> struct tasklet_struct txstatus_tasklet;
>>> + struct tasklet_struct pretbtt_tasklet;
>>> + struct tasklet_struct tbtt_tasklet;
>>> + struct tasklet_struct rxdone_tasklet;
>>> + struct tasklet_struct autowake_tasklet;
>>> +
>>> + /*
>>> + * Protect the interrupt mask register.
>>> + */
>>> + spinlock_t irqmask_lock;
>>> };
>>>
>>> /*
>>
>> Is there any resource overhead involved with tasklets (e.g. additional kernel threads, memory, etc)?
>> It seems that we could do with less tasklets, as for instance pretbtt and tbtt can share a tasklet, as
>> they never will happen at the same time. The same would be true for autowake and rxdone, and possibly
>> txstatus.
>>
>> So, if there is no additional resource overhead with having all these tasklets, then I'm fine, otherwise
>> I think we should cut down a little bit on the number of tasklets that we use.
>
> Hmm, good point. Since tasklets are executed as softirq there are no new kernel
> threads involved. Of course we need some more memory for the tasklet_structs.
> From a runtime POV I don't think it makes much difference in memory consumption.
>
> The problem with using one tasklet for tbtt and pretbtt is that we would have
> to somehow store which interrupt to process. Having one tasklet per interrupt
> doesn't have to store anything between the irq_handler and the tasklets.
>
> But you're right that tbtt and pretbtt should never run at the same time, it
> just cannot happen. So basically both could be processed by the same tasklet.
OK. I see your point on the difficulties in communicating to the tasklet which interrupt has fired.
Since there isn't any real resource impact for tasklets, I guess it is fine to have all these tasklets.
So,
Acked-by: Gertjan van Wingerde <gwingerde at gmail.com>
>
>>> diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
>>> index 04bf9af..9856652 100644
>>> --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
>>> +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
>>> @@ -828,6 +828,26 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
>>> }
>>>
>>> /*
>>> + * Initialize tasklets if used by the driver. Tasklets are
>>> + * disabled until the interrupts are turned on. The driver
>>> + * has to handle that.
>>> + */
>>> +#define RT2X00_TASKLET_INIT(taskletname) \
>>> + if (rt2x00dev->ops->lib->taskletname) { \
>>> + tasklet_init(&rt2x00dev->taskletname, \
>>> + rt2x00dev->ops->lib->taskletname, \
>>> + (unsigned long)rt2x00dev); \
>>> + tasklet_disable(&rt2x00dev->taskletname); \
>>> + }
>>> +
>>> + RT2X00_TASKLET_INIT(pretbtt_tasklet);
>>> + RT2X00_TASKLET_INIT(tbtt_tasklet);
>>> + RT2X00_TASKLET_INIT(rxdone_tasklet);
>>> + RT2X00_TASKLET_INIT(autowake_tasklet);
>>> +
>>> +#undef RT2X00_TASKLET_INIT
>>> +
>>> + /*
>>> * Register HW.
>>> */
>>> status = ieee80211_register_hw(rt2x00dev->hw);
>>
>> Ouch, that's one ugly macro, with the assumed naming for taskletname and the struct members.
>> However, I don't see how this can be done in an easier manner with less uglyness, so I guess
>> it is fine for now.
>
> Hehe, I had it open coded before, the macro was Ivos suggestion ;)
>
> Thanks for the quick review,
> Helmut
>
More information about the users
mailing list