aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c59
1 files changed, 55 insertions, 4 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index b2c5913ff72e..27d709bac98f 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -222,6 +222,7 @@ struct ibm_struct {
222 void (*exit) (void); 222 void (*exit) (void);
223 void (*resume) (void); 223 void (*resume) (void);
224 void (*suspend) (pm_message_t state); 224 void (*suspend) (pm_message_t state);
225 void (*shutdown) (void);
225 226
226 struct list_head all_drivers; 227 struct list_head all_drivers;
227 228
@@ -759,6 +760,18 @@ static int tpacpi_resume_handler(struct platform_device *pdev)
759 return 0; 760 return 0;
760} 761}
761 762
763static void tpacpi_shutdown_handler(struct platform_device *pdev)
764{
765 struct ibm_struct *ibm, *itmp;
766
767 list_for_each_entry_safe(ibm, itmp,
768 &tpacpi_all_drivers,
769 all_drivers) {
770 if (ibm->shutdown)
771 (ibm->shutdown)();
772 }
773}
774
762static struct platform_driver tpacpi_pdriver = { 775static struct platform_driver tpacpi_pdriver = {
763 .driver = { 776 .driver = {
764 .name = TPACPI_DRVR_NAME, 777 .name = TPACPI_DRVR_NAME,
@@ -766,6 +779,7 @@ static struct platform_driver tpacpi_pdriver = {
766 }, 779 },
767 .suspend = tpacpi_suspend_handler, 780 .suspend = tpacpi_suspend_handler,
768 .resume = tpacpi_resume_handler, 781 .resume = tpacpi_resume_handler,
782 .shutdown = tpacpi_shutdown_handler,
769}; 783};
770 784
771static struct platform_driver tpacpi_hwmon_pdriver = { 785static struct platform_driver tpacpi_hwmon_pdriver = {
@@ -957,7 +971,22 @@ static int __init tpacpi_new_rfkill(const unsigned int id,
957 int (*get_state)(void *, enum rfkill_state *)) 971 int (*get_state)(void *, enum rfkill_state *))
958{ 972{
959 int res; 973 int res;
960 enum rfkill_state initial_state; 974 enum rfkill_state initial_state = RFKILL_STATE_SOFT_BLOCKED;
975
976 res = get_state(NULL, &initial_state);
977 if (res < 0) {
978 printk(TPACPI_ERR
979 "failed to read initial state for %s, error %d; "
980 "will turn radio off\n", name, res);
981 } else {
982 /* try to set the initial state as the default for the rfkill
983 * type, since we ask the firmware to preserve it across S5 in
984 * NVRAM */
985 rfkill_set_default(rfktype,
986 (initial_state == RFKILL_STATE_UNBLOCKED) ?
987 RFKILL_STATE_UNBLOCKED :
988 RFKILL_STATE_SOFT_BLOCKED);
989 }
961 990
962 *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype); 991 *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype);
963 if (!*rfk) { 992 if (!*rfk) {
@@ -969,9 +998,7 @@ static int __init tpacpi_new_rfkill(const unsigned int id,
969 (*rfk)->name = name; 998 (*rfk)->name = name;
970 (*rfk)->get_state = get_state; 999 (*rfk)->get_state = get_state;
971 (*rfk)->toggle_radio = toggle_radio; 1000 (*rfk)->toggle_radio = toggle_radio;
972 1001 (*rfk)->state = initial_state;
973 if (!get_state(NULL, &initial_state))
974 (*rfk)->state = initial_state;
975 1002
976 res = rfkill_register(*rfk); 1003 res = rfkill_register(*rfk);
977 if (res < 0) { 1004 if (res < 0) {
@@ -2943,8 +2970,19 @@ static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state)
2943 return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); 2970 return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
2944} 2971}
2945 2972
2973static void bluetooth_shutdown(void)
2974{
2975 /* Order firmware to save current state to NVRAM */
2976 if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd",
2977 TP_ACPI_BLTH_SAVE_STATE))
2978 printk(TPACPI_NOTICE
2979 "failed to save bluetooth state to NVRAM\n");
2980}
2981
2946static void bluetooth_exit(void) 2982static void bluetooth_exit(void)
2947{ 2983{
2984 bluetooth_shutdown();
2985
2948 if (tpacpi_bluetooth_rfkill) 2986 if (tpacpi_bluetooth_rfkill)
2949 rfkill_unregister(tpacpi_bluetooth_rfkill); 2987 rfkill_unregister(tpacpi_bluetooth_rfkill);
2950 2988
@@ -3050,6 +3088,7 @@ static struct ibm_struct bluetooth_driver_data = {
3050 .write = bluetooth_write, 3088 .write = bluetooth_write,
3051 .exit = bluetooth_exit, 3089 .exit = bluetooth_exit,
3052 .suspend = bluetooth_suspend, 3090 .suspend = bluetooth_suspend,
3091 .shutdown = bluetooth_shutdown,
3053}; 3092};
3054 3093
3055/************************************************************************* 3094/*************************************************************************
@@ -3207,8 +3246,19 @@ static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state)
3207 return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); 3246 return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
3208} 3247}
3209 3248
3249static void wan_shutdown(void)
3250{
3251 /* Order firmware to save current state to NVRAM */
3252 if (!acpi_evalf(NULL, NULL, "\\WGSV", "vd",
3253 TP_ACPI_WGSV_SAVE_STATE))
3254 printk(TPACPI_NOTICE
3255 "failed to save WWAN state to NVRAM\n");
3256}
3257
3210static void wan_exit(void) 3258static void wan_exit(void)
3211{ 3259{
3260 wan_shutdown();
3261
3212 if (tpacpi_wan_rfkill) 3262 if (tpacpi_wan_rfkill)
3213 rfkill_unregister(tpacpi_wan_rfkill); 3263 rfkill_unregister(tpacpi_wan_rfkill);
3214 3264
@@ -3312,6 +3362,7 @@ static struct ibm_struct wan_driver_data = {
3312 .write = wan_write, 3362 .write = wan_write,
3313 .exit = wan_exit, 3363 .exit = wan_exit,
3314 .suspend = wan_suspend, 3364 .suspend = wan_suspend,
3365 .shutdown = wan_shutdown,
3315}; 3366};
3316 3367
3317/************************************************************************* 3368/*************************************************************************