Interesting. So an ACPI method is writing the radio state to NVRAM and you pick it back up on boot (or resume). Very nice -- to bad we don't have this method for all laptops. Len Brown, Intel Open Source Technology Center On Sun, 11 Jan 2009, Henrique de Moraes Holschuh wrote: > Store in firmware NVRAM the radio state on machine shutdown for WWAN and > bluetooth. Also, try to set the initial boot state of these radios as the > rfkill default state for their respective classes. > > Signed-off-by: Henrique de Moraes Holschuh <hmh@xxxxxxxxxx> > Cc: Ivo van Doorn <IvDoorn@xxxxxxxxx> > --- > drivers/platform/x86/thinkpad_acpi.c | 59 +++++++++++++++++++++++++++++++-- > 1 files changed, 55 insertions(+), 4 deletions(-) > > diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c > index b2c5913..27d709b 100644 > --- a/drivers/platform/x86/thinkpad_acpi.c > +++ b/drivers/platform/x86/thinkpad_acpi.c > @@ -222,6 +222,7 @@ struct ibm_struct { > void (*exit) (void); > void (*resume) (void); > void (*suspend) (pm_message_t state); > + void (*shutdown) (void); > > struct list_head all_drivers; > > @@ -759,6 +760,18 @@ static int tpacpi_resume_handler(struct platform_device *pdev) > return 0; > } > > +static void tpacpi_shutdown_handler(struct platform_device *pdev) > +{ > + struct ibm_struct *ibm, *itmp; > + > + list_for_each_entry_safe(ibm, itmp, > + &tpacpi_all_drivers, > + all_drivers) { > + if (ibm->shutdown) > + (ibm->shutdown)(); > + } > +} > + > static struct platform_driver tpacpi_pdriver = { > .driver = { > .name = TPACPI_DRVR_NAME, > @@ -766,6 +779,7 @@ static struct platform_driver tpacpi_pdriver = { > }, > .suspend = tpacpi_suspend_handler, > .resume = tpacpi_resume_handler, > + .shutdown = tpacpi_shutdown_handler, > }; > > static struct platform_driver tpacpi_hwmon_pdriver = { > @@ -957,7 +971,22 @@ static int __init tpacpi_new_rfkill(const unsigned int id, > int (*get_state)(void *, enum rfkill_state *)) > { > int res; > - enum rfkill_state initial_state; > + enum rfkill_state initial_state = RFKILL_STATE_SOFT_BLOCKED; > + > + res = get_state(NULL, &initial_state); > + if (res < 0) { > + printk(TPACPI_ERR > + "failed to read initial state for %s, error %d; " > + "will turn radio off\n", name, res); > + } else { > + /* try to set the initial state as the default for the rfkill > + * type, since we ask the firmware to preserve it across S5 in > + * NVRAM */ > + rfkill_set_default(rfktype, > + (initial_state == RFKILL_STATE_UNBLOCKED) ? > + RFKILL_STATE_UNBLOCKED : > + RFKILL_STATE_SOFT_BLOCKED); > + } > > *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype); > if (!*rfk) { > @@ -969,9 +998,7 @@ static int __init tpacpi_new_rfkill(const unsigned int id, > (*rfk)->name = name; > (*rfk)->get_state = get_state; > (*rfk)->toggle_radio = toggle_radio; > - > - if (!get_state(NULL, &initial_state)) > - (*rfk)->state = initial_state; > + (*rfk)->state = initial_state; > > res = rfkill_register(*rfk); > if (res < 0) { > @@ -2943,8 +2970,19 @@ static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state) > return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); > } > > +static void bluetooth_shutdown(void) > +{ > + /* Order firmware to save current state to NVRAM */ > + if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd", > + TP_ACPI_BLTH_SAVE_STATE)) > + printk(TPACPI_NOTICE > + "failed to save bluetooth state to NVRAM\n"); > +} > + > static void bluetooth_exit(void) > { > + bluetooth_shutdown(); > + > if (tpacpi_bluetooth_rfkill) > rfkill_unregister(tpacpi_bluetooth_rfkill); > > @@ -3050,6 +3088,7 @@ static struct ibm_struct bluetooth_driver_data = { > .write = bluetooth_write, > .exit = bluetooth_exit, > .suspend = bluetooth_suspend, > + .shutdown = bluetooth_shutdown, > }; > > /************************************************************************* > @@ -3207,8 +3246,19 @@ static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state) > return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); > } > > +static void wan_shutdown(void) > +{ > + /* Order firmware to save current state to NVRAM */ > + if (!acpi_evalf(NULL, NULL, "\\WGSV", "vd", > + TP_ACPI_WGSV_SAVE_STATE)) > + printk(TPACPI_NOTICE > + "failed to save WWAN state to NVRAM\n"); > +} > + > static void wan_exit(void) > { > + wan_shutdown(); > + > if (tpacpi_wan_rfkill) > rfkill_unregister(tpacpi_wan_rfkill); > > @@ -3312,6 +3362,7 @@ static struct ibm_struct wan_driver_data = { > .write = wan_write, > .exit = wan_exit, > .suspend = wan_suspend, > + .shutdown = wan_shutdown, > }; > > /************************************************************************* > -- > 1.5.6.5 > -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html