[PATCH] Keep a shadow copy of HFA384X_INTEN_OFF
Denis Vlasenko
vda
Thu May 22 22:43:47 PDT 2003
On 22 May 2003 09:04, Pavel Roskin wrote:
> On Tue, 20 May 2003, Denis Vlasenko wrote:
> > Hmm... this is a small bit of a bigger problem. If we are to guard
> > against interrupt / schedule / other CPU hitting us between these
> > two lines of code:
> >
> > HFA384X_OUTW(HFA384X_EVENT_MASK, HFA384X_INTEN_OFF);
> > ((local_info_t*)dev->priv)->shadow_hfa384x_inten =
> > HFA384X_EVENT_MASK;
>
> First of all, please make it an inline function or another macro -
> that's the best way to keep data in-sync.
Agreed.
> > we are almost inevitably want to protect some surrounding code too,
> > because setting IntEn is usually only one stage of some larger
> > hw manipulation.
>
> A lot of races can be avoided by enabling interrupts after such
> manipulation and disabling them before doing anything drastic (e.g.
> reset), provided that the hardware behaves properly and obeys those
> registers.
This is not enough considering SMP/preempt. IMHO current code
does not take this into consideration.
> > In short: if we are worried about this race, we already have
> > locking problem (lack of locking) to fix.
>
> I'm not sure that your understanding of Jouni's words is correct. I
> don't know what race he is worried about. Please give a realistic
> scenario.
He is worried about this:
HFA384X_OUTW(v, HFA384X_INTEN_OFF);
interrupt --------------------> handlers reads
shadow_hfa384x_inten
and sees wrong value
shadow_hfa384x_inten = v;
This indeed can happen. But the same bad thing can happen in
tons of places.
> > I won't pretend that I have experience in writing good
> > SMP/IRQ/preempt safe code, but I think I see rather incomplete
> > locking in hostap.
>
> It may be, but hostap has 4 locks, which is quite impressive.
Actually, number of locks is not indicative of lock correctness.
I'm afraid
> > hostap_ioctl -> prism2_ioctl_siwrate -> hostap_set_rate,
> > no locks/semaphores held, we arrive here:
>
> The orinoco driver holds a lock when processing ioctl. You may want
> to check that code. David Gibson is religious about locking.
Hmm? I'm not talking about orinoco code...
> > ret = (hostap_set_word(dev, HFA384X_RID_TXRATECONTROL,
> > local->tx_rate_control) ||
> > hostap_set_word(dev, HFA384X_RID_CNFSUPPORTEDRATES,
> > local->tx_rate_control) ||
> > local->func->reset_port(dev)); <--- (see below)
> >
> > What protects us between two set_port() calls or second set_port()
> > and reset_port()?
>
> The question is what is can happen and how can it affect correctness
> of the operation. I cannot think of anything bad in this case. RID
> settings become affective on reset, i.e. atomically.
But IRQs and, worse, other CPUs can bite us:
CPU1: doing ioctl CPU2: doing ioctl
----------------- -------------------------
hostap_set_word(...)
IRQ----> hostap_set_word(...)
processing IRQ... hostap_set_word(...)
<-------
hostap_set_word(...)
reset_port(...)
reset_port(...)
There is locking inside set_word(), but we need locking around whole
{set_word(),set_word(),reset_port()} thing.
And this is not a particularly bad piece of code, there are worse places.
So what about starting with one per-device semaphore to cover
interruptible/sleepable code and one spinlock for critical sections,
and then refining it if we'll see performance regression?
I can code it up but I'm afraid I can only compile-test it.
--
vda
More information about the Hostap
mailing list