Add patches accepted for 2.6.27-rc1
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Fri, 25 Jul 2008 23:06:09 +0000 (25 20:06 -0300)
committerHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Fri, 25 Jul 2008 23:06:09 +0000 (25 20:06 -0300)
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
releases/upstream/2.6.27-rc1/0001-ACPI-thinkpad-acpi-minor-refactor-on-radio-switch.patch [new file with mode: 0644]
releases/upstream/2.6.27-rc1/0002-ACPI-thinkpad-acpi-consolidate-wlsw-notification-f.patch [new file with mode: 0644]
releases/upstream/2.6.27-rc1/0003-ACPI-thinkpad-acpi-prepare-for-bluetooth-and-wwan.patch [new file with mode: 0644]
releases/upstream/2.6.27-rc1/0004-ACPI-thinkpad-acpi-WLSW-overrides-other-rfkill-swi.patch [new file with mode: 0644]
releases/upstream/2.6.27-rc1/0005-ACPI-thinkpad-acpi-add-bluetooth-and-WWAN-rfkill-s.patch [new file with mode: 0644]
releases/upstream/2.6.27-rc1/0006-ACPI-thinkpad-acpi-bump-up-version-to-0.21.patch [new file with mode: 0644]
releases/upstream/2.6.27-rc1/0007-ACPI-thinkpad-acpi-don-t-misdetect-in-get_thinkpad.patch [new file with mode: 0644]

