Search Linux Wireless

Re: [RFC v6] rfkill: rewrite

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On Thu, 2009-04-30 at 00:19 -0300, Henrique de Moraes Holschuh wrote:
> I am halfway on the thinkpad-acpi conversion. It is going slow because
> I have to cleanup the entire thing to have the code look even remotely
> sane now that HW and SW states are to be tracked separately by the
> backend driver, and I lost the RFKILL_STATE_* stuff.

Hmm. I didn't think it was that much of a problem for the other drivers
at least.

> Anyway, in the process (using v7 of the patch, taken from the URL you
> posted sometime ago), I noticed this:
> 
> The return values for rfkill_alloc() are not the same on the stub and
> real functions.  The stub function uses ERR_PTR, while the real
> function uses NULL for any errors.   Please make them do the same
> thing, and it is probably a damn good idea to document in the
> kerneldoc what kind of return values one should expect when you return
> a pointer and the function can fail (i.e. NULL or ERR_PTR).

Oops, yes, will fix that. I think I intended to use ERR_PTR but then
thought it was too much of an API change. Don't really remember though.

> Also, I have a question: are hooks ever called in atomic/interrupt
> context?  Just about every ACPI and I2C driver needs to sleep to do
> their magic, so I sure hope the answer is "no", otherwise life
> suddenly got a whole lot more complicated for thinkpad-acpi..

The answer is "no" unless there's a bug, this didn't really change,
they're called only from the input handler.

> Also, due to races, it is _impossible_ to assure the backend driver
> that the set_block hook will never be called when the radio is
> hard-blocked.  Best to change the description of that hook to make it
> clear that it could happen, but that the rfkill core will try to
> optimize away such changes.  Here's the race:
> 
>            A                                  B
> rfkill_set_block
>     saves state in "prev"
>     ...                            rfkill_set_hw_state(true)
>     call set_block hook
>       but radio IS hard-blocked
>       and the core WAS informed
>       of this

Good point. I wonder what's more important -- it would be almost trivial
to change this by using a spinlock instead of atomic bit operations.

> Also, it looks like the SW state rollback done by rfkill_set_block can
> sw-unblock a radio when it shouldn't on races very similar as the one
> above, but involving sw-blocking.
> 
> I don't see a way to do safe state rollback in a lockless rfkill core
> if set_sw_state can happen at any time.  Please enlighten me if I am
> wrong (and I hope I am) :-(
> 
> If I am not wrong, one could change rfkill_set_sw_state and
> rfkill_set_states to return an error if rfkill_set_block is on the way
> (that can be done lockless).  For rfkill_set_states, document that the
> hw state WILL be updated regardless, but that the sw state might not
> be.
> 
> Or one could kick the problem to the backend driver (which will have
> any required locking anyway), by giving the set_block hook the duty of
> calling set_sw_state when it succeeds.  The return status might be
> kept should we ever start passing it down to other layers like
> userspace, or you can remove it.

Thanks for your analysis. It does seem like a problem, and even locking
in rfkill can't really avoid the problem [1]. However, why would we
require the driver to postpone that? Your idea is sound, but I think we
can do it in the core. It might require a spinlock there, but that's
acceptable, I didn't use atomic operations to make it faster but to make
it simpler.

 * rfkill_set_block can set a flag "I'm in an update"
 * a concurrent rfkill_set_sw_state will check that flag, and update the
   "prev" variable instead of the real variable
 * on errors, rfkill_set_block will then revert to whatever the last
   set_sw_state said

That way, if the driver returns an error from ops->set_block, we will
really revert to what the driver last told us with set_sw_state. It
would seem to get this prev/in-update handling correct we need to add a
spinlock, but concurrent rfkill_set_block()s are already prevented by
the mutex so no additional locking would be needed there.

Does that sound correct/acceptable?

johannes

[1] unless we want to use a mutex or require ops->set_block to be atomic
but then we can't really do either

Attachment: signature.asc
Description: This is a digitally signed message part


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux