On Saturday 02 August 2008, Henrique de Moraes Holschuh wrote: > Guard rfkill controllers attached to a rfkill class against state changes > after class suspend has been issued. > > Signed-off-by: Henrique de Moraes Holschuh <hmh@xxxxxxxxxx> > Cc: Ivo van Doorn <IvDoorn@xxxxxxxxx> Acked-by: Ivo van Doorn <IvDoorn@xxxxxxxxx> > --- > Documentation/rfkill.txt | 5 +++++ > net/rfkill/rfkill.c | 14 ++++++++++---- > 2 files changed, 15 insertions(+), 4 deletions(-) > > diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt > index 28b6ec8..6fcb306 100644 > --- a/Documentation/rfkill.txt > +++ b/Documentation/rfkill.txt > @@ -363,6 +363,11 @@ This rule exists because users of the rfkill subsystem expect to get (and set, > when possible) the overall transmitter rfkill state, not of a particular rfkill > line. > > +5. During suspend, the rfkill class will attempt to soft-block the radio > +through a call to rfkill->toggle_radio, and will try to restore its previous > +state during resume. After a rfkill class is suspended, it will *not* call > +rfkill->toggle_radio until it is resumed. > + > Example of a WLAN wireless driver connected to the rfkill subsystem: > -------------------------------------------------------------------- > > diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c > index d2d4565..35a9994 100644 > --- a/net/rfkill/rfkill.c > +++ b/net/rfkill/rfkill.c > @@ -150,6 +150,8 @@ static void update_rfkill_state(struct rfkill *rfkill) > * calls and handling all the red tape such as issuing notifications > * if the call is successful. > * > + * Suspended devices are not touched at all, and -EAGAIN is returned. > + * > * Note that the @force parameter cannot override a (possibly cached) > * state of RFKILL_STATE_HARD_BLOCKED. Any device making use of > * RFKILL_STATE_HARD_BLOCKED implements either get_state() or > @@ -168,6 +170,9 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, > int retval = 0; > enum rfkill_state oldstate, newstate; > > + if (unlikely(rfkill->dev.power.power_state.event & PM_EVENT_SLEEP)) > + return -EBUSY; > + > oldstate = rfkill->state; > > if (rfkill->get_state && !force && > @@ -214,7 +219,7 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, > * > * This function toggles the state of all switches of given type, > * unless a specific switch is claimed by userspace (in which case, > - * that switch is left alone). > + * that switch is left alone) or suspended. > */ > void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) > { > @@ -239,8 +244,8 @@ EXPORT_SYMBOL(rfkill_switch_all); > /** > * rfkill_epo - emergency power off all transmitters > * > - * This kicks all rfkill devices to RFKILL_STATE_SOFT_BLOCKED, ignoring > - * everything in its path but rfkill_mutex and rfkill->mutex. > + * This kicks all non-suspended rfkill devices to RFKILL_STATE_SOFT_BLOCKED, > + * ignoring everything in its path but rfkill_mutex and rfkill->mutex. > */ > void rfkill_epo(void) > { > @@ -458,13 +463,14 @@ static int rfkill_resume(struct device *dev) > if (dev->power.power_state.event != PM_EVENT_ON) { > mutex_lock(&rfkill->mutex); > > + dev->power.power_state.event = PM_EVENT_ON; > + > /* restore radio state AND notify everybody */ > rfkill_toggle_radio(rfkill, rfkill->state, 1); > > mutex_unlock(&rfkill->mutex); > } > > - dev->power.power_state = PMSG_ON; > return 0; > } > #else -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html