diff --git a/releases/upstream/2.6.27-rc1/0001-ACPI-thinkpad-acpi-minor-refactor-on-radio-switch.patch b/releases/upstream/2.6.27-rc1/0001-ACPI-thinkpad-acpi-minor-refactor-on-radio-switch.patch
new file mode 100644 (file)
index 0000000..a5f2277
--- /dev/null
@@ -0,0 +1,94 @@
+From 3a87208028ef59215a88a143c723ac0b83c11df0 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Mon, 21 Jul 2008 09:15:49 -0300
+Subject: ACPI: thinkpad-acpi: minor refactor on radio switch init
+
+Change the code of hotkey_init, wan_init and bluetooth_init a bit to make it
+much easier to add some Kconfig-selected debugging code later.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+---
+ drivers/misc/thinkpad_acpi.c |   49 ++++++++++++++++++++++-------------------
+ 1 files changed, 26 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
+index b596929..c800855 100644
+--- a/drivers/misc/thinkpad_acpi.c
++++ b/drivers/misc/thinkpad_acpi.c
+@@ -2167,9 +2167,10 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
+               printk(TPACPI_INFO
+                       "radio switch found; radios are %s\n",
+                       enabled(status, 0));
++      }
++      if (tp_features.hotkey_wlsw)
+               res = add_to_attr_set(hotkey_dev_attributes,
+                               &dev_attr_hotkey_radio_sw.attr);
+-      }
+       /* For X41t, X60t, X61t Tablets... */
+       if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
+@@ -2646,18 +2647,19 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
+               str_supported(tp_features.bluetooth),
+               status);
++      if (tp_features.bluetooth &&
++          !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) {
++              /* no bluetooth hardware present in system */
++              tp_features.bluetooth = 0;
++              dbg_printk(TPACPI_DBG_INIT,
++                         "bluetooth hardware not installed\n");
++      }
++
+       if (tp_features.bluetooth) {
+-              if (!(status & TP_ACPI_BLUETOOTH_HWPRESENT)) {
+-                      /* no bluetooth hardware present in system */
+-                      tp_features.bluetooth = 0;
+-                      dbg_printk(TPACPI_DBG_INIT,
+-                                 "bluetooth hardware not installed\n");
+-              } else {
+-                      res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
+-                                      &bluetooth_attr_group);
+-                      if (res)
+-                              return res;
+-              }
++              res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
++                              &bluetooth_attr_group);
++              if (res)
++                      return res;
+       }
+       return (tp_features.bluetooth)? 0 : 1;
+@@ -2818,18 +2820,19 @@ static int __init wan_init(struct ibm_init_struct *iibm)
+               str_supported(tp_features.wan),
+               status);
++      if (tp_features.wan &&
++          !(status & TP_ACPI_WANCARD_HWPRESENT)) {
++              /* no wan hardware present in system */
++              tp_features.wan = 0;
++              dbg_printk(TPACPI_DBG_INIT,
++                         "wan hardware not installed\n");
++      }
++
+       if (tp_features.wan) {
+-              if (!(status & TP_ACPI_WANCARD_HWPRESENT)) {
+-                      /* no wan hardware present in system */
+-                      tp_features.wan = 0;
+-                      dbg_printk(TPACPI_DBG_INIT,
+-                                 "wan hardware not installed\n");
+-              } else {
+-                      res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
+-                                      &wan_attr_group);
+-                      if (res)
+-                              return res;
+-              }
++              res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
++                              &wan_attr_group);
++              if (res)
++                      return res;
+       }
+       return (tp_features.wan)? 0 : 1;
+-- 
+1.5.6.2
+
diff --git a/releases/upstream/2.6.27-rc1/0002-ACPI-thinkpad-acpi-consolidate-wlsw-notification-f.patch b/releases/upstream/2.6.27-rc1/0002-ACPI-thinkpad-acpi-consolidate-wlsw-notification-f.patch
new file mode 100644 (file)
index 0000000..0363bbe
--- /dev/null
@@ -0,0 +1,95 @@
+From 733e27c1cc86afae2d9481838693661b3d839950 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Mon, 21 Jul 2008 09:15:49 -0300
+Subject: ACPI: thinkpad-acpi: consolidate wlsw notification function
+
+Rename tpacpi_input_send_radiosw() to tpacpi_send_radiosw_update(), and
+make it a central point to issue "radio switch changed state" notifications
+by consolidating also the poll() notification in the same function.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+---
+ drivers/misc/thinkpad_acpi.c |   39 +++++++++++++++++++--------------------
+ 1 files changed, 19 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
+index c800855..9179f23 100644
+--- a/drivers/misc/thinkpad_acpi.c
++++ b/drivers/misc/thinkpad_acpi.c
+@@ -1285,21 +1285,6 @@ static int hotkey_status_set(int status)
+       return 0;
+ }
+-static void tpacpi_input_send_radiosw(void)
+-{
+-      int wlsw;
+-
+-      if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) {
+-              mutex_lock(&tpacpi_inputdev_send_mutex);
+-
+-              input_report_switch(tpacpi_inputdev,
+-                                  SW_RFKILL_ALL, !!wlsw);
+-              input_sync(tpacpi_inputdev);
+-
+-              mutex_unlock(&tpacpi_inputdev_send_mutex);
+-      }
+-}
+-
+ static void tpacpi_input_send_tabletsw(void)
+ {
+       int state;
+@@ -1921,6 +1906,22 @@ static struct attribute *hotkey_mask_attributes[] __initdata = {
+       &dev_attr_hotkey_wakeup_hotunplug_complete.attr,
+ };
++static void tpacpi_send_radiosw_update(void)
++{
++      int wlsw;
++
++      if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) {
++              mutex_lock(&tpacpi_inputdev_send_mutex);
++
++              input_report_switch(tpacpi_inputdev,
++                                  SW_RFKILL_ALL, !!wlsw);
++              input_sync(tpacpi_inputdev);
++
++              mutex_unlock(&tpacpi_inputdev_send_mutex);
++      }
++      hotkey_radio_sw_notify_change();
++}
++
+ static void hotkey_exit(void)
+ {
+ #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
+@@ -2288,7 +2289,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
+       tpacpi_inputdev->close = &hotkey_inputdev_close;
+       hotkey_poll_setup_safe(1);
+-      tpacpi_input_send_radiosw();
++      tpacpi_send_radiosw_update();
+       tpacpi_input_send_tabletsw();
+       return 0;
+@@ -2420,8 +2421,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
+               case 7:
+                       /* 0x7000-0x7FFF: misc */
+                       if (tp_features.hotkey_wlsw && hkey == 0x7000) {
+-                              tpacpi_input_send_radiosw();
+-                              hotkey_radio_sw_notify_change();
++                              tpacpi_send_radiosw_update();
+                               send_acpi_ev = 0;
+                               break;
+                       }
+@@ -2464,8 +2464,7 @@ static void hotkey_resume(void)
+               printk(TPACPI_ERR
+                      "error while trying to read hot key mask "
+                      "from firmware\n");
+-      tpacpi_input_send_radiosw();
+-      hotkey_radio_sw_notify_change();
++      tpacpi_send_radiosw_update();
+       hotkey_tablet_mode_notify_change();
+       hotkey_wakeup_reason_notify_change();
+       hotkey_wakeup_hotunplug_complete_notify_change();
+-- 
+1.5.6.2
+
diff --git a/releases/upstream/2.6.27-rc1/0003-ACPI-thinkpad-acpi-prepare-for-bluetooth-and-wwan.patch b/releases/upstream/2.6.27-rc1/0003-ACPI-thinkpad-acpi-prepare-for-bluetooth-and-wwan.patch
new file mode 100644 (file)
index 0000000..39fde4e
--- /dev/null
@@ -0,0 +1,216 @@
+From 07431ec82bf9dc74b470a1d820b41c92c4d86e6f Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Mon, 21 Jul 2008 09:15:50 -0300
+Subject: ACPI: thinkpad-acpi: prepare for bluetooth and wwan rfkill support
+
+Get rid of some forward definitions by moving code around, this will make
+the rfkill conversion of wwan and bluetooth a bit cleaner.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+---
+ drivers/misc/thinkpad_acpi.c |  154 ++++++++++++++++++++----------------------
+ 1 files changed, 74 insertions(+), 80 deletions(-)
+
+diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
+index 9179f23..743a4d6 100644
+--- a/drivers/misc/thinkpad_acpi.c
++++ b/drivers/misc/thinkpad_acpi.c
+@@ -2581,8 +2581,37 @@ enum {
+       TP_ACPI_BLUETOOTH_UNK           = 0x04, /* unknown function */
+ };
+-static int bluetooth_get_radiosw(void);
+-static int bluetooth_set_radiosw(int radio_on);
++static int bluetooth_get_radiosw(void)
++{
++      int status;
++
++      if (!tp_features.bluetooth)
++              return -ENODEV;
++
++      if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
++              return -EIO;
++
++      return (status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0;
++}
++
++static int bluetooth_set_radiosw(int radio_on)
++{
++      int status;
++
++      if (!tp_features.bluetooth)
++              return -ENODEV;
++
++      if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
++              return -EIO;
++      if (radio_on)
++              status |= TP_ACPI_BLUETOOTH_RADIOSSW;
++      else
++              status &= ~TP_ACPI_BLUETOOTH_RADIOSSW;
++      if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
++              return -EIO;
++
++      return 0;
++}
+ /* sysfs bluetooth enable ---------------------------------------------- */
+ static ssize_t bluetooth_enable_show(struct device *dev,
+@@ -2628,6 +2657,12 @@ static const struct attribute_group bluetooth_attr_group = {
+       .attrs = bluetooth_attributes,
+ };
++static void bluetooth_exit(void)
++{
++      sysfs_remove_group(&tpacpi_pdev->dev.kobj,
++                      &bluetooth_attr_group);
++}
++
+ static int __init bluetooth_init(struct ibm_init_struct *iibm)
+ {
+       int res;
+@@ -2664,44 +2699,6 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
+       return (tp_features.bluetooth)? 0 : 1;
+ }
+-static void bluetooth_exit(void)
+-{
+-      sysfs_remove_group(&tpacpi_pdev->dev.kobj,
+-                      &bluetooth_attr_group);
+-}
+-
+-static int bluetooth_get_radiosw(void)
+-{
+-      int status;
+-
+-      if (!tp_features.bluetooth)
+-              return -ENODEV;
+-
+-      if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
+-              return -EIO;
+-
+-      return ((status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0);
+-}
+-
+-static int bluetooth_set_radiosw(int radio_on)
+-{
+-      int status;
+-
+-      if (!tp_features.bluetooth)
+-              return -ENODEV;
+-
+-      if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
+-              return -EIO;
+-      if (radio_on)
+-              status |= TP_ACPI_BLUETOOTH_RADIOSSW;
+-      else
+-              status &= ~TP_ACPI_BLUETOOTH_RADIOSSW;
+-      if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
+-              return -EIO;
+-
+-      return 0;
+-}
+-
+ /* procfs -------------------------------------------------------------- */
+ static int bluetooth_read(char *p)
+ {
+@@ -2756,8 +2753,37 @@ enum {
+       TP_ACPI_WANCARD_UNK             = 0x04, /* unknown function */
+ };
+-static int wan_get_radiosw(void);
+-static int wan_set_radiosw(int radio_on);
++static int wan_get_radiosw(void)
++{
++      int status;
++
++      if (!tp_features.wan)
++              return -ENODEV;
++
++      if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
++              return -EIO;
++
++      return (status & TP_ACPI_WANCARD_RADIOSSW) != 0;
++}
++
++static int wan_set_radiosw(int radio_on)
++{
++      int status;
++
++      if (!tp_features.wan)
++              return -ENODEV;
++
++      if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
++              return -EIO;
++      if (radio_on)
++              status |= TP_ACPI_WANCARD_RADIOSSW;
++      else
++              status &= ~TP_ACPI_WANCARD_RADIOSSW;
++      if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
++              return -EIO;
++
++      return 0;
++}
+ /* sysfs wan enable ---------------------------------------------------- */
+ static ssize_t wan_enable_show(struct device *dev,
+@@ -2803,6 +2829,12 @@ static const struct attribute_group wan_attr_group = {
+       .attrs = wan_attributes,
+ };
++static void wan_exit(void)
++{
++      sysfs_remove_group(&tpacpi_pdev->dev.kobj,
++              &wan_attr_group);
++}
++
+ static int __init wan_init(struct ibm_init_struct *iibm)
+ {
+       int res;
+@@ -2837,44 +2869,6 @@ static int __init wan_init(struct ibm_init_struct *iibm)
+       return (tp_features.wan)? 0 : 1;
+ }
+-static void wan_exit(void)
+-{
+-      sysfs_remove_group(&tpacpi_pdev->dev.kobj,
+-              &wan_attr_group);
+-}
+-
+-static int wan_get_radiosw(void)
+-{
+-      int status;
+-
+-      if (!tp_features.wan)
+-              return -ENODEV;
+-
+-      if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
+-              return -EIO;
+-
+-      return ((status & TP_ACPI_WANCARD_RADIOSSW) != 0);
+-}
+-
+-static int wan_set_radiosw(int radio_on)
+-{
+-      int status;
+-
+-      if (!tp_features.wan)
+-              return -ENODEV;
+-
+-      if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
+-              return -EIO;
+-      if (radio_on)
+-              status |= TP_ACPI_WANCARD_RADIOSSW;
+-      else
+-              status &= ~TP_ACPI_WANCARD_RADIOSSW;
+-      if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
+-              return -EIO;
+-
+-      return 0;
+-}
+-
+ /* procfs -------------------------------------------------------------- */
+ static int wan_read(char *p)
+ {
+-- 
+1.5.6.2
+
diff --git a/releases/upstream/2.6.27-rc1/0004-ACPI-thinkpad-acpi-WLSW-overrides-other-rfkill-swi.patch b/releases/upstream/2.6.27-rc1/0004-ACPI-thinkpad-acpi-WLSW-overrides-other-rfkill-swi.patch
new file mode 100644 (file)
index 0000000..c664dc7
--- /dev/null
@@ -0,0 +1,77 @@
+From 133ec3bd3ae409895eacdce326cdc8d73c249e8a Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Mon, 21 Jul 2008 09:15:50 -0300
+Subject: ACPI: thinkpad-acpi: WLSW overrides other rfkill switches
+
+On ThinkPads where the WLSW switch exists, the firmware or the hardware
+ANDs the WLSW state with the device-specific switches (WWAN, Bluetooth).
+It is downright impossible to enable WWAN or Bluetooth when WLSW is
+blocking the radios.
+
+This reality does not necessarily carry over to the WWAN and Bluetooth
+firmware interfaces, though... so the state thinkpad-acpi was reporting
+could be incorrect.
+
+Tie the three switches in the driver so that we keep their state sane.
+When WLSL is off, force the other switches to off as well.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+---
+ drivers/misc/thinkpad_acpi.c |   20 ++++++++++++++++++++
+ 1 files changed, 20 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
+index 743a4d6..202d63e 100644
+--- a/drivers/misc/thinkpad_acpi.c
++++ b/drivers/misc/thinkpad_acpi.c
+@@ -2588,6 +2588,10 @@ static int bluetooth_get_radiosw(void)
+       if (!tp_features.bluetooth)
+               return -ENODEV;
++      /* WLSW overrides bluetooth in firmware/hardware, reflect that */
++      if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
++              return 0;
++
+       if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
+               return -EIO;
+@@ -2601,6 +2605,12 @@ static int bluetooth_set_radiosw(int radio_on)
+       if (!tp_features.bluetooth)
+               return -ENODEV;
++      /* WLSW overrides bluetooth in firmware/hardware, but there is no
++       * reason to risk weird behaviour. */
++      if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status
++          && radio_on)
++              return -EPERM;
++
+       if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
+               return -EIO;
+       if (radio_on)
+@@ -2760,6 +2770,10 @@ static int wan_get_radiosw(void)
+       if (!tp_features.wan)
+               return -ENODEV;
++      /* WLSW overrides WWAN in firmware/hardware, reflect that */
++      if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
++              return 0;
++
+       if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
+               return -EIO;
+@@ -2773,6 +2787,12 @@ static int wan_set_radiosw(int radio_on)
+       if (!tp_features.wan)
+               return -ENODEV;
++      /* WLSW overrides bluetooth in firmware/hardware, but there is no
++       * reason to risk weird behaviour. */
++      if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status
++          && radio_on)
++              return -EPERM;
++
+       if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
+               return -EIO;
+       if (radio_on)
+-- 
+1.5.6.2
+
diff --git a/releases/upstream/2.6.27-rc1/0005-ACPI-thinkpad-acpi-add-bluetooth-and-WWAN-rfkill-s.patch b/releases/upstream/2.6.27-rc1/0005-ACPI-thinkpad-acpi-add-bluetooth-and-WWAN-rfkill-s.patch
new file mode 100644 (file)
index 0000000..73f0cc0
--- /dev/null
@@ -0,0 +1,487 @@
+From 0e74dc2646db04b644faa8ea10ff4f408d55cf90 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Mon, 21 Jul 2008 09:15:51 -0300
+Subject: ACPI: thinkpad-acpi: add bluetooth and WWAN rfkill support
+
+Add a read/write rfkill interface to the bluetooth radio switch on the
+bluetooth submodule, and one for the wireless wan radio switch to the wan
+submodule.
+
+Since rfkill does care for when a switch changes state, use WLSW
+notifications to also check if the WWAN or Bluetooth switches did not
+change state (due to them being slaves of WLSW in firmware/hardware, but
+that reality not being always properly exported by the thinkpad firmware).
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Cc: Ivo van Doorn <IvDoorn@gmail.com>
+Cc: John W. Linville <linville@tuxdriver.com>
+---
+ Documentation/laptops/thinkpad-acpi.txt |   22 +++-
+ drivers/misc/Kconfig                    |    2 +
+ drivers/misc/thinkpad_acpi.c            |  208 +++++++++++++++++++++++++++----
+ 3 files changed, 200 insertions(+), 32 deletions(-)
+
+diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
+index 64b3f14..1c1c021 100644
+--- a/Documentation/laptops/thinkpad-acpi.txt
++++ b/Documentation/laptops/thinkpad-acpi.txt
+@@ -621,7 +621,8 @@ Bluetooth
+ ---------
+ procfs: /proc/acpi/ibm/bluetooth
+-sysfs device attribute: bluetooth_enable
++sysfs device attribute: bluetooth_enable (deprecated)
++sysfs rfkill class: switch "tpacpi_bluetooth_sw"
+ This feature shows the presence and current state of a ThinkPad
+ Bluetooth device in the internal ThinkPad CDC slot.
+@@ -643,8 +644,12 @@ Sysfs notes:
+               0: disables Bluetooth / Bluetooth is disabled
+               1: enables Bluetooth / Bluetooth is enabled.
+-      Note: this interface will be probably be superseded by the
+-      generic rfkill class, so it is NOT to be considered stable yet.
++      Note: this interface has been superseded by the generic rfkill
++      class.  It has been deprecated, and it will be removed in year
++      2010.
++
++      rfkill controller switch "tpacpi_bluetooth_sw": refer to
++      Documentation/rfkill.txt for details.
+ Video output control -- /proc/acpi/ibm/video
+ --------------------------------------------
+@@ -1374,7 +1379,8 @@ EXPERIMENTAL: WAN
+ -----------------
+ procfs: /proc/acpi/ibm/wan
+-sysfs device attribute: wwan_enable
++sysfs device attribute: wwan_enable (deprecated)
++sysfs rfkill class: switch "tpacpi_wwan_sw"
+ This feature is marked EXPERIMENTAL because the implementation
+ directly accesses hardware registers and may not work as expected. USE
+@@ -1404,8 +1410,12 @@ Sysfs notes:
+               0: disables WWAN card / WWAN card is disabled
+               1: enables WWAN card / WWAN card is enabled.
+-      Note: this interface will be probably be superseded by the
+-      generic rfkill class, so it is NOT to be considered stable yet.
++      Note: this interface has been superseded by the generic rfkill
++      class.  It has been deprecated, and it will be removed in year
++      2010.
++
++      rfkill controller switch "tpacpi_wwan_sw": refer to
++      Documentation/rfkill.txt for details.
+ Multiple Commands, Module Parameters
+ ------------------------------------
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index 1921b8d..b27ca91 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -279,6 +279,8 @@ config THINKPAD_ACPI
+       select INPUT
+       select NEW_LEDS
+       select LEDS_CLASS
++      select NET
++      select RFKILL
+       ---help---
+         This is a driver for the IBM and Lenovo ThinkPad laptops. It adds
+         support for Fn-Fx key combinations, Bluetooth control, video
+diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
+index 202d63e..dc8d00a 100644
+--- a/drivers/misc/thinkpad_acpi.c
++++ b/drivers/misc/thinkpad_acpi.c
+@@ -68,6 +68,7 @@
+ #include <linux/hwmon-sysfs.h>
+ #include <linux/input.h>
+ #include <linux/leds.h>
++#include <linux/rfkill.h>
+ #include <asm/uaccess.h>
+ #include <linux/dmi.h>
+@@ -144,6 +145,12 @@ enum {
+ #define TPACPI_MAX_ACPI_ARGS 3
++/* rfkill switches */
++enum {
++      TPACPI_RFK_BLUETOOTH_SW_ID = 0,
++      TPACPI_RFK_WWAN_SW_ID,
++};
++
+ /* Debugging */
+ #define TPACPI_LOG TPACPI_FILE ": "
+ #define TPACPI_ERR       KERN_ERR    TPACPI_LOG
+@@ -905,6 +912,43 @@ static int __init tpacpi_check_std_acpi_brightness_support(void)
+       return 0;
+ }
++static int __init tpacpi_new_rfkill(const unsigned int id,
++                      struct rfkill **rfk,
++                      const enum rfkill_type rfktype,
++                      const char *name,
++                      int (*toggle_radio)(void *, enum rfkill_state),
++                      int (*get_state)(void *, enum rfkill_state *))
++{
++      int res;
++      enum rfkill_state initial_state;
++
++      *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype);
++      if (!*rfk) {
++              printk(TPACPI_ERR
++                      "failed to allocate memory for rfkill class\n");
++              return -ENOMEM;
++      }
++
++      (*rfk)->name = name;
++      (*rfk)->get_state = get_state;
++      (*rfk)->toggle_radio = toggle_radio;
++
++      if (!get_state(NULL, &initial_state))
++              (*rfk)->state = initial_state;
++
++      res = rfkill_register(*rfk);
++      if (res < 0) {
++              printk(TPACPI_ERR
++                      "failed to register %s rfkill switch: %d\n",
++                      name, res);
++              rfkill_free(*rfk);
++              *rfk = NULL;
++              return res;
++      }
++
++      return 0;
++}
++
+ /*************************************************************************
+  * thinkpad-acpi driver attributes
+  */
+@@ -1906,10 +1950,18 @@ static struct attribute *hotkey_mask_attributes[] __initdata = {
+       &dev_attr_hotkey_wakeup_hotunplug_complete.attr,
+ };
++static void bluetooth_update_rfk(void);
++static void wan_update_rfk(void);
+ static void tpacpi_send_radiosw_update(void)
+ {
+       int wlsw;
++      /* Sync these BEFORE sending any rfkill events */
++      if (tp_features.bluetooth)
++              bluetooth_update_rfk();
++      if (tp_features.wan)
++              wan_update_rfk();
++
+       if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) {
+               mutex_lock(&tpacpi_inputdev_send_mutex);
+@@ -2581,6 +2633,8 @@ enum {
+       TP_ACPI_BLUETOOTH_UNK           = 0x04, /* unknown function */
+ };
++static struct rfkill *tpacpi_bluetooth_rfkill;
++
+ static int bluetooth_get_radiosw(void)
+ {
+       int status;
+@@ -2590,15 +2644,29 @@ static int bluetooth_get_radiosw(void)
+       /* WLSW overrides bluetooth in firmware/hardware, reflect that */
+       if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
+-              return 0;
++              return RFKILL_STATE_HARD_BLOCKED;
+       if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
+               return -EIO;
+-      return (status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0;
++      return ((status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0) ?
++              RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED;
+ }
+-static int bluetooth_set_radiosw(int radio_on)
++static void bluetooth_update_rfk(void)
++{
++      int status;
++
++      if (!tpacpi_bluetooth_rfkill)
++              return;
++
++      status = bluetooth_get_radiosw();
++      if (status < 0)
++              return;
++      rfkill_force_state(tpacpi_bluetooth_rfkill, status);
++}
++
++static int bluetooth_set_radiosw(int radio_on, int update_rfk)
+ {
+       int status;
+@@ -2620,6 +2688,9 @@ static int bluetooth_set_radiosw(int radio_on)
+       if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
+               return -EIO;
++      if (update_rfk)
++              bluetooth_update_rfk();
++
+       return 0;
+ }
+@@ -2634,7 +2705,8 @@ static ssize_t bluetooth_enable_show(struct device *dev,
+       if (status < 0)
+               return status;
+-      return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0);
++      return snprintf(buf, PAGE_SIZE, "%d\n",
++                      (status == RFKILL_STATE_UNBLOCKED) ? 1 : 0);
+ }
+ static ssize_t bluetooth_enable_store(struct device *dev,
+@@ -2647,7 +2719,7 @@ static ssize_t bluetooth_enable_store(struct device *dev,
+       if (parse_strtoul(buf, 1, &t))
+               return -EINVAL;
+-      res = bluetooth_set_radiosw(t);
++      res = bluetooth_set_radiosw(t, 1);
+       return (res) ? res : count;
+ }
+@@ -2667,8 +2739,27 @@ static const struct attribute_group bluetooth_attr_group = {
+       .attrs = bluetooth_attributes,
+ };
++static int tpacpi_bluetooth_rfk_get(void *data, enum rfkill_state *state)
++{
++      int bts = bluetooth_get_radiosw();
++
++      if (bts < 0)
++              return bts;
++
++      *state = bts;
++      return 0;
++}
++
++static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state)
++{
++      return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
++}
++
+ static void bluetooth_exit(void)
+ {
++      if (tpacpi_bluetooth_rfkill)
++              rfkill_unregister(tpacpi_bluetooth_rfkill);
++
+       sysfs_remove_group(&tpacpi_pdev->dev.kobj,
+                       &bluetooth_attr_group);
+ }
+@@ -2699,14 +2790,26 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
+                          "bluetooth hardware not installed\n");
+       }
+-      if (tp_features.bluetooth) {
+-              res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
++      if (!tp_features.bluetooth)
++              return 1;
++
++      res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
+                               &bluetooth_attr_group);
+-              if (res)
+-                      return res;
++      if (res)
++              return res;
++
++      res = tpacpi_new_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID,
++                              &tpacpi_bluetooth_rfkill,
++                              RFKILL_TYPE_BLUETOOTH,
++                              "tpacpi_bluetooth_sw",
++                              tpacpi_bluetooth_rfk_set,
++                              tpacpi_bluetooth_rfk_get);
++      if (res) {
++              bluetooth_exit();
++              return res;
+       }
+-      return (tp_features.bluetooth)? 0 : 1;
++      return 0;
+ }
+ /* procfs -------------------------------------------------------------- */
+@@ -2719,7 +2822,8 @@ static int bluetooth_read(char *p)
+               len += sprintf(p + len, "status:\t\tnot supported\n");
+       else {
+               len += sprintf(p + len, "status:\t\t%s\n",
+-                              (status)? "enabled" : "disabled");
++                              (status == RFKILL_STATE_UNBLOCKED) ?
++                                      "enabled" : "disabled");
+               len += sprintf(p + len, "commands:\tenable, disable\n");
+       }
+@@ -2735,9 +2839,9 @@ static int bluetooth_write(char *buf)
+       while ((cmd = next_cmd(&buf))) {
+               if (strlencmp(cmd, "enable") == 0) {
+-                      bluetooth_set_radiosw(1);
++                      bluetooth_set_radiosw(1, 1);
+               } else if (strlencmp(cmd, "disable") == 0) {
+-                      bluetooth_set_radiosw(0);
++                      bluetooth_set_radiosw(0, 1);
+               } else
+                       return -EINVAL;
+       }
+@@ -2763,6 +2867,8 @@ enum {
+       TP_ACPI_WANCARD_UNK             = 0x04, /* unknown function */
+ };
++static struct rfkill *tpacpi_wan_rfkill;
++
+ static int wan_get_radiosw(void)
+ {
+       int status;
+@@ -2772,15 +2878,29 @@ static int wan_get_radiosw(void)
+       /* WLSW overrides WWAN in firmware/hardware, reflect that */
+       if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
+-              return 0;
++              return RFKILL_STATE_HARD_BLOCKED;
+       if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
+               return -EIO;
+-      return (status & TP_ACPI_WANCARD_RADIOSSW) != 0;
++      return ((status & TP_ACPI_WANCARD_RADIOSSW) != 0) ?
++              RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED;
+ }
+-static int wan_set_radiosw(int radio_on)
++static void wan_update_rfk(void)
++{
++      int status;
++
++      if (!tpacpi_wan_rfkill)
++              return;
++
++      status = wan_get_radiosw();
++      if (status < 0)
++              return;
++      rfkill_force_state(tpacpi_wan_rfkill, status);
++}
++
++static int wan_set_radiosw(int radio_on, int update_rfk)
+ {
+       int status;
+@@ -2802,6 +2922,9 @@ static int wan_set_radiosw(int radio_on)
+       if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
+               return -EIO;
++      if (update_rfk)
++              wan_update_rfk();
++
+       return 0;
+ }
+@@ -2816,7 +2939,8 @@ static ssize_t wan_enable_show(struct device *dev,
+       if (status < 0)
+               return status;
+-      return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0);
++      return snprintf(buf, PAGE_SIZE, "%d\n",
++                      (status == RFKILL_STATE_UNBLOCKED) ? 1 : 0);
+ }
+ static ssize_t wan_enable_store(struct device *dev,
+@@ -2829,7 +2953,7 @@ static ssize_t wan_enable_store(struct device *dev,
+       if (parse_strtoul(buf, 1, &t))
+               return -EINVAL;
+-      res = wan_set_radiosw(t);
++      res = wan_set_radiosw(t, 1);
+       return (res) ? res : count;
+ }
+@@ -2849,8 +2973,27 @@ static const struct attribute_group wan_attr_group = {
+       .attrs = wan_attributes,
+ };
++static int tpacpi_wan_rfk_get(void *data, enum rfkill_state *state)
++{
++      int wans = wan_get_radiosw();
++
++      if (wans < 0)
++              return wans;
++
++      *state = wans;
++      return 0;
++}
++
++static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state)
++{
++      return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
++}
++
+ static void wan_exit(void)
+ {
++      if (tpacpi_wan_rfkill)
++              rfkill_unregister(tpacpi_wan_rfkill);
++
+       sysfs_remove_group(&tpacpi_pdev->dev.kobj,
+               &wan_attr_group);
+ }
+@@ -2879,14 +3022,26 @@ static int __init wan_init(struct ibm_init_struct *iibm)
+                          "wan hardware not installed\n");
+       }
+-      if (tp_features.wan) {
+-              res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
++      if (!tp_features.wan)
++              return 1;
++
++      res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
+                               &wan_attr_group);
+-              if (res)
+-                      return res;
++      if (res)
++              return res;
++
++      res = tpacpi_new_rfkill(TPACPI_RFK_WWAN_SW_ID,
++                              &tpacpi_wan_rfkill,
++                              RFKILL_TYPE_WWAN,
++                              "tpacpi_wwan_sw",
++                              tpacpi_wan_rfk_set,
++                              tpacpi_wan_rfk_get);
++      if (res) {
++              wan_exit();
++              return res;
+       }
+-      return (tp_features.wan)? 0 : 1;
++      return 0;
+ }
+ /* procfs -------------------------------------------------------------- */
+@@ -2899,7 +3054,8 @@ static int wan_read(char *p)
+               len += sprintf(p + len, "status:\t\tnot supported\n");
+       else {
+               len += sprintf(p + len, "status:\t\t%s\n",
+-                              (status)? "enabled" : "disabled");
++                              (status == RFKILL_STATE_UNBLOCKED) ?
++                                      "enabled" : "disabled");
+               len += sprintf(p + len, "commands:\tenable, disable\n");
+       }
+@@ -2915,9 +3071,9 @@ static int wan_write(char *buf)
+       while ((cmd = next_cmd(&buf))) {
+               if (strlencmp(cmd, "enable") == 0) {
+-                      wan_set_radiosw(1);
++                      wan_set_radiosw(1, 1);
+               } else if (strlencmp(cmd, "disable") == 0) {
+-                      wan_set_radiosw(0);
++                      wan_set_radiosw(0, 1);
+               } else
+                       return -EINVAL;
+       }
+-- 
+1.5.6.2
+
diff --git a/releases/upstream/2.6.27-rc1/0006-ACPI-thinkpad-acpi-bump-up-version-to-0.21.patch b/releases/upstream/2.6.27-rc1/0006-ACPI-thinkpad-acpi-bump-up-version-to-0.21.patch
new file mode 100644 (file)
index 0000000..0f423b5
--- /dev/null
@@ -0,0 +1,43 @@
+From 490673dc98adfc7de1703cc88508902bd10f446b Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Mon, 21 Jul 2008 09:15:51 -0300
+Subject: ACPI: thinkpad-acpi: bump up version to 0.21
+
+rfkill support deserves a new version checkpoint...
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+---
+ Documentation/laptops/thinkpad-acpi.txt |    4 ++--
+ drivers/misc/thinkpad_acpi.c            |    2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
+index 1c1c021..02dc748 100644
+--- a/Documentation/laptops/thinkpad-acpi.txt
++++ b/Documentation/laptops/thinkpad-acpi.txt
+@@ -1,7 +1,7 @@
+                    ThinkPad ACPI Extras Driver
+-                            Version 0.20
+-                          April 09th, 2008
++                            Version 0.21
++                           May 29th, 2008
+                Borislav Deianov <borislav@users.sf.net>
+              Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
+index dc8d00a..3eb01af 100644
+--- a/drivers/misc/thinkpad_acpi.c
++++ b/drivers/misc/thinkpad_acpi.c
+@@ -21,7 +21,7 @@
+  *  02110-1301, USA.
+  */
+-#define TPACPI_VERSION "0.20"
++#define TPACPI_VERSION "0.21"
+ #define TPACPI_SYSFS_VERSION 0x020200
+ /*
+-- 
+1.5.6.2
+
diff --git a/releases/upstream/2.6.27-rc1/0007-ACPI-thinkpad-acpi-don-t-misdetect-in-get_thinkpad.patch b/releases/upstream/2.6.27-rc1/0007-ACPI-thinkpad-acpi-don-t-misdetect-in-get_thinkpad.patch
new file mode 100644 (file)
index 0000000..81aa88b
--- /dev/null
@@ -0,0 +1,114 @@
+From bf20e740a4bcc686de02e2fd1c1810a58872f46e Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Mon, 21 Jul 2008 09:15:51 -0300
+Subject: ACPI: thinkpad-acpi: don't misdetect in get_thinkpad_model_data() on -ENOMEM
+
+Explicitly check for memory allocation failures, and return status to
+indicate that we could not collect data due to errors.
+
+This lets the driver have a far more predictable failure mode on ENOMEM in
+that codepath: it will refuse to load.  This is far better than trying to
+proceed with missing data which is used to detect quirks, etc.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+---
+ drivers/misc/thinkpad_acpi.c |   47 +++++++++++++++++++++++++++++------------
+ 1 files changed, 33 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
+index 3eb01af..d3eb790 100644
+--- a/drivers/misc/thinkpad_acpi.c
++++ b/drivers/misc/thinkpad_acpi.c
+@@ -6340,13 +6340,18 @@ err_out:
+ /* Probing */
+-static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp)
++/* returns 0 - probe ok, or < 0 - probe error.
++ * Probe ok doesn't mean thinkpad found.
++ * On error, kfree() cleanup on tp->* is not performed, caller must do it */
++static int __must_check __init get_thinkpad_model_data(
++                                              struct thinkpad_id_data *tp)
+ {
+       const struct dmi_device *dev = NULL;
+       char ec_fw_string[18];
++      char const *s;
+       if (!tp)
+-              return;
++              return -EINVAL;
+       memset(tp, 0, sizeof(*tp));
+@@ -6355,12 +6360,14 @@ static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp)
+       else if (dmi_name_in_vendors("LENOVO"))
+               tp->vendor = PCI_VENDOR_ID_LENOVO;
+       else
+-              return;
++              return 0;
+-      tp->bios_version_str = kstrdup(dmi_get_system_info(DMI_BIOS_VERSION),
+-                                      GFP_KERNEL);
++      s = dmi_get_system_info(DMI_BIOS_VERSION);
++      tp->bios_version_str = kstrdup(s, GFP_KERNEL);
++      if (s && !tp->bios_version_str)
++              return -ENOMEM;
+       if (!tp->bios_version_str)
+-              return;
++              return 0;
+       tp->bios_model = tp->bios_version_str[0]
+                        | (tp->bios_version_str[1] << 8);
+@@ -6379,21 +6386,27 @@ static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp)
+                       ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
+                       tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL);
++                      if (!tp->ec_version_str)
++                              return -ENOMEM;
+                       tp->ec_model = ec_fw_string[0]
+                                       | (ec_fw_string[1] << 8);
+                       break;
+               }
+       }
+-      tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION),
+-                                      GFP_KERNEL);
+-      if (tp->model_str && strnicmp(tp->model_str, "ThinkPad", 8) != 0) {
+-              kfree(tp->model_str);
+-              tp->model_str = NULL;
++      s = dmi_get_system_info(DMI_PRODUCT_VERSION);
++      if (s && !strnicmp(s, "ThinkPad", 8)) {
++              tp->model_str = kstrdup(s, GFP_KERNEL);
++              if (!tp->model_str)
++                      return -ENOMEM;
+       }
+-      tp->nummodel_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_NAME),
+-                                      GFP_KERNEL);
++      s = dmi_get_system_info(DMI_PRODUCT_NAME);
++      tp->nummodel_str = kstrdup(s, GFP_KERNEL);
++      if (s && !tp->nummodel_str)
++              return -ENOMEM;
++
++      return 0;
+ }
+ static int __init probe_for_thinkpad(void)
+@@ -6656,7 +6669,13 @@ static int __init thinkpad_acpi_module_init(void)
+       /* Driver-level probe */
+-      get_thinkpad_model_data(&thinkpad_id);
++      ret = get_thinkpad_model_data(&thinkpad_id);
++      if (ret) {
++              printk(TPACPI_ERR
++                      "unable to get DMI data: %d\n", ret);
++              thinkpad_acpi_module_exit();
++              return ret;
++      }
+       ret = probe_for_thinkpad();
+       if (ret) {
+               thinkpad_acpi_module_exit();
+-- 
+1.5.6.2
+