Add patches accepted for 2.6.30-rc1
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Thu, 9 Apr 2009 01:38:25 +0000 (8 22:38 -0300)
committerHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Thu, 9 Apr 2009 01:38:25 +0000 (8 22:38 -0300)
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
14 files changed:
releases/upstream/2.6.30-rc1/0001-trivial-Fix-misspelling-of-firmware.patch [new file with mode: 0644]
releases/upstream/2.6.30-rc1/0002-proc-2-2-remove-struct-proc_dir_entry-owner.patch [new file with mode: 0644]
releases/upstream/2.6.30-rc1/0003-thinkpad-acpi-update-copyright-notices.patch [new file with mode: 0644]
releases/upstream/2.6.30-rc1/0004-thinkpad-acpi-drop-ibm-acpi-alias.patch [new file with mode: 0644]
releases/upstream/2.6.30-rc1/0005-thinkpad-acpi-documentation-cleanup.patch [new file with mode: 0644]
releases/upstream/2.6.30-rc1/0006-thinkpad-acpi-cleanup-debug-helpers.patch [new file with mode: 0644]
releases/upstream/2.6.30-rc1/0007-thinkpad-acpi-add-missing-log-levels.patch [new file with mode: 0644]
releases/upstream/2.6.30-rc1/0008-thinkpad-acpi-add-new-debug-helpers-and-warn-of-dep.patch [new file with mode: 0644]
releases/upstream/2.6.30-rc1/0009-thinkpad-acpi-remove-HKEY-disable-functionality.patch [new file with mode: 0644]
releases/upstream/2.6.30-rc1/0010-thinkpad-acpi-restrict-access-to-some-firmware-LEDs.patch [new file with mode: 0644]
releases/upstream/2.6.30-rc1/0011-thinkpad-acpi-enhanced-debugging-messages-for-rfkil.patch [new file with mode: 0644]
releases/upstream/2.6.30-rc1/0012-thinkpad-acpi-enhanced-debugging-messages-for-the-h.patch [new file with mode: 0644]
releases/upstream/2.6.30-rc1/0013-thinkpad-acpi-enhanced-debugging-messages-for-the-f.patch [new file with mode: 0644]
releases/upstream/2.6.30-rc1/0014-thinkpad-acpi-rework-brightness-support.patch [new file with mode: 0644]

diff --git a/releases/upstream/2.6.30-rc1/0001-trivial-Fix-misspelling-of-firmware.patch b/releases/upstream/2.6.30-rc1/0001-trivial-Fix-misspelling-of-firmware.patch
new file mode 100644 (file)
index 0000000..e2b664c
--- /dev/null
@@ -0,0 +1,303 @@
+From 877d03105d04b2c13e241130277fa69c8d2564f0 Mon Sep 17 00:00:00 2001
+From: Nick Andrew <nick@nick-andrew.net>
+Date: Mon, 26 Jan 2009 11:06:57 +0100
+Subject: trivial: Fix misspelling of firmware
+
+Fix misspelling of firmware.
+
+Signed-off-by: Nick Andrew <nick@nick-andrew.net>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+---
+ Documentation/ia64/kvm.txt                         |    2 +-
+ .../dts-bindings/fsl/cpm_qe/qe/firmware.txt        |    2 +-
+ arch/mips/sgi-ip27/ip27-smp.c                      |    2 +-
+ arch/sparc/kernel/head_64.S                        |    2 +-
+ drivers/net/sb1250-mac.c                           |    2 +-
+ drivers/net/tg3.c                                  |    2 +-
+ drivers/net/wireless/ipw2x00/ipw2100.c             |    2 +-
+ drivers/net/wireless/ipw2x00/ipw2200.c             |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-agn.c             |    2 +-
+ drivers/net/wireless/iwlwifi/iwl3945-base.c        |    2 +-
+ drivers/net/wireless/libertas/cmd.c                |    2 +-
+ drivers/pci/pci.c                                  |    2 +-
+ drivers/platform/x86/thinkpad_acpi.c               |    2 +-
+ drivers/staging/otus/hal/hpmain.c                  |    2 +-
+ drivers/usb/atm/ueagle-atm.c                       |    2 +-
+ drivers/usb/serial/ChangeLog.history               |    2 +-
+ include/linux/libata.h                             |    2 +-
+ kernel/power/disk.c                                |    4 ++--
+ sound/oss/pss.c                                    |    2 +-
+ sound/sh/aica.c                                    |    2 +-
+ 20 files changed, 21 insertions(+), 21 deletions(-)
+
+diff --git a/Documentation/ia64/kvm.txt b/Documentation/ia64/kvm.txt
+index 84f7cb3..ffb5c80 100644
+--- a/Documentation/ia64/kvm.txt
++++ b/Documentation/ia64/kvm.txt
+@@ -42,7 +42,7 @@ Note: For step 2, please make sure that host page size == TARGET_PAGE_SIZE of qe
+               hg clone http://xenbits.xensource.com/ext/efi-vfirmware.hg
+           you can get the firmware's binary in the directory of efi-vfirmware.hg/binaries.
+-      (3) Rename the firware you owned to Flash.fd, and copy it to /usr/local/share/qemu
++      (3) Rename the firmware you owned to Flash.fd, and copy it to /usr/local/share/qemu
+ 4. Boot up Linux or Windows guests:
+       4.1 Create or install a image for guest boot. If you have xen experience, it should be easy.
+diff --git a/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/firmware.txt b/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/firmware.txt
+index 6c238f5..249db3a 100644
+--- a/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/firmware.txt
++++ b/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/firmware.txt
+@@ -1,6 +1,6 @@
+ * Uploaded QE firmware
+-      If a new firwmare has been uploaded to the QE (usually by the
++      If a new firmware has been uploaded to the QE (usually by the
+       boot loader), then a 'firmware' child node should be added to the QE
+       node.  This node provides information on the uploaded firmware that
+       device drivers may need.
+diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c
+index 5b47d6b..cbcd7eb 100644
+--- a/arch/mips/sgi-ip27/ip27-smp.c
++++ b/arch/mips/sgi-ip27/ip27-smp.c
+@@ -221,7 +221,7 @@ static void __init ip27_smp_setup(void)
+        * Assumption to be fixed: we're always booted on logical / physical
+        * processor 0.  While we're always running on logical processor 0
+        * this still means this is physical processor zero; it might for
+-       * example be disabled in the firwware.
++       * example be disabled in the firmware.
+        */
+       alloc_cpupda(0, 0);
+ }
+diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S
+index a46c3a2..3a1b7bf 100644
+--- a/arch/sparc/kernel/head_64.S
++++ b/arch/sparc/kernel/head_64.S
+@@ -686,7 +686,7 @@ tlb_fixup_done:
+        * point.
+        *
+        * There used to be enormous complexity wrt. transferring
+-       * over from the firwmare's trap table to the Linux kernel's.
++       * over from the firmware's trap table to the Linux kernel's.
+        * For example, there was a chicken & egg problem wrt. building
+        * the OBP page tables, yet needing to be on the Linux kernel
+        * trap table (to translate PAGE_OFFSET addresses) in order to
+diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
+index 88dd2e0..ce7551e 100644
+--- a/drivers/net/sb1250-mac.c
++++ b/drivers/net/sb1250-mac.c
+@@ -2299,7 +2299,7 @@ static int sbmac_init(struct platform_device *pldev, long long base)
+       eaddr = sc->sbm_hwaddr;
+       /*
+-       * Read the ethernet address.  The firwmare left this programmed
++       * Read the ethernet address.  The firmware left this programmed
+        * for us in the ethernet address register for each mac.
+        */
+diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
+index f7efcec..ed60b18 100644
+--- a/drivers/net/tg3.c
++++ b/drivers/net/tg3.c
+@@ -11225,7 +11225,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
+               return tg3_phy_init(tp);
+       /* Reading the PHY ID register can conflict with ASF
+-       * firwmare access to the PHY hardware.
++       * firmware access to the PHY hardware.
+        */
+       err = 0;
+       if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
+diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
+index 115b704..f4e963b 100644
+--- a/drivers/net/wireless/ipw2x00/ipw2100.c
++++ b/drivers/net/wireless/ipw2x00/ipw2100.c
+@@ -2362,7 +2362,7 @@ static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
+                      i * sizeof(struct ipw2100_status));
+ #ifdef IPW2100_DEBUG_C3
+-      /* Halt the fimrware so we can get a good image */
++      /* Halt the firmware so we can get a good image */
+       write_register(priv->net_dev, IPW_REG_RESET_REG,
+                      IPW_AUX_HOST_RESET_REG_STOP_MASTER);
+       j = 5;
+diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
+index b344994..f6174fd 100644
+--- a/drivers/net/wireless/ipw2x00/ipw2200.c
++++ b/drivers/net/wireless/ipw2x00/ipw2200.c
+@@ -8844,7 +8844,7 @@ static int ipw_wx_set_mode(struct net_device *dev,
+ #endif                                /* CONFIG_IPW2200_MONITOR */
+       /* Free the existing firmware and reset the fw_loaded
+-       * flag so ipw_load() will bring in the new firmawre */
++       * flag so ipw_load() will bring in the new firmware */
+       free_firmware();
+       priv->ieee->iw_mode = wrqu->mode;
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
+index 663dc83..3889158 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
+@@ -1337,7 +1337,7 @@ static int iwl_read_ucode(struct iwl_priv *priv)
+       /* api_ver should match the api version forming part of the
+        * firmware filename ... but we don't check for that and only rely
+-       * on the API version read from firware header from here on forward */
++       * on the API version read from firmware header from here on forward */
+       if (api_ver < api_min || api_ver > api_max) {
+               IWL_ERR(priv, "Driver unable to support your firmware API. "
+diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
+index a71b08c..9d5f97d 100644
+--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
++++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
+@@ -2562,7 +2562,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
+       /* api_ver should match the api version forming part of the
+        * firmware filename ... but we don't check for that and only rely
+-       * on the API version read from firware header from here on forward */
++       * on the API version read from firmware header from here on forward */
+       if (api_ver < api_min || api_ver > api_max) {
+               IWL_ERR(priv, "Driver unable to support your firmware API. "
+diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
+index 639dd02..8c3605c 100644
+--- a/drivers/net/wireless/libertas/cmd.c
++++ b/drivers/net/wireless/libertas/cmd.c
+@@ -1649,7 +1649,7 @@ static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv)
+ /**
+  *  @brief This function executes next command in command
+- *  pending queue. It will put fimware back to PS mode
++ *  pending queue. It will put firmware back to PS mode
+  *  if applicable.
+  *
+  *  @param priv     A pointer to struct lbs_private structure
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index 6d61200..dab33a2 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -550,7 +550,7 @@ void pci_update_current_state(struct pci_dev *dev, pci_power_t state)
+  * @dev: PCI device to handle.
+  * @state: PCI power state (D0, D1, D2, D3hot) to put the device into.
+  *
+- * Transition a device to a new power state, using the platform formware and/or
++ * Transition a device to a new power state, using the platform firmware and/or
+  * the device's PCI PM registers.
+  *
+  * RETURN VALUE:
+diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
+index d243320..814cb65 100644
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -5811,7 +5811,7 @@ static struct ibm_struct volume_driver_data = {
+  *    ThinkPads from this same time period (and earlier) probably lack the
+  *    tachometer as well.
+  *
+- *    Unfortunately a lot of ThinkPads with new-style ECs but whose firwmare
++ *    Unfortunately a lot of ThinkPads with new-style ECs but whose firmware
+  *    was never fixed by IBM to report the EC firmware version string
+  *    probably support the tachometer (like the early X models), so
+  *    detecting it is quite hard.  We need more data to know for sure.
+diff --git a/drivers/staging/otus/hal/hpmain.c b/drivers/staging/otus/hal/hpmain.c
+index 2e65c46..dab2783 100644
+--- a/drivers/staging/otus/hal/hpmain.c
++++ b/drivers/staging/otus/hal/hpmain.c
+@@ -152,7 +152,7 @@ u16_t zfHpInit(zdev_t* dev, u32_t frequency)
+     else
+     {
+     #ifndef ZM_OTUS_LINUX_PHASE_2
+-        /* donwload the normal frimware */
++        /* download the normal firmware */
+         if ((ret = zfFirmwareDownload(dev, (u32_t*)zcFwImage,
+                 (u32_t)zcFwImageSize, ZM_FIRMWARE_WLAN_ADDR)) != ZM_SUCCESS)
+         {
+diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
+index b6483dd..9cf9ff6 100644
+--- a/drivers/usb/atm/ueagle-atm.c
++++ b/drivers/usb/atm/ueagle-atm.c
+@@ -626,7 +626,7 @@ static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *conte
+               goto err_fw_corrupted;
+       /*
+-       * Start to upload formware : send reset
++       * Start to upload firmware : send reset
+        */
+       value = 1;
+       ret = uea_send_modem_cmd(usb, F8051_USBCS, sizeof(value), &value);
+diff --git a/drivers/usb/serial/ChangeLog.history b/drivers/usb/serial/ChangeLog.history
+index c1b2799..f13fd48 100644
+--- a/drivers/usb/serial/ChangeLog.history
++++ b/drivers/usb/serial/ChangeLog.history
+@@ -715,7 +715,7 @@ io_edgeport.c Change Log comments:
+  0.2 (01/30/2000) greg kroah-hartman
+       Milestone 1 release.
+-      Device is found by USB subsystem, enumerated, fimware is downloaded
++      Device is found by USB subsystem, enumerated, firmware is downloaded
+       and the descriptors are printed to the debug log, config is set, and
+       green light starts to blink. Open port works, and data can be sent
+       and received at the default settings of the UART. Loopback connector
+diff --git a/include/linux/libata.h b/include/linux/libata.h
+index 76262d8..b450a26 100644
+--- a/include/linux/libata.h
++++ b/include/linux/libata.h
+@@ -379,7 +379,7 @@ enum {
+       ATA_HORKAGE_BRIDGE_OK   = (1 << 10),    /* no bridge limits */
+       ATA_HORKAGE_ATAPI_MOD16_DMA = (1 << 11), /* use ATAPI DMA for commands
+                                                   not multiple of 16 bytes */
+-      ATA_HORKAGE_FIRMWARE_WARN = (1 << 12),  /* firwmare update warning */
++      ATA_HORKAGE_FIRMWARE_WARN = (1 << 12),  /* firmware update warning */
+       ATA_HORKAGE_1_5_GBPS    = (1 << 13),    /* force 1.5 Gbps */
+        /* DMA mask for user DMA control: User visible values; DO NOT
+diff --git a/kernel/power/disk.c b/kernel/power/disk.c
+index 4a4a206..9d1c1a0 100644
+--- a/kernel/power/disk.c
++++ b/kernel/power/disk.c
+@@ -265,7 +265,7 @@ static int create_image(int platform_mode)
+  *    hibernation_snapshot - quiesce devices and create the hibernation
+  *    snapshot image.
+  *    @platform_mode - if set, use the platform driver, if available, to
+- *                     prepare the platform frimware for the power transition.
++ *                     prepare the platform firmware for the power transition.
+  *
+  *    Must be called with pm_mutex held
+  */
+@@ -378,7 +378,7 @@ static int resume_target_kernel(void)
+  *    hibernation_restore - quiesce devices and restore the hibernation
+  *    snapshot image.  If successful, control returns in hibernation_snaphot()
+  *    @platform_mode - if set, use the platform driver, if available, to
+- *                     prepare the platform frimware for the transition.
++ *                     prepare the platform firmware for the transition.
+  *
+  *    Must be called with pm_mutex held
+  */
+diff --git a/sound/oss/pss.c b/sound/oss/pss.c
+index 16517a5..83f5ee2 100644
+--- a/sound/oss/pss.c
++++ b/sound/oss/pss.c
+@@ -46,7 +46,7 @@
+  *          load the driver as it did in previous versions.
+  * 04-07-1999: Anthony Barbachan <barbcode@xmen.cis.fordham.edu>
+  *          Added module parameter pss_firmware to allow the user to tell 
+- *          the driver where the fireware file is located.  The default 
++ *          the driver where the firmware file is located.  The default 
+  *          setting is the previous hardcoded setting "/etc/sound/pss_synth".
+  * 00-03-03: Christoph Hellwig <chhellwig@infradead.org>
+  *        Adapted to module_init/module_exit
+diff --git a/sound/sh/aica.c b/sound/sh/aica.c
+index f551233..583a369 100644
+--- a/sound/sh/aica.c
++++ b/sound/sh/aica.c
+@@ -565,7 +565,7 @@ static int load_aica_firmware(void)
+       err = request_firmware(&fw_entry, "aica_firmware.bin", &pd->dev);
+       if (unlikely(err))
+               return err;
+-      /* write firware into memory */
++      /* write firmware into memory */
+       spu_disable();
+       spu_memload(0, fw_entry->data, fw_entry->size);
+       spu_enable();
+-- 
+1.6.2.1
+
diff --git a/releases/upstream/2.6.30-rc1/0002-proc-2-2-remove-struct-proc_dir_entry-owner.patch b/releases/upstream/2.6.30-rc1/0002-proc-2-2-remove-struct-proc_dir_entry-owner.patch
new file mode 100644 (file)
index 0000000..9f56c2e
--- /dev/null
@@ -0,0 +1,1274 @@
+From 99b76233803beab302123d243eea9e41149804f3 Mon Sep 17 00:00:00 2001
+From: Alexey Dobriyan <adobriyan@gmail.com>
+Date: Wed, 25 Mar 2009 22:48:06 +0300
+Subject: proc 2/2: remove struct proc_dir_entry::owner
+
+Setting ->owner as done currently (pde->owner = THIS_MODULE) is racy
+as correctly noted at bug #12454. Someone can lookup entry with NULL
+->owner, thus not pinning enything, and release it later resulting
+in module refcount underflow.
+
+We can keep ->owner and supply it at registration time like ->proc_fops
+and ->data.
+
+But this leaves ->owner as easy-manipulative field (just one C assignment)
+and somebody will forget to unpin previous/pin current module when
+switching ->owner. ->proc_fops is declared as "const" which should give
+some thoughts.
+
+->read_proc/->write_proc were just fixed to not require ->owner for
+protection.
+
+rmmod'ed directories will be empty and return "." and ".." -- no harm.
+And directories with tricky enough readdir and lookup shouldn't be modular.
+We definitely don't want such modular code.
+
+Removing ->owner will also make PDE smaller.
+
+So, let's nuke it.
+
+Kudos to Jeff Layton for reminding about this, let's say, oversight.
+
+http://bugzilla.kernel.org/show_bug.cgi?id=12454
+
+Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
+---
+ Documentation/DocBook/procfs_example.c  |    9 --------
+ arch/alpha/kernel/srm_env.c             |    5 ----
+ arch/blackfin/mm/sram-alloc.c           |    1 -
+ arch/ia64/kernel/palinfo.c              |    2 -
+ arch/ia64/sn/kernel/sn2/prominfo_proc.c |    9 +------
+ arch/powerpc/kernel/rtas_flash.c        |    1 -
+ arch/sparc/kernel/led.c                 |    1 -
+ arch/x86/kernel/cpu/mtrr/if.c           |   10 +--------
+ drivers/acpi/ac.c                       |    1 -
+ drivers/acpi/battery.c                  |    1 -
+ drivers/acpi/button.c                   |    3 --
+ drivers/acpi/fan.c                      |    2 -
+ drivers/acpi/processor_core.c           |    2 -
+ drivers/acpi/sbs.c                      |    1 -
+ drivers/acpi/thermal.c                  |    2 -
+ drivers/acpi/video.c                    |    5 ----
+ drivers/block/ps3vram.c                 |    2 -
+ drivers/char/ipmi/ipmi_msghandler.c     |   12 +++-------
+ drivers/char/ipmi/ipmi_si_intf.c        |    6 ++--
+ drivers/input/input.c                   |    2 -
+ drivers/isdn/hardware/eicon/divasi.c    |    1 -
+ drivers/media/video/cpia.c              |    4 +--
+ drivers/message/i2o/i2o_proc.c          |    2 -
+ drivers/net/bonding/bond_main.c         |   35 +-----------------------------
+ drivers/net/irda/vlsi_ir.c              |    7 ------
+ drivers/net/wireless/airo.c             |    1 -
+ drivers/platform/x86/asus_acpi.c        |    3 --
+ drivers/platform/x86/thinkpad_acpi.c    |    2 -
+ drivers/platform/x86/toshiba_acpi.c     |    3 --
+ drivers/rtc/rtc-proc.c                  |   10 +-------
+ drivers/s390/block/dasd_proc.c          |    2 -
+ drivers/scsi/scsi_devinfo.c             |    2 -
+ drivers/scsi/scsi_proc.c                |    3 --
+ drivers/video/via/viafbdev.c            |    5 ----
+ fs/afs/proc.c                           |    1 -
+ fs/cifs/cifs_debug.c                    |    1 -
+ fs/jfs/jfs_debug.c                      |    1 -
+ fs/nfs/client.c                         |    2 -
+ fs/proc/inode.c                         |   19 ++--------------
+ fs/proc/proc_tty.c                      |    1 -
+ fs/reiserfs/procfs.c                    |    5 +---
+ include/linux/ipmi_smi.h                |    2 +-
+ include/linux/proc_fs.h                 |    4 ---
+ net/appletalk/atalk_proc.c              |    1 -
+ net/atm/mpoa_proc.c                     |    1 -
+ net/atm/proc.c                          |    1 -
+ net/can/bcm.c                           |    4 ---
+ net/can/proc.c                          |    2 -
+ net/core/pktgen.c                       |    1 -
+ net/irda/irproc.c                       |    1 -
+ net/llc/llc_proc.c                      |    1 -
+ net/sctp/protocol.c                     |    8 +-----
+ net/sunrpc/cache.c                      |    4 ---
+ net/sunrpc/stats.c                      |   10 +-------
+ sound/core/info.c                       |   31 +-------------------------
+ 55 files changed, 26 insertions(+), 232 deletions(-)
+
+diff --git a/Documentation/DocBook/procfs_example.c b/Documentation/DocBook/procfs_example.c
+index 8c6396e..a5b1179 100644
+--- a/Documentation/DocBook/procfs_example.c
++++ b/Documentation/DocBook/procfs_example.c
+@@ -117,9 +117,6 @@ static int __init init_procfs_example(void)
+               rv = -ENOMEM;
+               goto out;
+       }
+-      
+-      example_dir->owner = THIS_MODULE;
+-      
+       /* create jiffies using convenience function */
+       jiffies_file = create_proc_read_entry("jiffies", 
+                                             0444, example_dir, 
+@@ -130,8 +127,6 @@ static int __init init_procfs_example(void)
+               goto no_jiffies;
+       }
+-      jiffies_file->owner = THIS_MODULE;
+-
+       /* create foo and bar files using same callback
+        * functions 
+        */
+@@ -146,7 +141,6 @@ static int __init init_procfs_example(void)
+       foo_file->data = &foo_data;
+       foo_file->read_proc = proc_read_foobar;
+       foo_file->write_proc = proc_write_foobar;
+-      foo_file->owner = THIS_MODULE;
+               
+       bar_file = create_proc_entry("bar", 0644, example_dir);
+       if(bar_file == NULL) {
+@@ -159,7 +153,6 @@ static int __init init_procfs_example(void)
+       bar_file->data = &bar_data;
+       bar_file->read_proc = proc_read_foobar;
+       bar_file->write_proc = proc_write_foobar;
+-      bar_file->owner = THIS_MODULE;
+               
+       /* create symlink */
+       symlink = proc_symlink("jiffies_too", example_dir, 
+@@ -169,8 +162,6 @@ static int __init init_procfs_example(void)
+               goto no_symlink;
+       }
+-      symlink->owner = THIS_MODULE;
+-
+       /* everything OK */
+       printk(KERN_INFO "%s %s initialised\n",
+              MODULE_NAME, MODULE_VERS);
+diff --git a/arch/alpha/kernel/srm_env.c b/arch/alpha/kernel/srm_env.c
+index 78ad7cd..d12af47 100644
+--- a/arch/alpha/kernel/srm_env.c
++++ b/arch/alpha/kernel/srm_env.c
+@@ -218,7 +218,6 @@ srm_env_init(void)
+                               BASE_DIR);
+               goto cleanup;
+       }
+-      base_dir->owner = THIS_MODULE;
+       /*
+        * Create per-name subdirectory
+@@ -229,7 +228,6 @@ srm_env_init(void)
+                               BASE_DIR, NAMED_DIR);
+               goto cleanup;
+       }
+-      named_dir->owner = THIS_MODULE;
+       /*
+        * Create per-number subdirectory
+@@ -241,7 +239,6 @@ srm_env_init(void)
+               goto cleanup;
+       }
+-      numbered_dir->owner = THIS_MODULE;
+       /*
+        * Create all named nodes
+@@ -254,7 +251,6 @@ srm_env_init(void)
+                       goto cleanup;
+               entry->proc_entry->data         = (void *) entry;
+-              entry->proc_entry->owner        = THIS_MODULE;
+               entry->proc_entry->read_proc    = srm_env_read;
+               entry->proc_entry->write_proc   = srm_env_write;
+@@ -275,7 +271,6 @@ srm_env_init(void)
+               entry->id                       = var_num;
+               entry->proc_entry->data         = (void *) entry;
+-              entry->proc_entry->owner        = THIS_MODULE;
+               entry->proc_entry->read_proc    = srm_env_read;
+               entry->proc_entry->write_proc   = srm_env_write;
+       }
+diff --git a/arch/blackfin/mm/sram-alloc.c b/arch/blackfin/mm/sram-alloc.c
+index 834cab7..530d139 100644
+--- a/arch/blackfin/mm/sram-alloc.c
++++ b/arch/blackfin/mm/sram-alloc.c
+@@ -854,7 +854,6 @@ static int __init sram_proc_init(void)
+               printk(KERN_WARNING "unable to create /proc/sram\n");
+               return -1;
+       }
+-      ptr->owner = THIS_MODULE;
+       ptr->read_proc = sram_proc_read;
+       return 0;
+ }
+diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
+index e5c57f4..a4f19c7 100644
+--- a/arch/ia64/kernel/palinfo.c
++++ b/arch/ia64/kernel/palinfo.c
+@@ -1002,8 +1002,6 @@ create_palinfo_proc_entries(unsigned int cpu)
+               *pdir = create_proc_read_entry(
+                               palinfo_entries[j].name, 0, cpu_dir,
+                               palinfo_read_entry, (void *)f.value);
+-              if (*pdir)
+-                      (*pdir)->owner = THIS_MODULE;
+               pdir++;
+       }
+ }
+diff --git a/arch/ia64/sn/kernel/sn2/prominfo_proc.c b/arch/ia64/sn/kernel/sn2/prominfo_proc.c
+index 4dcce3d..e633288 100644
+--- a/arch/ia64/sn/kernel/sn2/prominfo_proc.c
++++ b/arch/ia64/sn/kernel/sn2/prominfo_proc.c
+@@ -225,7 +225,6 @@ static struct proc_dir_entry *sgi_prominfo_entry;
+ int __init prominfo_init(void)
+ {
+       struct proc_dir_entry **entp;
+-      struct proc_dir_entry *p;
+       cnodeid_t cnodeid;
+       unsigned long nasid;
+       int size;
+@@ -246,14 +245,10 @@ int __init prominfo_init(void)
+               sprintf(name, "node%d", cnodeid);
+               *entp = proc_mkdir(name, sgi_prominfo_entry);
+               nasid = cnodeid_to_nasid(cnodeid);
+-              p = create_proc_read_entry("fit", 0, *entp, read_fit_entry,
++              create_proc_read_entry("fit", 0, *entp, read_fit_entry,
+                                          (void *)nasid);
+-              if (p)
+-                      p->owner = THIS_MODULE;
+-              p = create_proc_read_entry("version", 0, *entp,
++              create_proc_read_entry("version", 0, *entp,
+                                          read_version_entry, (void *)nasid);
+-              if (p)
+-                      p->owner = THIS_MODULE;
+               entp++;
+       }
+diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
+index 149cb11..13011a9 100644
+--- a/arch/powerpc/kernel/rtas_flash.c
++++ b/arch/powerpc/kernel/rtas_flash.c
+@@ -669,7 +669,6 @@ static void remove_flash_pde(struct proc_dir_entry *dp)
+ {
+       if (dp) {
+               kfree(dp->data);
+-              dp->owner = NULL;
+               remove_proc_entry(dp->name, dp->parent);
+       }
+ }
+diff --git a/arch/sparc/kernel/led.c b/arch/sparc/kernel/led.c
+index adaaed4..00d034e 100644
+--- a/arch/sparc/kernel/led.c
++++ b/arch/sparc/kernel/led.c
+@@ -126,7 +126,6 @@ static int __init led_init(void)
+       led = proc_create("led", 0, NULL, &led_proc_fops);
+       if (!led)
+               return -ENOMEM;
+-      led->owner = THIS_MODULE;
+       printk(KERN_INFO
+              "led: version %s, Lars Kotthoff <metalhead@metalhead.ws>\n",
+diff --git a/arch/x86/kernel/cpu/mtrr/if.c b/arch/x86/kernel/cpu/mtrr/if.c
+index 4c42146..fb73a52 100644
+--- a/arch/x86/kernel/cpu/mtrr/if.c
++++ b/arch/x86/kernel/cpu/mtrr/if.c
+@@ -377,10 +377,6 @@ static const struct file_operations mtrr_fops = {
+       .release = mtrr_close,
+ };
+-
+-static struct proc_dir_entry *proc_root_mtrr;
+-
+-
+ static int mtrr_seq_show(struct seq_file *seq, void *offset)
+ {
+       char factor;
+@@ -423,11 +419,7 @@ static int __init mtrr_if_init(void)
+           (!cpu_has(c, X86_FEATURE_CENTAUR_MCR)))
+               return -ENODEV;
+-      proc_root_mtrr =
+-              proc_create("mtrr", S_IWUSR | S_IRUGO, NULL, &mtrr_fops);
+-
+-      if (proc_root_mtrr)
+-              proc_root_mtrr->owner = THIS_MODULE;
++      proc_create("mtrr", S_IWUSR | S_IRUGO, NULL, &mtrr_fops);
+       return 0;
+ }
+diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
+index 9b917da..88e42ab 100644
+--- a/drivers/acpi/ac.c
++++ b/drivers/acpi/ac.c
+@@ -191,7 +191,6 @@ static int acpi_ac_add_fs(struct acpi_device *device)
+                                                    acpi_ac_dir);
+               if (!acpi_device_dir(device))
+                       return -ENODEV;
+-              acpi_device_dir(device)->owner = THIS_MODULE;
+       }
+       /* 'state' [R] */
+diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
+index 69cbc57..3bcb5bf 100644
+--- a/drivers/acpi/battery.c
++++ b/drivers/acpi/battery.c
+@@ -760,7 +760,6 @@ static int acpi_battery_add_fs(struct acpi_device *device)
+                                                    acpi_battery_dir);
+               if (!acpi_device_dir(device))
+                       return -ENODEV;
+-              acpi_device_dir(device)->owner = THIS_MODULE;
+       }
+       for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
+diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
+index 171fd91..c2f0606 100644
+--- a/drivers/acpi/button.c
++++ b/drivers/acpi/button.c
+@@ -200,12 +200,10 @@ static int acpi_button_add_fs(struct acpi_device *device)
+       if (!entry)
+               return -ENODEV;
+-      entry->owner = THIS_MODULE;
+       acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry);
+       if (!acpi_device_dir(device))
+               return -ENODEV;
+-      acpi_device_dir(device)->owner = THIS_MODULE;
+       /* 'info' [R] */
+       entry = proc_create_data(ACPI_BUTTON_FILE_INFO,
+@@ -522,7 +520,6 @@ static int __init acpi_button_init(void)
+       acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
+       if (!acpi_button_dir)
+               return -ENODEV;
+-      acpi_button_dir->owner = THIS_MODULE;
+       result = acpi_bus_register_driver(&acpi_button_driver);
+       if (result < 0) {
+               remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
+diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
+index eaaee16..8a02944 100644
+--- a/drivers/acpi/fan.c
++++ b/drivers/acpi/fan.c
+@@ -193,7 +193,6 @@ static int acpi_fan_add_fs(struct acpi_device *device)
+                                                    acpi_fan_dir);
+               if (!acpi_device_dir(device))
+                       return -ENODEV;
+-              acpi_device_dir(device)->owner = THIS_MODULE;
+       }
+       /* 'status' [R/W] */
+@@ -347,7 +346,6 @@ static int __init acpi_fan_init(void)
+       acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
+       if (!acpi_fan_dir)
+               return -ENODEV;
+-      acpi_fan_dir->owner = THIS_MODULE;
+ #endif
+       result = acpi_bus_register_driver(&acpi_fan_driver);
+diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
+index 0cc2fd3..fa2f742 100644
+--- a/drivers/acpi/processor_core.c
++++ b/drivers/acpi/processor_core.c
+@@ -359,7 +359,6 @@ static int acpi_processor_add_fs(struct acpi_device *device)
+               if (!acpi_device_dir(device))
+                       return -ENODEV;
+       }
+-      acpi_device_dir(device)->owner = THIS_MODULE;
+       /* 'info' [R] */
+       entry = proc_create_data(ACPI_PROCESSOR_FILE_INFO,
+@@ -1137,7 +1136,6 @@ static int __init acpi_processor_init(void)
+       acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
+       if (!acpi_processor_dir)
+               return -ENOMEM;
+-      acpi_processor_dir->owner = THIS_MODULE;
+       /*
+        * Check whether the system is DMI table. If yes, OSPM
+diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
+index 6050ce4..59afd52 100644
+--- a/drivers/acpi/sbs.c
++++ b/drivers/acpi/sbs.c
+@@ -488,7 +488,6 @@ acpi_sbs_add_fs(struct proc_dir_entry **dir,
+               if (!*dir) {
+                       return -ENODEV;
+               }
+-              (*dir)->owner = THIS_MODULE;
+       }
+       /* 'info' [R] */
+diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
+index 99e6f1f..c11f9ae 100644
+--- a/drivers/acpi/thermal.c
++++ b/drivers/acpi/thermal.c
+@@ -1506,7 +1506,6 @@ static int acpi_thermal_add_fs(struct acpi_device *device)
+                                                    acpi_thermal_dir);
+               if (!acpi_device_dir(device))
+                       return -ENODEV;
+-              acpi_device_dir(device)->owner = THIS_MODULE;
+       }
+       /* 'state' [R] */
+@@ -1875,7 +1874,6 @@ static int __init acpi_thermal_init(void)
+       acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
+       if (!acpi_thermal_dir)
+               return -ENODEV;
+-      acpi_thermal_dir->owner = THIS_MODULE;
+       result = acpi_bus_register_driver(&acpi_thermal_driver);
+       if (result < 0) {
+diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
+index bb5ed05..67cc36d 100644
+--- a/drivers/acpi/video.c
++++ b/drivers/acpi/video.c
+@@ -1125,8 +1125,6 @@ static int acpi_video_device_add_fs(struct acpi_device *device)
+       if (!device_dir)
+               return -ENOMEM;
+-      device_dir->owner = THIS_MODULE;
+-
+       /* 'info' [R] */
+       entry = proc_create_data("info", S_IRUGO, device_dir,
+                       &acpi_video_device_info_fops, acpi_driver_data(device));
+@@ -1403,8 +1401,6 @@ static int acpi_video_bus_add_fs(struct acpi_device *device)
+       if (!device_dir)
+               return -ENOMEM;
+-      device_dir->owner = THIS_MODULE;
+-
+       /* 'info' [R] */
+       entry = proc_create_data("info", S_IRUGO, device_dir,
+                                &acpi_video_bus_info_fops,
+@@ -2131,7 +2127,6 @@ static int __init acpi_video_init(void)
+       acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);
+       if (!acpi_video_dir)
+               return -ENODEV;
+-      acpi_video_dir->owner = THIS_MODULE;
+       result = acpi_bus_register_driver(&acpi_video_bus);
+       if (result < 0) {
+diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
+index 393ed67..8eddef3 100644
+--- a/drivers/block/ps3vram.c
++++ b/drivers/block/ps3vram.c
+@@ -551,8 +551,6 @@ static void __devinit ps3vram_proc_init(struct ps3_system_bus_device *dev)
+               dev_warn(&dev->core, "failed to create /proc entry\n");
+               return;
+       }
+-
+-      pde->owner = THIS_MODULE;
+       pde->data = priv;
+ }
+diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
+index 7a88dfd..e93fc8d 100644
+--- a/drivers/char/ipmi/ipmi_msghandler.c
++++ b/drivers/char/ipmi/ipmi_msghandler.c
+@@ -1944,7 +1944,7 @@ static int stat_file_read_proc(char *page, char **start, off_t off,
+ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
+                           read_proc_t *read_proc,
+-                          void *data, struct module *owner)
++                          void *data)
+ {
+       int                    rv = 0;
+ #ifdef CONFIG_PROC_FS
+@@ -1970,7 +1970,6 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
+       } else {
+               file->data = data;
+               file->read_proc = read_proc;
+-              file->owner = owner;
+               mutex_lock(&smi->proc_entry_lock);
+               /* Stick it on the list. */
+@@ -1993,23 +1992,21 @@ static int add_proc_entries(ipmi_smi_t smi, int num)
+       smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root);
+       if (!smi->proc_dir)
+               rv = -ENOMEM;
+-      else
+-              smi->proc_dir->owner = THIS_MODULE;
+       if (rv == 0)
+               rv = ipmi_smi_add_proc_entry(smi, "stats",
+                                            stat_file_read_proc,
+-                                           smi, THIS_MODULE);
++                                           smi);
+       if (rv == 0)
+               rv = ipmi_smi_add_proc_entry(smi, "ipmb",
+                                            ipmb_file_read_proc,
+-                                           smi, THIS_MODULE);
++                                           smi);
+       if (rv == 0)
+               rv = ipmi_smi_add_proc_entry(smi, "version",
+                                            version_file_read_proc,
+-                                           smi, THIS_MODULE);
++                                           smi);
+ #endif /* CONFIG_PROC_FS */
+       return rv;
+@@ -4265,7 +4262,6 @@ static int ipmi_init_msghandler(void)
+           return -ENOMEM;
+       }
+-      proc_ipmi_root->owner = THIS_MODULE;
+ #endif /* CONFIG_PROC_FS */
+       setup_timer(&ipmi_timer, ipmi_timeout, 0);
+diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
+index 3000135..e58ea4c 100644
+--- a/drivers/char/ipmi/ipmi_si_intf.c
++++ b/drivers/char/ipmi/ipmi_si_intf.c
+@@ -2899,7 +2899,7 @@ static int try_smi_init(struct smi_info *new_smi)
+       rv = ipmi_smi_add_proc_entry(new_smi->intf, "type",
+                                    type_file_read_proc,
+-                                   new_smi, THIS_MODULE);
++                                   new_smi);
+       if (rv) {
+               printk(KERN_ERR
+                      "ipmi_si: Unable to create proc entry: %d\n",
+@@ -2909,7 +2909,7 @@ static int try_smi_init(struct smi_info *new_smi)
+       rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats",
+                                    stat_file_read_proc,
+-                                   new_smi, THIS_MODULE);
++                                   new_smi);
+       if (rv) {
+               printk(KERN_ERR
+                      "ipmi_si: Unable to create proc entry: %d\n",
+@@ -2919,7 +2919,7 @@ static int try_smi_init(struct smi_info *new_smi)
+       rv = ipmi_smi_add_proc_entry(new_smi->intf, "params",
+                                    param_read_proc,
+-                                   new_smi, THIS_MODULE);
++                                   new_smi);
+       if (rv) {
+               printk(KERN_ERR
+                      "ipmi_si: Unable to create proc entry: %d\n",
+diff --git a/drivers/input/input.c b/drivers/input/input.c
+index 1730d73..ec3db3a 100644
+--- a/drivers/input/input.c
++++ b/drivers/input/input.c
+@@ -903,8 +903,6 @@ static int __init input_proc_init(void)
+       if (!proc_bus_input_dir)
+               return -ENOMEM;
+-      proc_bus_input_dir->owner = THIS_MODULE;
+-
+       entry = proc_create("devices", 0, proc_bus_input_dir,
+                           &input_devices_fileops);
+       if (!entry)
+diff --git a/drivers/isdn/hardware/eicon/divasi.c b/drivers/isdn/hardware/eicon/divasi.c
+index f4969fe..69e71eb 100644
+--- a/drivers/isdn/hardware/eicon/divasi.c
++++ b/drivers/isdn/hardware/eicon/divasi.c
+@@ -118,7 +118,6 @@ static int DIVA_INIT_FUNCTION create_um_idi_proc(void)
+               return (0);
+       um_idi_proc_entry->read_proc = um_idi_proc_read;
+-      um_idi_proc_entry->owner = THIS_MODULE;
+       return (1);
+ }
+diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
+index c3b0c8c..43ab0ad 100644
+--- a/drivers/media/video/cpia.c
++++ b/drivers/media/video/cpia.c
+@@ -1381,9 +1381,7 @@ static void proc_cpia_create(void)
+ {
+       cpia_proc_root = proc_mkdir("cpia", NULL);
+-      if (cpia_proc_root)
+-              cpia_proc_root->owner = THIS_MODULE;
+-      else
++      if (!cpia_proc_root)
+               LOG("Unable to initialise /proc/cpia\n");
+ }
+diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
+index 9a36b5a..7045c45 100644
+--- a/drivers/message/i2o/i2o_proc.c
++++ b/drivers/message/i2o/i2o_proc.c
+@@ -2037,8 +2037,6 @@ static int __init i2o_proc_fs_create(void)
+       if (!i2o_proc_dir_root)
+               return -1;
+-      i2o_proc_dir_root->owner = THIS_MODULE;
+-
+       list_for_each_entry(c, &i2o_controllers, list)
+           i2o_proc_iop_add(i2o_proc_dir_root, c);
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 9c326a5..99610f3 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -3444,25 +3444,12 @@ static void bond_remove_proc_entry(struct bonding *bond)
+  */
+ static void bond_create_proc_dir(void)
+ {
+-      int len = strlen(DRV_NAME);
+-
+-      for (bond_proc_dir = init_net.proc_net->subdir; bond_proc_dir;
+-           bond_proc_dir = bond_proc_dir->next) {
+-              if ((bond_proc_dir->namelen == len) &&
+-                  !memcmp(bond_proc_dir->name, DRV_NAME, len)) {
+-                      break;
+-              }
+-      }
+-
+       if (!bond_proc_dir) {
+               bond_proc_dir = proc_mkdir(DRV_NAME, init_net.proc_net);
+-              if (bond_proc_dir) {
+-                      bond_proc_dir->owner = THIS_MODULE;
+-              } else {
++              if (!bond_proc_dir)
+                       printk(KERN_WARNING DRV_NAME
+                               ": Warning: cannot create /proc/net/%s\n",
+                               DRV_NAME);
+-              }
+       }
+ }
+@@ -3471,25 +3458,7 @@ static void bond_create_proc_dir(void)
+  */
+ static void bond_destroy_proc_dir(void)
+ {
+-      struct proc_dir_entry *de;
+-
+-      if (!bond_proc_dir) {
+-              return;
+-      }
+-
+-      /* verify that the /proc dir is empty */
+-      for (de = bond_proc_dir->subdir; de; de = de->next) {
+-              /* ignore . and .. */
+-              if (*(de->name) != '.') {
+-                      break;
+-              }
+-      }
+-
+-      if (de) {
+-              if (bond_proc_dir->owner == THIS_MODULE) {
+-                      bond_proc_dir->owner = NULL;
+-              }
+-      } else {
++      if (bond_proc_dir) {
+               remove_proc_entry(DRV_NAME, init_net.proc_net);
+               bond_proc_dir = NULL;
+       }
+diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
+index 1243bc8..ac0e4b6 100644
+--- a/drivers/net/irda/vlsi_ir.c
++++ b/drivers/net/irda/vlsi_ir.c
+@@ -1871,13 +1871,6 @@ static int __init vlsi_mod_init(void)
+        * without procfs - it's not required for the driver to work.
+        */
+       vlsi_proc_root = proc_mkdir(PROC_DIR, NULL);
+-      if (vlsi_proc_root) {
+-              /* protect registered procdir against module removal.
+-               * Because we are in the module init path there's no race
+-               * window after create_proc_entry (and no barrier needed).
+-               */
+-              vlsi_proc_root->owner = THIS_MODULE;
+-      }
+       ret = pci_register_driver(&vlsi_irda_driver);
+diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
+index 7e80aba..31b1cc2 100644
+--- a/drivers/net/wireless/airo.c
++++ b/drivers/net/wireless/airo.c
+@@ -4494,7 +4494,6 @@ static int setup_proc_entry( struct net_device *dev,
+               goto fail;
+       apriv->proc_entry->uid = proc_uid;
+       apriv->proc_entry->gid = proc_gid;
+-      apriv->proc_entry->owner = THIS_MODULE;
+       /* Setup the StatsDelta */
+       entry = proc_create_data("StatsDelta",
+diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c
+index d63f26e..ba1f749 100644
+--- a/drivers/platform/x86/asus_acpi.c
++++ b/drivers/platform/x86/asus_acpi.c
+@@ -987,7 +987,6 @@ asus_proc_add(char *name, proc_writefunc *writefunc,
+       proc->write_proc = writefunc;
+       proc->read_proc = readfunc;
+       proc->data = acpi_driver_data(device);
+-      proc->owner = THIS_MODULE;
+       proc->uid = asus_uid;
+       proc->gid = asus_gid;
+       return 0;
+@@ -1020,7 +1019,6 @@ static int asus_hotk_add_fs(struct acpi_device *device)
+       if (proc) {
+               proc->read_proc = proc_read_info;
+               proc->data = acpi_driver_data(device);
+-              proc->owner = THIS_MODULE;
+               proc->uid = asus_uid;
+               proc->gid = asus_gid;
+       } else {
+@@ -1436,7 +1434,6 @@ static int __init asus_acpi_init(void)
+               printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n");
+               return -ENODEV;
+       }
+-      asus_proc_dir->owner = THIS_MODULE;
+       result = acpi_bus_register_driver(&asus_hotk_driver);
+       if (result < 0) {
+diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
+index d243320..3dad27a 100644
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -6992,7 +6992,6 @@ static int __init ibm_init(struct ibm_init_struct *iibm)
+                       ret = -ENODEV;
+                       goto err_out;
+               }
+-              entry->owner = THIS_MODULE;
+               entry->data = ibm;
+               entry->read_proc = &dispatch_procfs_read;
+               if (ibm->write)
+@@ -7405,7 +7404,6 @@ static int __init thinkpad_acpi_module_init(void)
+               thinkpad_acpi_module_exit();
+               return -ENODEV;
+       }
+-      proc_dir->owner = THIS_MODULE;
+       ret = platform_driver_register(&tpacpi_pdriver);
+       if (ret) {
+diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
+index 40e60fc..9f18726 100644
+--- a/drivers/platform/x86/toshiba_acpi.c
++++ b/drivers/platform/x86/toshiba_acpi.c
+@@ -679,8 +679,6 @@ static acpi_status __init add_device(void)
+                                             toshiba_proc_dir,
+                                             (read_proc_t *) dispatch_read,
+                                             item);
+-              if (proc)
+-                      proc->owner = THIS_MODULE;
+               if (proc && item->write_func)
+                       proc->write_proc = (write_proc_t *) dispatch_write;
+       }
+@@ -772,7 +770,6 @@ static int __init toshiba_acpi_init(void)
+               toshiba_acpi_exit();
+               return -ENODEV;
+       } else {
+-              toshiba_proc_dir->owner = THIS_MODULE;
+               status = add_device();
+               if (ACPI_FAILURE(status)) {
+                       toshiba_acpi_exit();
+diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c
+index 0c6257a..c086fc3 100644
+--- a/drivers/rtc/rtc-proc.c
++++ b/drivers/rtc/rtc-proc.c
+@@ -105,14 +105,8 @@ static const struct file_operations rtc_proc_fops = {
+ void rtc_proc_add_device(struct rtc_device *rtc)
+ {
+-      if (rtc->id == 0) {
+-              struct proc_dir_entry *ent;
+-
+-              ent = proc_create_data("driver/rtc", 0, NULL,
+-                                     &rtc_proc_fops, rtc);
+-              if (ent)
+-                      ent->owner = rtc->owner;
+-      }
++      if (rtc->id == 0)
++              proc_create_data("driver/rtc", 0, NULL, &rtc_proc_fops, rtc);
+ }
+ void rtc_proc_del_device(struct rtc_device *rtc)
+diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
+index 2080ba6..654daa3 100644
+--- a/drivers/s390/block/dasd_proc.c
++++ b/drivers/s390/block/dasd_proc.c
+@@ -320,7 +320,6 @@ dasd_proc_init(void)
+       dasd_proc_root_entry = proc_mkdir("dasd", NULL);
+       if (!dasd_proc_root_entry)
+               goto out_nodasd;
+-      dasd_proc_root_entry->owner = THIS_MODULE;
+       dasd_devices_entry = proc_create("devices",
+                                        S_IFREG | S_IRUGO | S_IWUSR,
+                                        dasd_proc_root_entry,
+@@ -334,7 +333,6 @@ dasd_proc_init(void)
+               goto out_nostatistics;
+       dasd_statistics_entry->read_proc = dasd_statistics_read;
+       dasd_statistics_entry->write_proc = dasd_statistics_write;
+-      dasd_statistics_entry->owner = THIS_MODULE;
+       return 0;
+  out_nostatistics:
+diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
+index 099b545..b134813 100644
+--- a/drivers/scsi/scsi_devinfo.c
++++ b/drivers/scsi/scsi_devinfo.c
+@@ -596,8 +596,6 @@ int __init scsi_init_devinfo(void)
+               error = -ENOMEM;
+               goto out;
+       }
+-
+-      p->owner = THIS_MODULE;
+ #endif /* CONFIG_SCSI_PROC_FS */
+  out:
+diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
+index 82f7b2d..77fbddb 100644
+--- a/drivers/scsi/scsi_proc.c
++++ b/drivers/scsi/scsi_proc.c
+@@ -115,8 +115,6 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht)
+               if (!sht->proc_dir)
+                       printk(KERN_ERR "%s: proc_mkdir failed for %s\n",
+                              __func__, sht->proc_name);
+-              else
+-                      sht->proc_dir->owner = sht->module;
+       }
+       mutex_unlock(&global_host_template_mutex);
+ }
+@@ -163,7 +161,6 @@ void scsi_proc_host_add(struct Scsi_Host *shost)
+       } 
+       p->write_proc = proc_scsi_write_proc;
+-      p->owner = sht->module;
+ }
+ /**
+diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
+index 37b433a..e327b84 100644
+--- a/drivers/video/via/viafbdev.c
++++ b/drivers/video/via/viafbdev.c
+@@ -2059,25 +2059,21 @@ static void viafb_init_proc(struct proc_dir_entry **viafb_entry)
+       if (viafb_entry) {
+               entry = create_proc_entry("dvp0", 0, *viafb_entry);
+               if (entry) {
+-                      entry->owner = THIS_MODULE;
+                       entry->read_proc = viafb_dvp0_proc_read;
+                       entry->write_proc = viafb_dvp0_proc_write;
+               }
+               entry = create_proc_entry("dvp1", 0, *viafb_entry);
+               if (entry) {
+-                      entry->owner = THIS_MODULE;
+                       entry->read_proc = viafb_dvp1_proc_read;
+                       entry->write_proc = viafb_dvp1_proc_write;
+               }
+               entry = create_proc_entry("dfph", 0, *viafb_entry);
+               if (entry) {
+-                      entry->owner = THIS_MODULE;
+                       entry->read_proc = viafb_dfph_proc_read;
+                       entry->write_proc = viafb_dfph_proc_write;
+               }
+               entry = create_proc_entry("dfpl", 0, *viafb_entry);
+               if (entry) {
+-                      entry->owner = THIS_MODULE;
+                       entry->read_proc = viafb_dfpl_proc_read;
+                       entry->write_proc = viafb_dfpl_proc_write;
+               }
+@@ -2086,7 +2082,6 @@ static void viafb_init_proc(struct proc_dir_entry **viafb_entry)
+                   viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
+                       entry = create_proc_entry("vt1636", 0, *viafb_entry);
+                       if (entry) {
+-                              entry->owner = THIS_MODULE;
+                               entry->read_proc = viafb_vt1636_proc_read;
+                               entry->write_proc = viafb_vt1636_proc_write;
+                       }
+diff --git a/fs/afs/proc.c b/fs/afs/proc.c
+index 7578c1a..8630615 100644
+--- a/fs/afs/proc.c
++++ b/fs/afs/proc.c
+@@ -146,7 +146,6 @@ int afs_proc_init(void)
+       proc_afs = proc_mkdir("fs/afs", NULL);
+       if (!proc_afs)
+               goto error_dir;
+-      proc_afs->owner = THIS_MODULE;
+       p = proc_create("cells", 0, proc_afs, &afs_proc_cells_fops);
+       if (!p)
+diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
+index 877e4d9..7f19fef 100644
+--- a/fs/cifs/cifs_debug.c
++++ b/fs/cifs/cifs_debug.c
+@@ -404,7 +404,6 @@ cifs_proc_init(void)
+       if (proc_fs_cifs == NULL)
+               return;
+-      proc_fs_cifs->owner = THIS_MODULE;
+       proc_create("DebugData", 0, proc_fs_cifs, &cifs_debug_data_proc_fops);
+ #ifdef CONFIG_CIFS_STATS
+diff --git a/fs/jfs/jfs_debug.c b/fs/jfs/jfs_debug.c
+index 6a73de8..dd824d9 100644
+--- a/fs/jfs/jfs_debug.c
++++ b/fs/jfs/jfs_debug.c
+@@ -90,7 +90,6 @@ void jfs_proc_init(void)
+       if (!(base = proc_mkdir("fs/jfs", NULL)))
+               return;
+-      base->owner = THIS_MODULE;
+       for (i = 0; i < NPROCENT; i++)
+               proc_create(Entries[i].name, 0, base, Entries[i].proc_fops);
+diff --git a/fs/nfs/client.c b/fs/nfs/client.c
+index 574158a..2277421 100644
+--- a/fs/nfs/client.c
++++ b/fs/nfs/client.c
+@@ -1606,8 +1606,6 @@ int __init nfs_fs_proc_init(void)
+       if (!proc_fs_nfs)
+               goto error_0;
+-      proc_fs_nfs->owner = THIS_MODULE;
+-
+       /* a file of servers with which we're dealing */
+       p = proc_create("servers", S_IFREG|S_IRUGO,
+                       proc_fs_nfs, &nfs_server_list_fops);
+diff --git a/fs/proc/inode.c b/fs/proc/inode.c
+index e11dc22..d78ade3 100644
+--- a/fs/proc/inode.c
++++ b/fs/proc/inode.c
+@@ -58,11 +58,8 @@ static void proc_delete_inode(struct inode *inode)
+       /* Let go of any associated proc directory entry */
+       de = PROC_I(inode)->pde;
+-      if (de) {
+-              if (de->owner)
+-                      module_put(de->owner);
++      if (de)
+               de_put(de);
+-      }
+       if (PROC_I(inode)->sysctl)
+               sysctl_head_put(PROC_I(inode)->sysctl);
+       clear_inode(inode);
+@@ -449,12 +446,9 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
+ {
+       struct inode * inode;
+-      if (!try_module_get(de->owner))
+-              goto out_mod;
+-
+       inode = iget_locked(sb, ino);
+       if (!inode)
+-              goto out_ino;
++              return NULL;
+       if (inode->i_state & I_NEW) {
+               inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+               PROC_I(inode)->fd = 0;
+@@ -485,16 +479,9 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
+                       }
+               }
+               unlock_new_inode(inode);
+-      } else {
+-             module_put(de->owner);
++      } else
+              de_put(de);
+-      }
+       return inode;
+-
+-out_ino:
+-      module_put(de->owner);
+-out_mod:
+-      return NULL;
+ }                     
+ int proc_fill_super(struct super_block *s)
+diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
+index d153946..4a9e0f6 100644
+--- a/fs/proc/proc_tty.c
++++ b/fs/proc/proc_tty.c
+@@ -152,7 +152,6 @@ void proc_tty_register_driver(struct tty_driver *driver)
+       if (!ent)
+               return;
+       ent->read_proc = driver->ops->read_proc;
+-      ent->owner = driver->owner;
+       ent->data = driver;
+       driver->proc_entry = ent;
+diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
+index d506640..9229e55 100644
+--- a/fs/reiserfs/procfs.c
++++ b/fs/reiserfs/procfs.c
+@@ -492,7 +492,6 @@ int reiserfs_proc_info_init(struct super_block *sb)
+       spin_lock_init(&__PINFO(sb).lock);
+       REISERFS_SB(sb)->procdir = proc_mkdir(b, proc_info_root);
+       if (REISERFS_SB(sb)->procdir) {
+-              REISERFS_SB(sb)->procdir->owner = THIS_MODULE;
+               REISERFS_SB(sb)->procdir->data = sb;
+               add_file(sb, "version", show_version);
+               add_file(sb, "super", show_super);
+@@ -556,9 +555,7 @@ int reiserfs_proc_info_global_init(void)
+ {
+       if (proc_info_root == NULL) {
+               proc_info_root = proc_mkdir(proc_info_root_name, NULL);
+-              if (proc_info_root) {
+-                      proc_info_root->owner = THIS_MODULE;
+-              } else {
++              if (!proc_info_root) {
+                       reiserfs_warning(NULL, "cannot create /proc/%s",
+                                        proc_info_root_name);
+                       return 1;
+diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
+index 62b7366..f7c9c75 100644
+--- a/include/linux/ipmi_smi.h
++++ b/include/linux/ipmi_smi.h
+@@ -230,6 +230,6 @@ static inline void ipmi_free_smi_msg(struct ipmi_smi_msg *msg)
+    automatically be dstroyed when the interface is destroyed. */
+ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
+                           read_proc_t *read_proc,
+-                          void *data, struct module *owner);
++                          void *data);
+ #endif /* __LINUX_IPMI_SMI_H */
+diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
+index b8bdb96..fbfa3d4 100644
+--- a/include/linux/proc_fs.h
++++ b/include/linux/proc_fs.h
+@@ -41,9 +41,6 @@ enum {
+  * while parent/subdir create the directory structure (every
+  * /proc file has a parent, but "subdir" is NULL for all
+  * non-directory entries).
+- *
+- * "owner" is used to protect module
+- * from unloading while proc_dir_entry is in use
+  */
+ typedef       int (read_proc_t)(char *page, char **start, off_t off,
+@@ -70,7 +67,6 @@ struct proc_dir_entry {
+        * somewhere.
+        */
+       const struct file_operations *proc_fops;
+-      struct module *owner;
+       struct proc_dir_entry *next, *parent, *subdir;
+       void *data;
+       read_proc_t *read_proc;
+diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c
+index 162199a..fd8e084 100644
+--- a/net/appletalk/atalk_proc.c
++++ b/net/appletalk/atalk_proc.c
+@@ -281,7 +281,6 @@ int __init atalk_proc_init(void)
+       atalk_proc_dir = proc_mkdir("atalk", init_net.proc_net);
+       if (!atalk_proc_dir)
+               goto out;
+-      atalk_proc_dir->owner = THIS_MODULE;
+       p = proc_create("interface", S_IRUGO, atalk_proc_dir,
+                       &atalk_seq_interface_fops);
+diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c
+index 4990541..1a0f5cc 100644
+--- a/net/atm/mpoa_proc.c
++++ b/net/atm/mpoa_proc.c
+@@ -281,7 +281,6 @@ int mpc_proc_init(void)
+               printk(KERN_ERR "Unable to initialize /proc/atm/%s\n", STAT_FILE_NAME);
+               return -ENOMEM;
+       }
+-      p->owner = THIS_MODULE;
+       return 0;
+ }
+diff --git a/net/atm/proc.c b/net/atm/proc.c
+index 49487b3..e7b3b27 100644
+--- a/net/atm/proc.c
++++ b/net/atm/proc.c
+@@ -476,7 +476,6 @@ int __init atm_proc_init(void)
+                                    atm_proc_root, e->proc_fops);
+               if (!dirent)
+                       goto err_out_remove;
+-              dirent->owner = THIS_MODULE;
+               e->dirent = dirent;
+       }
+       ret = 0;
+diff --git a/net/can/bcm.c b/net/can/bcm.c
+index b7c7d46..95d7f32 100644
+--- a/net/can/bcm.c
++++ b/net/can/bcm.c
+@@ -1604,10 +1604,6 @@ static int __init bcm_module_init(void)
+       /* create /proc/net/can-bcm directory */
+       proc_dir = proc_mkdir("can-bcm", init_net.proc_net);
+-
+-      if (proc_dir)
+-              proc_dir->owner = THIS_MODULE;
+-
+       return 0;
+ }
+diff --git a/net/can/proc.c b/net/can/proc.c
+index 520fef5..1463653 100644
+--- a/net/can/proc.c
++++ b/net/can/proc.c
+@@ -473,8 +473,6 @@ void can_init_proc(void)
+               return;
+       }
+-      can_dir->owner = THIS_MODULE;
+-
+       /* own procfs entries from the AF_CAN core */
+       pde_version     = can_create_proc_readentry(CAN_PROC_VERSION, 0644,
+                                       can_proc_read_version, NULL);
+diff --git a/net/core/pktgen.c b/net/core/pktgen.c
+index 32d419f..3779c14 100644
+--- a/net/core/pktgen.c
++++ b/net/core/pktgen.c
+@@ -3806,7 +3806,6 @@ static int __init pg_init(void)
+       pg_proc_dir = proc_mkdir(PG_PROC_DIR, init_net.proc_net);
+       if (!pg_proc_dir)
+               return -ENODEV;
+-      pg_proc_dir->owner = THIS_MODULE;
+       pe = proc_create(PGCTRL, 0600, pg_proc_dir, &pktgen_fops);
+       if (pe == NULL) {
+diff --git a/net/irda/irproc.c b/net/irda/irproc.c
+index 88e80a3..8ff1861 100644
+--- a/net/irda/irproc.c
++++ b/net/irda/irproc.c
+@@ -70,7 +70,6 @@ void __init irda_proc_register(void)
+       proc_irda = proc_mkdir("irda", init_net.proc_net);
+       if (proc_irda == NULL)
+               return;
+-      proc_irda->owner = THIS_MODULE;
+       for (i = 0; i < ARRAY_SIZE(irda_dirs); i++)
+               d = proc_create(irda_dirs[i].name, 0, proc_irda,
+diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c
+index b58bd7c..d208b33 100644
+--- a/net/llc/llc_proc.c
++++ b/net/llc/llc_proc.c
+@@ -236,7 +236,6 @@ int __init llc_proc_init(void)
+       llc_proc_dir = proc_mkdir("llc", init_net.proc_net);
+       if (!llc_proc_dir)
+               goto out;
+-      llc_proc_dir->owner = THIS_MODULE;
+       p = proc_create("socket", S_IRUGO, llc_proc_dir, &llc_seq_socket_fops);
+       if (!p)
+diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
+index cb198af..8eb3e61 100644
+--- a/net/sctp/protocol.c
++++ b/net/sctp/protocol.c
+@@ -106,12 +106,8 @@ static __init int sctp_proc_init(void)
+               goto out_nomem;
+ #ifdef CONFIG_PROC_FS
+       if (!proc_net_sctp) {
+-              struct proc_dir_entry *ent;
+-              ent = proc_mkdir("sctp", init_net.proc_net);
+-              if (ent) {
+-                      ent->owner = THIS_MODULE;
+-                      proc_net_sctp = ent;
+-              } else
++              proc_net_sctp = proc_mkdir("sctp", init_net.proc_net);
++              if (!proc_net_sctp)
+                       goto out_free_percpu;
+       }
+diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
+index 4735caa..20029a7 100644
+--- a/net/sunrpc/cache.c
++++ b/net/sunrpc/cache.c
+@@ -313,7 +313,6 @@ static int create_cache_proc_entries(struct cache_detail *cd)
+       cd->proc_ent = proc_mkdir(cd->name, proc_net_rpc);
+       if (cd->proc_ent == NULL)
+               goto out_nomem;
+-      cd->proc_ent->owner = cd->owner;
+       cd->channel_ent = cd->content_ent = NULL;
+       p = proc_create_data("flush", S_IFREG|S_IRUSR|S_IWUSR,
+@@ -321,7 +320,6 @@ static int create_cache_proc_entries(struct cache_detail *cd)
+       cd->flush_ent = p;
+       if (p == NULL)
+               goto out_nomem;
+-      p->owner = cd->owner;
+       if (cd->cache_request || cd->cache_parse) {
+               p = proc_create_data("channel", S_IFREG|S_IRUSR|S_IWUSR,
+@@ -329,7 +327,6 @@ static int create_cache_proc_entries(struct cache_detail *cd)
+               cd->channel_ent = p;
+               if (p == NULL)
+                       goto out_nomem;
+-              p->owner = cd->owner;
+       }
+       if (cd->cache_show) {
+               p = proc_create_data("content", S_IFREG|S_IRUSR|S_IWUSR,
+@@ -337,7 +334,6 @@ static int create_cache_proc_entries(struct cache_detail *cd)
+               cd->content_ent = p;
+               if (p == NULL)
+                       goto out_nomem;
+-              p->owner = cd->owner;
+       }
+       return 0;
+ out_nomem:
+diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
+index 085372e..1ef6e46 100644
+--- a/net/sunrpc/stats.c
++++ b/net/sunrpc/stats.c
+@@ -262,14 +262,8 @@ void
+ rpc_proc_init(void)
+ {
+       dprintk("RPC:       registering /proc/net/rpc\n");
+-      if (!proc_net_rpc) {
+-              struct proc_dir_entry *ent;
+-              ent = proc_mkdir("rpc", init_net.proc_net);
+-              if (ent) {
+-                      ent->owner = THIS_MODULE;
+-                      proc_net_rpc = ent;
+-              }
+-      }
++      if (!proc_net_rpc)
++              proc_net_rpc = proc_mkdir("rpc", init_net.proc_net);
+ }
+ void
+diff --git a/sound/core/info.c b/sound/core/info.c
+index 70fa871..35df614 100644
+--- a/sound/core/info.c
++++ b/sound/core/info.c
+@@ -154,11 +154,6 @@ EXPORT_SYMBOL(snd_seq_root);
+ struct snd_info_entry *snd_oss_root;
+ #endif
+-static inline void snd_info_entry_prepare(struct proc_dir_entry *de)
+-{
+-      de->owner = THIS_MODULE;
+-}
+-
+ static void snd_remove_proc_entry(struct proc_dir_entry *parent,
+                                 struct proc_dir_entry *de)
+ {
+@@ -522,32 +517,11 @@ static const struct file_operations snd_info_entry_operations =
+       .release =              snd_info_entry_release,
+ };
+-/**
+- * snd_create_proc_entry - create a procfs entry
+- * @name: the name of the proc file
+- * @mode: the file permission bits, S_Ixxx
+- * @parent: the parent proc-directory entry
+- *
+- * Creates a new proc file entry with the given name and permission
+- * on the given directory.
+- *
+- * Returns the pointer of new instance or NULL on failure.
+- */
+-static struct proc_dir_entry *snd_create_proc_entry(const char *name, mode_t mode,
+-                                                  struct proc_dir_entry *parent)
+-{
+-      struct proc_dir_entry *p;
+-      p = create_proc_entry(name, mode, parent);
+-      if (p)
+-              snd_info_entry_prepare(p);
+-      return p;
+-}
+-
+ int __init snd_info_init(void)
+ {
+       struct proc_dir_entry *p;
+-      p = snd_create_proc_entry("asound", S_IFDIR | S_IRUGO | S_IXUGO, NULL);
++      p = create_proc_entry("asound", S_IFDIR | S_IRUGO | S_IXUGO, NULL);
+       if (p == NULL)
+               return -ENOMEM;
+       snd_proc_root = p;
+@@ -974,12 +948,11 @@ int snd_info_register(struct snd_info_entry * entry)
+               return -ENXIO;
+       root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
+       mutex_lock(&info_mutex);
+-      p = snd_create_proc_entry(entry->name, entry->mode, root);
++      p = create_proc_entry(entry->name, entry->mode, root);
+       if (!p) {
+               mutex_unlock(&info_mutex);
+               return -ENOMEM;
+       }
+-      p->owner = entry->module;
+       if (!S_ISDIR(entry->mode))
+               p->proc_fops = &snd_info_entry_operations;
+       p->size = entry->size;
+-- 
+1.6.2.1
+
diff --git a/releases/upstream/2.6.30-rc1/0003-thinkpad-acpi-update-copyright-notices.patch b/releases/upstream/2.6.30-rc1/0003-thinkpad-acpi-update-copyright-notices.patch
new file mode 100644 (file)
index 0000000..1bdaa8b
--- /dev/null
@@ -0,0 +1,29 @@
+From 1c762ca438447fa3525d84f4a0784a2021a66200 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Sat, 4 Apr 2009 04:25:42 +0000
+Subject: thinkpad-acpi: update copyright notices
+
+It is that time of the year again...
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ drivers/platform/x86/thinkpad_acpi.c |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
+index d243320..792d22e 100644
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -3,7 +3,7 @@
+  *
+  *
+  *  Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.net>
+- *  Copyright (C) 2006-2008 Henrique de Moraes Holschuh <hmh@hmh.eng.br>
++ *  Copyright (C) 2006-2009 Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+  *
+  *  This program is free software; you can redistribute it and/or modify
+  *  it under the terms of the GNU General Public License as published by
+-- 
+1.6.2.1
+
diff --git a/releases/upstream/2.6.30-rc1/0004-thinkpad-acpi-drop-ibm-acpi-alias.patch b/releases/upstream/2.6.30-rc1/0004-thinkpad-acpi-drop-ibm-acpi-alias.patch
new file mode 100644 (file)
index 0000000..38c210e
--- /dev/null
@@ -0,0 +1,32 @@
+From 257bc1cb3e29c8da62b9c9e0a4505011776c7040 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Sat, 4 Apr 2009 04:25:43 +0000
+Subject: thinkpad-acpi: drop ibm-acpi alias
+
+The driver was renamed two years ago, on 2.6.21.  Drop the old
+compatibility alias, we have given everybody quite enough time
+to update their configs to the new name.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ drivers/platform/x86/thinkpad_acpi.c |    3 ---
+ 1 files changed, 0 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
+index 792d22e..c83ec94 100644
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -7517,9 +7517,6 @@ static int __init thinkpad_acpi_module_init(void)
+       return 0;
+ }
+-/* Please remove this in year 2009 */
+-MODULE_ALIAS("ibm_acpi");
+-
+ MODULE_ALIAS(TPACPI_DRVR_SHORTNAME);
+ /*
+-- 
+1.6.2.1
+
diff --git a/releases/upstream/2.6.30-rc1/0005-thinkpad-acpi-documentation-cleanup.patch b/releases/upstream/2.6.30-rc1/0005-thinkpad-acpi-documentation-cleanup.patch
new file mode 100644 (file)
index 0000000..1c6c4ad
--- /dev/null
@@ -0,0 +1,301 @@
+From 078ac19ed8f476a7c2d729712e15f5ab516ff491 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Sat, 4 Apr 2009 04:25:44 +0000
+Subject: thinkpad-acpi: documentation cleanup
+
+Some cleanups to the documentation of the driver.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ Documentation/laptops/thinkpad-acpi.txt |   76 +++++++++++++++++++++----------
+ 1 files changed, 52 insertions(+), 24 deletions(-)
+
+diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
+index 41bc99f..f6e6bc6 100644
+--- a/Documentation/laptops/thinkpad-acpi.txt
++++ b/Documentation/laptops/thinkpad-acpi.txt
+@@ -20,7 +20,8 @@ moved to the drivers/misc tree and renamed to thinkpad-acpi for kernel
+ kernel 2.6.29 and release 0.22.
+ The driver is named "thinkpad-acpi".  In some places, like module
+-names, "thinkpad_acpi" is used because of userspace issues.
++names and log messages, "thinkpad_acpi" is used because of userspace
++issues.
+ "tpacpi" is used as a shorthand where "thinkpad-acpi" would be too
+ long due to length limitations on some Linux kernel versions.
+@@ -37,7 +38,7 @@ detailed description):
+       - ThinkLight on and off
+       - limited docking and undocking
+       - UltraBay eject
+-      - CMOS control
++      - CMOS/UCMS control
+       - LED control
+       - ACPI sounds
+       - temperature sensors
+@@ -46,6 +47,7 @@ detailed description):
+       - Volume control
+       - Fan control and monitoring: fan speed, fan enable/disable
+       - WAN enable and disable
++      - UWB enable and disable
+ A compatibility table by model and feature is maintained on the web
+ site, http://ibm-acpi.sf.net/. I appreciate any success or failure
+@@ -53,7 +55,7 @@ reports, especially if they add to or correct the compatibility table.
+ Please include the following information in your report:
+       - ThinkPad model name
+-      - a copy of your DSDT, from /proc/acpi/dsdt
++      - a copy of your ACPI tables, using the "acpidump" utility
+       - a copy of the output of dmidecode, with serial numbers
+         and UUIDs masked off
+       - which driver features work and which don't
+@@ -66,17 +68,18 @@ Installation
+ ------------
+ If you are compiling this driver as included in the Linux kernel
+-sources, simply enable the CONFIG_THINKPAD_ACPI option, and optionally
+-enable the CONFIG_THINKPAD_ACPI_BAY option if you want the
+-thinkpad-specific bay functionality.
++sources, look for the CONFIG_THINKPAD_ACPI Kconfig option.
++It is located on the menu path: "Device Drivers" -> "X86 Platform
++Specific Device Drivers" -> "ThinkPad ACPI Laptop Extras".
++
+ Features
+ --------
+ The driver exports two different interfaces to userspace, which can be
+ used to access the features it provides.  One is a legacy procfs-based
+-interface, which will be removed at some time in the distant future.
+-The other is a new sysfs-based interface which is not complete yet.
++interface, which will be removed at some time in the future.  The other
++is a new sysfs-based interface which is not complete yet.
+ The procfs interface creates the /proc/acpi/ibm directory.  There is a
+ file under that directory for each feature it supports.  The procfs
+@@ -111,15 +114,17 @@ The version of thinkpad-acpi's sysfs interface is exported by the driver
+ as a driver attribute (see below).
+ Sysfs driver attributes are on the driver's sysfs attribute space,
+-for 2.6.23 this is /sys/bus/platform/drivers/thinkpad_acpi/ and
++for 2.6.23+ this is /sys/bus/platform/drivers/thinkpad_acpi/ and
+ /sys/bus/platform/drivers/thinkpad_hwmon/
+ Sysfs device attributes are on the thinkpad_acpi device sysfs attribute
+-space, for 2.6.23 this is /sys/devices/platform/thinkpad_acpi/.
++space, for 2.6.23+ this is /sys/devices/platform/thinkpad_acpi/.
+ Sysfs device attributes for the sensors and fan are on the
+ thinkpad_hwmon device's sysfs attribute space, but you should locate it
+-looking for a hwmon device with the name attribute of "thinkpad".
++looking for a hwmon device with the name attribute of "thinkpad", or
++better yet, through libsensors.
++
+ Driver version
+ --------------
+@@ -129,6 +134,7 @@ sysfs driver attribute: version
+ The driver name and version. No commands can be written to this file.
++
+ Sysfs interface version
+ -----------------------
+@@ -160,6 +166,7 @@ expect that an attribute might not be there, and deal with it properly
+ (an attribute not being there *is* a valid way to make it clear that a
+ feature is not available in sysfs).
++
+ Hot keys
+ --------
+@@ -618,6 +625,7 @@ For Lenovo models *with* ACPI backlight control:
+    and map them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN.  Process
+    these keys on userspace somehow (e.g. by calling xbacklight).
++
+ Bluetooth
+ ---------
+@@ -628,6 +636,9 @@ 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.
++If the ThinkPad supports it, the Bluetooth state is stored in NVRAM,
++so it is kept across reboots and power-off.
++
+ Procfs notes:
+ If Bluetooth is installed, the following commands can be used:
+@@ -652,6 +663,7 @@ Sysfs notes:
+       rfkill controller switch "tpacpi_bluetooth_sw": refer to
+       Documentation/rfkill.txt for details.
++
+ Video output control -- /proc/acpi/ibm/video
+ --------------------------------------------
+@@ -693,11 +705,8 @@ Fn-F7 from working. This also disables the video output switching
+ features of this driver, as it uses the same ACPI methods as
+ Fn-F7. Video switching on the console should still work.
+-UPDATE: There's now a patch for the X.org Radeon driver which
+-addresses this issue. Some people are reporting success with the patch
+-while others are still having problems. For more information:
++UPDATE: refer to https://bugs.freedesktop.org/show_bug.cgi?id=2000
+-https://bugs.freedesktop.org/show_bug.cgi?id=2000
+ ThinkLight control
+ ------------------
+@@ -720,10 +729,11 @@ The ThinkLight sysfs interface is documented by the LED class
+ documentation, in Documentation/leds-class.txt.  The ThinkLight LED name
+ is "tpacpi::thinklight".
+-Due to limitations in the sysfs LED class, if the status of the thinklight
++Due to limitations in the sysfs LED class, if the status of the ThinkLight
+ cannot be read or if it is unknown, thinkpad-acpi will report it as "off".
+ It is impossible to know if the status returned through sysfs is valid.
++
+ Docking / undocking -- /proc/acpi/ibm/dock
+ ------------------------------------------
+@@ -784,6 +794,7 @@ the only docking stations currently supported are the X-series
+ UltraBase docks and "dumb" port replicators like the Mini Dock (the
+ latter don't need any ACPI support, actually).
++
+ UltraBay eject -- /proc/acpi/ibm/bay
+ ------------------------------------
+@@ -847,8 +858,9 @@ supported. Use "eject2" instead of "eject" for the second bay.
+ Note: the UltraBay eject support on the 600e/x, A22p and A3x is
+ EXPERIMENTAL and may not work as expected. USE WITH CAUTION!
+-CMOS control
+-------------
++
++CMOS/UCMS control
++-----------------
+ procfs: /proc/acpi/ibm/cmos
+ sysfs device attribute: cmos_command
+@@ -882,6 +894,7 @@ The cmos command interface is prone to firmware split-brain problems, as
+ in newer ThinkPads it is just a compatibility layer.  Do not use it, it is
+ exported just as a debug tool.
++
+ LED control
+ -----------
+@@ -939,6 +952,7 @@ ThinkPad indicator LED should blink in hardware accelerated mode, use the
+ "timer" trigger, and leave the delay_on and delay_off parameters set to
+ zero (to request hardware acceleration autodetection).
++
+ ACPI sounds -- /proc/acpi/ibm/beep
+ ----------------------------------
+@@ -968,6 +982,7 @@ X40:
+       16 - one medium-pitched beep repeating constantly, stop with 17
+       17 - stop 16
++
+ Temperature sensors
+ -------------------
+@@ -1115,6 +1130,7 @@ registers contain the current battery capacity, etc. If you experiment
+ with this, do send me your results (including some complete dumps with
+ a description of the conditions when they were taken.)
++
+ LCD brightness control
+ ----------------------
+@@ -1124,10 +1140,9 @@ sysfs backlight device "thinkpad_screen"
+ This feature allows software control of the LCD brightness on ThinkPad
+ models which don't have a hardware brightness slider.
+-It has some limitations: the LCD backlight cannot be actually turned on or
+-off by this interface, and in many ThinkPad models, the "dim while on
+-battery" functionality will be enabled by the BIOS when this interface is
+-used, and cannot be controlled.
++It has some limitations: the LCD backlight cannot be actually turned
++on or off by this interface, it just controls the backlight brightness
++level.
+ On IBM (and some of the earlier Lenovo) ThinkPads, the backlight control
+ has eight brightness levels, ranging from 0 to 7.  Some of the levels
+@@ -1201,6 +1216,7 @@ WARNING:
+     and maybe reduce the life of the backlight lamps by needlessly kicking
+     its level up and down at every change.
++
+ Volume control -- /proc/acpi/ibm/volume
+ ---------------------------------------
+@@ -1217,6 +1233,11 @@ distinct. The unmute the volume after the mute command, use either the
+ up or down command (the level command will not unmute the volume).
+ The current volume level and mute state is shown in the file.
++The ALSA mixer interface to this feature is still missing, but patches
++to add it exist.  That problem should be addressed in the not so
++distant future.
++
++
+ Fan control and monitoring: fan speed, fan enable/disable
+ ---------------------------------------------------------
+@@ -1383,8 +1404,11 @@ procfs: /proc/acpi/ibm/wan
+ sysfs device attribute: wwan_enable (deprecated)
+ sysfs rfkill class: switch "tpacpi_wwan_sw"
+-This feature shows the presence and current state of a W-WAN (Sierra
+-Wireless EV-DO) device.
++This feature shows the presence and current state of the built-in
++Wireless WAN device.
++
++If the ThinkPad supports it, the WWAN state is stored in NVRAM,
++so it is kept across reboots and power-off.
+ It was tested on a Lenovo ThinkPad X60. It should probably work on other
+ ThinkPad models which come with this module installed.
+@@ -1413,6 +1437,7 @@ Sysfs notes:
+       rfkill controller switch "tpacpi_wwan_sw": refer to
+       Documentation/rfkill.txt for details.
++
+ EXPERIMENTAL: UWB
+ -----------------
+@@ -1431,6 +1456,7 @@ Sysfs notes:
+       rfkill controller switch "tpacpi_uwb_sw": refer to
+       Documentation/rfkill.txt for details.
++
+ Multiple Commands, Module Parameters
+ ------------------------------------
+@@ -1445,6 +1471,7 @@ for example:
+       modprobe thinkpad_acpi hotkey=enable,0xffff video=auto_disable
++
+ Enabling debugging output
+ -------------------------
+@@ -1467,6 +1494,7 @@ The level of debugging information output by the driver can be changed
+ at runtime through sysfs, using the driver attribute debug_level.  The
+ attribute takes the same bitmask as the debug module parameter above.
++
+ Force loading of module
+ -----------------------
+-- 
+1.6.2.1
+
diff --git a/releases/upstream/2.6.30-rc1/0006-thinkpad-acpi-cleanup-debug-helpers.patch b/releases/upstream/2.6.30-rc1/0006-thinkpad-acpi-cleanup-debug-helpers.patch
new file mode 100644 (file)
index 0000000..4ad4759
--- /dev/null
@@ -0,0 +1,68 @@
+From 3dcc2c3b00cad01a0e3667607f8644e891e4dc8b Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Sat, 4 Apr 2009 04:25:45 +0000
+Subject: thinkpad-acpi: cleanup debug helpers
+
+Fix the vdbg_printk macro definition to be sane when
+CONFIG_THINKPAD_ACPI_DEBUG is undefined, and move the mess into a file
+section of its own.
+
+This doesn't change anything in the current code, but future code will
+need the proper behaviour.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ drivers/platform/x86/thinkpad_acpi.c |   29 ++++++++++++++++++-----------
+ 1 files changed, 18 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
+index c83ec94..3367df9 100644
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -184,17 +184,6 @@ enum {
+ #define TPACPI_DBG_ALL                0xffff
+ #define TPACPI_DBG_INIT               0x0001
+ #define TPACPI_DBG_EXIT               0x0002
+-#define dbg_printk(a_dbg_level, format, arg...) \
+-      do { if (dbg_level & a_dbg_level) \
+-              printk(TPACPI_DEBUG "%s: " format, __func__ , ## arg); \
+-      } while (0)
+-#ifdef CONFIG_THINKPAD_ACPI_DEBUG
+-#define vdbg_printk(a_dbg_level, format, arg...) \
+-      dbg_printk(a_dbg_level, format, ## arg)
+-static const char *str_supported(int is_supported);
+-#else
+-#define vdbg_printk(a_dbg_level, format, arg...)
+-#endif
+ #define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off")
+ #define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
+@@ -326,6 +315,24 @@ static int tpacpi_uwb_emulstate;
+ #endif
++/*************************************************************************
++ *  Debugging helpers
++ */
++
++#define dbg_printk(a_dbg_level, format, arg...) \
++      do { if (dbg_level & (a_dbg_level)) \
++              printk(TPACPI_DEBUG "%s: " format, __func__ , ## arg); \
++      } while (0)
++
++#ifdef CONFIG_THINKPAD_ACPI_DEBUG
++#define vdbg_printk dbg_printk
++static const char *str_supported(int is_supported);
++#else
++#define vdbg_printk(a_dbg_level, format, arg...) \
++      do { } while (0)
++#endif
++
++
+ /****************************************************************************
+  ****************************************************************************
+  *
+-- 
+1.6.2.1
+
diff --git a/releases/upstream/2.6.30-rc1/0007-thinkpad-acpi-add-missing-log-levels.patch b/releases/upstream/2.6.30-rc1/0007-thinkpad-acpi-add-missing-log-levels.patch
new file mode 100644 (file)
index 0000000..af07bb2
--- /dev/null
@@ -0,0 +1,49 @@
+From 7ff8d62f7f055aaffbeb493863136c1b876bbe2e Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Sat, 4 Apr 2009 04:25:46 +0000
+Subject: thinkpad-acpi: add missing log levels
+
+Add missing log levels in a standalone commit, to avoid dependencies in
+future unrelated changes, just because they wanted to use one of the
+missing log levels.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ drivers/platform/x86/thinkpad_acpi.c |   19 +++++++++++--------
+ 1 files changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
+index 3367df9..6331b88 100644
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -172,15 +172,18 @@ enum {
+       TPACPI_RFK_UWB_SW_ID,
+ };
+-/* Debugging */
++/* printk headers */
+ #define TPACPI_LOG TPACPI_FILE ": "
+-#define TPACPI_ALERT  KERN_ALERT  TPACPI_LOG
+-#define TPACPI_CRIT   KERN_CRIT   TPACPI_LOG
+-#define TPACPI_ERR    KERN_ERR    TPACPI_LOG
+-#define TPACPI_NOTICE KERN_NOTICE TPACPI_LOG
+-#define TPACPI_INFO   KERN_INFO   TPACPI_LOG
+-#define TPACPI_DEBUG  KERN_DEBUG  TPACPI_LOG
+-
++#define TPACPI_EMERG  KERN_EMERG      TPACPI_LOG
++#define TPACPI_ALERT  KERN_ALERT      TPACPI_LOG
++#define TPACPI_CRIT   KERN_CRIT       TPACPI_LOG
++#define TPACPI_ERR    KERN_ERR        TPACPI_LOG
++#define TPACPI_WARN   KERN_WARNING    TPACPI_LOG
++#define TPACPI_NOTICE KERN_NOTICE     TPACPI_LOG
++#define TPACPI_INFO   KERN_INFO       TPACPI_LOG
++#define TPACPI_DEBUG  KERN_DEBUG      TPACPI_LOG
++
++/* Debugging printk groups */
+ #define TPACPI_DBG_ALL                0xffff
+ #define TPACPI_DBG_INIT               0x0001
+ #define TPACPI_DBG_EXIT               0x0002
+-- 
+1.6.2.1
+
diff --git a/releases/upstream/2.6.30-rc1/0008-thinkpad-acpi-add-new-debug-helpers-and-warn-of-dep.patch b/releases/upstream/2.6.30-rc1/0008-thinkpad-acpi-add-new-debug-helpers-and-warn-of-dep.patch
new file mode 100644 (file)
index 0000000..76a8891
--- /dev/null
@@ -0,0 +1,139 @@
+From 73a94d86a8625371f76de0ee12dc5bacd3ed42c0 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Sat, 4 Apr 2009 04:25:47 +0000
+Subject: thinkpad-acpi: add new debug helpers and warn of deprecated atts
+
+Add a debug helper that discloses the TGID of the userspace task
+attempting to access the driver.  This is highly useful when dealing
+with bug reports, since often the user has no idea that some userspace
+application is accessing thinkpad-acpi...
+
+Also add a helper to log warnings about sysfs attributes that are
+deprecated.
+
+Use the new helpers to issue deprecation warnings for bluetooth_enable
+and wwan_enabled, that have been deprecated for a while, now.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ Documentation/laptops/thinkpad-acpi.txt |    2 +
+ drivers/platform/x86/thinkpad_acpi.c    |   40 +++++++++++++++++++++++++++++++
+ 2 files changed, 42 insertions(+), 0 deletions(-)
+
+diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
+index f6e6bc6..e8f52fb 100644
+--- a/Documentation/laptops/thinkpad-acpi.txt
++++ b/Documentation/laptops/thinkpad-acpi.txt
+@@ -1484,6 +1484,8 @@ will enable all debugging output classes.  It takes a bitmask, so
+ to enable more than one output class, just add their values.
+       Debug bitmask           Description
++      0x8000                  Disclose PID of userspace programs
++                              accessing some functions of the driver
+       0x0001                  Initialization and probing
+       0x0002                  Removal
+diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
+index 6331b88..852be7c 100644
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -54,6 +54,7 @@
+ #include <linux/string.h>
+ #include <linux/list.h>
+ #include <linux/mutex.h>
++#include <linux/sched.h>
+ #include <linux/kthread.h>
+ #include <linux/freezer.h>
+ #include <linux/delay.h>
+@@ -185,6 +186,7 @@ enum {
+ /* Debugging printk groups */
+ #define TPACPI_DBG_ALL                0xffff
++#define TPACPI_DBG_DISCLOSETASK       0x8000
+ #define TPACPI_DBG_INIT               0x0001
+ #define TPACPI_DBG_EXIT               0x0002
+@@ -335,6 +337,21 @@ static const char *str_supported(int is_supported);
+       do { } while (0)
+ #endif
++static void tpacpi_log_usertask(const char * const what)
++{
++      printk(TPACPI_DEBUG "%s: access by process with PID %d\n",
++              what, task_tgid_vnr(current));
++}
++
++#define tpacpi_disclose_usertask(what, format, arg...) \
++      do { \
++              if (unlikely( \
++                  (dbg_level & TPACPI_DBG_DISCLOSETASK) && \
++                  (tpacpi_lifecycle == TPACPI_LIFE_RUNNING))) { \
++                      printk(TPACPI_DEBUG "%s: PID %d: " format, \
++                              what, task_tgid_vnr(current), ## arg); \
++              } \
++      } while (0)
+ /****************************************************************************
+  ****************************************************************************
+@@ -1030,6 +1047,21 @@ static int __init tpacpi_new_rfkill(const unsigned int id,
+       return 0;
+ }
++static void printk_deprecated_attribute(const char * const what,
++                                      const char * const details)
++{
++      tpacpi_log_usertask("deprecated sysfs attribute");
++      printk(TPACPI_WARN "WARNING: sysfs attribute %s is deprecated and "
++              "will be removed. %s\n",
++              what, details);
++}
++
++static void printk_deprecated_rfkill_attribute(const char * const what)
++{
++      printk_deprecated_attribute(what,
++                      "Please switch to generic rfkill before year 2010");
++}
++
+ /*************************************************************************
+  * thinkpad-acpi driver attributes
+  */
+@@ -3070,6 +3102,8 @@ static ssize_t bluetooth_enable_show(struct device *dev,
+ {
+       int status;
++      printk_deprecated_rfkill_attribute("bluetooth_enable");
++
+       status = bluetooth_get_radiosw();
+       if (status < 0)
+               return status;
+@@ -3085,6 +3119,8 @@ static ssize_t bluetooth_enable_store(struct device *dev,
+       unsigned long t;
+       int res;
++      printk_deprecated_rfkill_attribute("bluetooth_enable");
++
+       if (parse_strtoul(buf, 1, &t))
+               return -EINVAL;
+@@ -3347,6 +3383,8 @@ static ssize_t wan_enable_show(struct device *dev,
+ {
+       int status;
++      printk_deprecated_rfkill_attribute("wwan_enable");
++
+       status = wan_get_radiosw();
+       if (status < 0)
+               return status;
+@@ -3362,6 +3400,8 @@ static ssize_t wan_enable_store(struct device *dev,
+       unsigned long t;
+       int res;
++      printk_deprecated_rfkill_attribute("wwan_enable");
++
+       if (parse_strtoul(buf, 1, &t))
+               return -EINVAL;
+-- 
+1.6.2.1
+
diff --git a/releases/upstream/2.6.30-rc1/0009-thinkpad-acpi-remove-HKEY-disable-functionality.patch b/releases/upstream/2.6.30-rc1/0009-thinkpad-acpi-remove-HKEY-disable-functionality.patch
new file mode 100644 (file)
index 0000000..27ecd40
--- /dev/null
@@ -0,0 +1,271 @@
+From 2586d5663d0a17d69383acf6110f16a979a07c4e Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Sat, 4 Apr 2009 04:25:48 +0000
+Subject: thinkpad-acpi: remove HKEY disable functionality
+
+The HKEY disable functionality basically cripples the entire event
+model of the ThinkPad firmware and of the thinkpad-acpi driver.
+Remove this functionality from the driver.  HKEY must be enabled at
+all times while thinkpad-acpi is loaded, and disabled otherwise.
+
+For sysfs, according to the sysfs ABI and the thinkpad-acpi sysfs
+rules of engagement, we will just remove the attributes.  This will be
+done in two stages: disable their function now, after two kernel
+releases, remove the attributes.
+
+For procfs, we call WARN().  If nothing triggers it, I will simply
+remove the enable/disable commands entirely in the future along with
+the sysfs attributes.
+
+I don't expect much, if any fallout from this.  There really isn't any
+reason to mess with hotkey_enable or with the enable/disable commands
+to /proc/acpi/ibm/hotkey, and this has been true for years...
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ Documentation/laptops/thinkpad-acpi.txt |   39 ++++++++++++------------
+ drivers/platform/x86/thinkpad_acpi.c    |   49 +++++++++++++++++--------------
+ 2 files changed, 46 insertions(+), 42 deletions(-)
+
+diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
+index e8f52fb..de6f14c 100644
+--- a/Documentation/laptops/thinkpad-acpi.txt
++++ b/Documentation/laptops/thinkpad-acpi.txt
+@@ -179,17 +179,14 @@ system.  Enabling the hotkey functionality of thinkpad-acpi signals the
+ firmware that such a driver is present, and modifies how the ThinkPad
+ firmware will behave in many situations.
+-The driver enables the hot key feature automatically when loaded.  The
+-feature can later be disabled and enabled back at runtime.  The driver
+-will also restore the hot key feature to its previous state and mask
+-when it is unloaded.
++The driver enables the HKEY ("hot key") event reporting automatically
++when loaded, and disables it when it is removed.
+-When the hotkey feature is enabled and the hot key mask is set (see
+-below), the driver will report HKEY events in the following format:
++The driver will report HKEY events in the following format:
+       ibm/hotkey HKEY 00000080 0000xxxx
+-Some of these events refer to hot key presses, but not all.
++Some of these events refer to hot key presses, but not all of them.
+ The driver will generate events over the input layer for hot keys and
+ radio switches, and over the ACPI netlink layer for other events.  The
+@@ -221,13 +218,17 @@ procfs notes:
+ The following commands can be written to the /proc/acpi/ibm/hotkey file:
+-      echo enable > /proc/acpi/ibm/hotkey -- enable the hot keys feature
+-      echo disable > /proc/acpi/ibm/hotkey -- disable the hot keys feature
+       echo 0xffffffff > /proc/acpi/ibm/hotkey -- enable all hot keys
+       echo 0 > /proc/acpi/ibm/hotkey -- disable all possible hot keys
+       ... any other 8-hex-digit mask ...
+       echo reset > /proc/acpi/ibm/hotkey -- restore the original mask
++The following commands have been deprecated and will cause the kernel
++to log a warning:
++
++      echo enable > /proc/acpi/ibm/hotkey -- does nothing
++      echo disable > /proc/acpi/ibm/hotkey -- returns an error
++
+ The procfs interface does not support NVRAM polling control.  So as to
+ maintain maximum bug-to-bug compatibility, it does not report any masks,
+ nor does it allow one to manipulate the hot key mask when the firmware
+@@ -236,12 +237,9 @@ does not support masks at all, even if NVRAM polling is in use.
+ sysfs notes:
+       hotkey_bios_enabled:
+-              Returns the status of the hot keys feature when
+-              thinkpad-acpi was loaded.  Upon module unload, the hot
+-              key feature status will be restored to this value.
++              DEPRECATED, WILL BE REMOVED SOON.
+-              0: hot keys were disabled
+-              1: hot keys were enabled (unusual)
++              Returns 0.
+       hotkey_bios_mask:
+               Returns the hot keys mask when thinkpad-acpi was loaded.
+@@ -249,13 +247,10 @@ sysfs notes:
+               to this value.
+       hotkey_enable:
+-              Enables/disables the hot keys feature in the ACPI
+-              firmware, and reports current status of the hot keys
+-              feature.  Has no effect on the NVRAM hot key polling
+-              functionality.
++              DEPRECATED, WILL BE REMOVED SOON.
+-              0: disables the hot keys feature / feature disabled
+-              1: enables the hot keys feature / feature enabled
++              0: returns -EPERM
++              1: does nothing
+       hotkey_mask:
+               bit mask to enable driver-handling (and depending on
+@@ -1535,3 +1530,7 @@ Sysfs interface changelog:
+ 0x020200:     Add poll()/select() support to the following attributes:
+               hotkey_radio_sw, wakeup_hotunplug_complete, wakeup_reason
++
++0x020300:     hotkey enable/disable support removed, attributes
++              hotkey_bios_enabled and hotkey_enable deprecated and
++              marked for removal.
+diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
+index 852be7c..f003fb7 100644
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -22,7 +22,7 @@
+  */
+ #define TPACPI_VERSION "0.22"
+-#define TPACPI_SYSFS_VERSION 0x020200
++#define TPACPI_SYSFS_VERSION 0x020300
+ /*
+  *  Changelog:
+@@ -1424,7 +1424,6 @@ static enum {    /* Reasons for waking up */
+ static int hotkey_autosleep_ack;
+-static int hotkey_orig_status;
+ static u32 hotkey_orig_mask;
+ static u32 hotkey_all_mask;
+ static u32 hotkey_reserved_mask;
+@@ -1571,9 +1570,9 @@ static int hotkey_status_get(int *status)
+       return 0;
+ }
+-static int hotkey_status_set(int status)
++static int hotkey_status_set(bool enable)
+ {
+-      if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status))
++      if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", enable ? 1 : 0))
+               return -EIO;
+       return 0;
+@@ -1889,6 +1888,9 @@ static ssize_t hotkey_enable_show(struct device *dev,
+ {
+       int res, status;
++      printk_deprecated_attribute("hotkey_enable",
++                      "Hotkey reporting is always enabled");
++
+       res = hotkey_status_get(&status);
+       if (res)
+               return res;
+@@ -1901,14 +1903,17 @@ static ssize_t hotkey_enable_store(struct device *dev,
+                           const char *buf, size_t count)
+ {
+       unsigned long t;
+-      int res;
++
++      printk_deprecated_attribute("hotkey_enable",
++                      "Hotkeys can be disabled through hotkey_mask");
+       if (parse_strtoul(buf, 1, &t))
+               return -EINVAL;
+-      res = hotkey_status_set(t);
++      if (t == 0)
++              return -EPERM;
+-      return (res) ? res : count;
++      return count;
+ }
+ static struct device_attribute dev_attr_hotkey_enable =
+@@ -1964,7 +1969,7 @@ static ssize_t hotkey_bios_enabled_show(struct device *dev,
+                          struct device_attribute *attr,
+                          char *buf)
+ {
+-      return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_orig_status);
++      return sprintf(buf, "0\n");
+ }
+ static struct device_attribute dev_attr_hotkey_bios_enabled =
+@@ -2243,7 +2248,7 @@ static void hotkey_exit(void)
+                          "restoring original hot key mask\n");
+               /* no short-circuit boolean operator below! */
+               if ((hotkey_mask_set(hotkey_orig_mask) |
+-                   hotkey_status_set(hotkey_orig_status)) != 0)
++                   hotkey_status_set(false)) != 0)
+                       printk(TPACPI_ERR
+                              "failed to restore hot key mask "
+                              "to BIOS defaults\n");
+@@ -2438,10 +2443,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
+       /* hotkey_source_mask *must* be zero for
+        * the first hotkey_mask_get */
+-      res = hotkey_status_get(&hotkey_orig_status);
+-      if (res)
+-              goto err_exit;
+-
+       if (tp_features.hotkey_mask) {
+               res = hotkey_mask_get();
+               if (res)
+@@ -2581,7 +2582,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
+       }
+       dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n");
+-      res = hotkey_status_set(1);
++      res = hotkey_status_set(true);
+       if (res) {
+               hotkey_exit();
+               return res;
+@@ -2926,9 +2927,17 @@ static int hotkey_read(char *p)
+       return len;
+ }
++static void hotkey_enabledisable_warn(void)
++{
++      tpacpi_log_usertask("procfs hotkey enable/disable");
++      WARN(1, TPACPI_WARN
++           "hotkey enable/disable functionality has been "
++           "removed from the driver. Hotkeys are always enabled.\n");
++}
++
+ static int hotkey_write(char *buf)
+ {
+-      int res, status;
++      int res;
+       u32 mask;
+       char *cmd;
+@@ -2938,17 +2947,16 @@ static int hotkey_write(char *buf)
+       if (mutex_lock_killable(&hotkey_mutex))
+               return -ERESTARTSYS;
+-      status = -1;
+       mask = hotkey_mask;
+       res = 0;
+       while ((cmd = next_cmd(&buf))) {
+               if (strlencmp(cmd, "enable") == 0) {
+-                      status = 1;
++                      hotkey_enabledisable_warn();
+               } else if (strlencmp(cmd, "disable") == 0) {
+-                      status = 0;
++                      hotkey_enabledisable_warn();
++                      res = -EPERM;
+               } else if (strlencmp(cmd, "reset") == 0) {
+-                      status = hotkey_orig_status;
+                       mask = hotkey_orig_mask;
+               } else if (sscanf(cmd, "0x%x", &mask) == 1) {
+                       /* mask set */
+@@ -2959,9 +2967,6 @@ static int hotkey_write(char *buf)
+                       goto errexit;
+               }
+       }
+-      if (status != -1)
+-              res = hotkey_status_set(status);
+-
+       if (!res && mask != hotkey_mask)
+               res = hotkey_mask_set(mask);
+-- 
+1.6.2.1
+
diff --git a/releases/upstream/2.6.30-rc1/0010-thinkpad-acpi-restrict-access-to-some-firmware-LEDs.patch b/releases/upstream/2.6.30-rc1/0010-thinkpad-acpi-restrict-access-to-some-firmware-LEDs.patch
new file mode 100644 (file)
index 0000000..eaa5781
--- /dev/null
@@ -0,0 +1,216 @@
+From a4d5effcc73749ee3ebbf578d162905e6fa4e07d Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Sat, 4 Apr 2009 04:25:49 +0000
+Subject: thinkpad-acpi: restrict access to some firmware LEDs
+
+Some of the ThinkPad LEDs indicate critical conditions that can cause
+data loss or cause hardware damage when ignored (e.g. force-ejecting
+a powered up bay; ignoring a failing battery, or empty battery; force-
+undocking with the dock buses still active, etc).
+
+On almost all ThinkPads, LED access is write-only, and the firmware
+usually does fire-and-forget signaling on them, so you effectively
+lose whatever message the firmware was trying to convey to the user
+when you override the LED state, without any chance to restore it.
+
+Restrict access to all LEDs that can convey important alarms, or that
+could mislead the user into incorrectly operating the hardware.  This
+will make the Lenovo engineers less unhappy about the whole issue.
+
+Allow users that really want it to still control all LEDs, it is the
+unaware user that we have to worry about.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ Documentation/laptops/thinkpad-acpi.txt |   11 +++++
+ drivers/platform/x86/Kconfig            |   24 ++++++++++
+ drivers/platform/x86/thinkpad_acpi.c    |   76 +++++++++++++++++++++++--------
+ 3 files changed, 91 insertions(+), 20 deletions(-)
+
+diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
+index de6f14c..bce1d95 100644
+--- a/Documentation/laptops/thinkpad-acpi.txt
++++ b/Documentation/laptops/thinkpad-acpi.txt
+@@ -901,6 +901,17 @@ some older ThinkPad models, it is possible to query the status of the
+ LED indicators as well.  Newer ThinkPads cannot query the real status
+ of the LED indicators.
++Because misuse of the LEDs could induce an unaware user to perform
++dangerous actions (like undocking or ejecting a bay device while the
++buses are still active), or mask an important alarm (such as a nearly
++empty battery, or a broken battery), access to most LEDs is
++restricted.
++
++Unrestricted access to all LEDs requires that thinkpad-acpi be
++compiled with the CONFIG_THINKPAD_ACPI_UNSAFE_LEDS option enabled.
++Distributions must never enable this option.  Individual users that
++are aware of the consequences are welcome to enabling it.
++
+ procfs notes:
+ The available commands are:
+diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
+index 3608081..d45c6ab 100644
+--- a/drivers/platform/x86/Kconfig
++++ b/drivers/platform/x86/Kconfig
+@@ -226,6 +226,30 @@ config THINKPAD_ACPI_DEBUG
+         If you are not sure, say N here.
++config THINKPAD_ACPI_UNSAFE_LEDS
++      bool "Allow control of important LEDs (unsafe)"
++      depends on THINKPAD_ACPI
++      default n
++      ---help---
++        Overriding LED state on ThinkPads can mask important
++        firmware alerts (like critical battery condition), or misled
++        the user into damaging the hardware (undocking or ejecting
++        the bay while buses are still active), etc.
++
++        LED control on the ThinkPad is write-only (with very few
++        exceptions on very ancient models), which makes it
++        impossible to know beforehand if important information will
++        be lost when one changes LED state.
++
++        Users that know what they are doing can enable this option
++        and the driver will allow control of every LED, including
++        the ones on the dock stations.
++
++        Never enable this option on a distribution kernel.
++
++        Say N here, unless you are building a kernel for your own
++        use, and need to control the important firmware LEDs.
++
+ config THINKPAD_ACPI_DOCK
+       bool "Legacy Docking Station Support"
+       depends on THINKPAD_ACPI
+diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
+index f003fb7..38c34c7 100644
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -4657,6 +4657,16 @@ static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = {
+       "tpacpi::unknown_led",
+       "tpacpi::standby",
+ };
++#define TPACPI_SAFE_LEDS      0x0081U
++
++static inline bool tpacpi_is_led_restricted(const unsigned int led)
++{
++#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS
++      return false;
++#else
++      return (TPACPI_SAFE_LEDS & (1 << led)) == 0;
++#endif
++}
+ static int led_get_status(const unsigned int led)
+ {
+@@ -4694,16 +4704,20 @@ static int led_set_status(const unsigned int led,
+       switch (led_supported) {
+       case TPACPI_LED_570:
+               /* 570 */
+-              if (led > 7)
++              if (unlikely(led > 7))
+                       return -EINVAL;
++              if (unlikely(tpacpi_is_led_restricted(led)))
++                      return -EPERM;
+               if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
+                               (1 << led), led_sled_arg1[ledstatus]))
+                       rc = -EIO;
+               break;
+       case TPACPI_LED_OLD:
+               /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
+-              if (led > 7)
++              if (unlikely(led > 7))
+                       return -EINVAL;
++              if (unlikely(tpacpi_is_led_restricted(led)))
++                      return -EPERM;
+               rc = ec_write(TPACPI_LED_EC_HLMS, (1 << led));
+               if (rc >= 0)
+                       rc = ec_write(TPACPI_LED_EC_HLBL,
+@@ -4714,6 +4728,10 @@ static int led_set_status(const unsigned int led,
+               break;
+       case TPACPI_LED_NEW:
+               /* all others */
++              if (unlikely(led >= TPACPI_LED_NUMLEDS))
++                      return -EINVAL;
++              if (unlikely(tpacpi_is_led_restricted(led)))
++                      return -EPERM;
+               if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
+                               led, led_led_arg1[ledstatus]))
+                       rc = -EIO;
+@@ -4806,6 +4824,30 @@ static void led_exit(void)
+       kfree(tpacpi_leds);
+ }
++static int __init tpacpi_init_led(unsigned int led)
++{
++      int rc;
++
++      tpacpi_leds[led].led = led;
++
++      tpacpi_leds[led].led_classdev.brightness_set = &led_sysfs_set;
++      tpacpi_leds[led].led_classdev.blink_set = &led_sysfs_blink_set;
++      if (led_supported == TPACPI_LED_570)
++              tpacpi_leds[led].led_classdev.brightness_get =
++                                              &led_sysfs_get;
++
++      tpacpi_leds[led].led_classdev.name = tpacpi_led_names[led];
++
++      INIT_WORK(&tpacpi_leds[led].work, led_set_status_worker);
++
++      rc = led_classdev_register(&tpacpi_pdev->dev,
++                              &tpacpi_leds[led].led_classdev);
++      if (rc < 0)
++              tpacpi_leds[led].led_classdev.name = NULL;
++
++      return rc;
++}
++
+ static int __init led_init(struct ibm_init_struct *iibm)
+ {
+       unsigned int i;
+@@ -4839,27 +4881,21 @@ static int __init led_init(struct ibm_init_struct *iibm)
+       }
+       for (i = 0; i < TPACPI_LED_NUMLEDS; i++) {
+-              tpacpi_leds[i].led = i;
+-
+-              tpacpi_leds[i].led_classdev.brightness_set = &led_sysfs_set;
+-              tpacpi_leds[i].led_classdev.blink_set = &led_sysfs_blink_set;
+-              if (led_supported == TPACPI_LED_570)
+-                      tpacpi_leds[i].led_classdev.brightness_get =
+-                                                      &led_sysfs_get;
+-
+-              tpacpi_leds[i].led_classdev.name = tpacpi_led_names[i];
+-
+-              INIT_WORK(&tpacpi_leds[i].work, led_set_status_worker);
+-
+-              rc = led_classdev_register(&tpacpi_pdev->dev,
+-                                         &tpacpi_leds[i].led_classdev);
+-              if (rc < 0) {
+-                      tpacpi_leds[i].led_classdev.name = NULL;
+-                      led_exit();
+-                      return rc;
++              if (!tpacpi_is_led_restricted(i)) {
++                      rc = tpacpi_init_led(i);
++                      if (rc < 0) {
++                              led_exit();
++                              return rc;
++                      }
+               }
+       }
++#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS
++      if (led_supported != TPACPI_LED_NONE)
++              printk(TPACPI_NOTICE
++                      "warning: userspace override of important "
++                      "firmware LEDs is enabled\n");
++#endif
+       return (led_supported != TPACPI_LED_NONE)? 0 : 1;
+ }
+-- 
+1.6.2.1
+
diff --git a/releases/upstream/2.6.30-rc1/0011-thinkpad-acpi-enhanced-debugging-messages-for-rfkil.patch b/releases/upstream/2.6.30-rc1/0011-thinkpad-acpi-enhanced-debugging-messages-for-rfkil.patch
new file mode 100644 (file)
index 0000000..140a164
--- /dev/null
@@ -0,0 +1,414 @@
+From bee4cd9b9eaa8c72832e1ee7f4940604e94beb27 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Sat, 4 Apr 2009 04:25:50 +0000
+Subject: thinkpad-acpi: enhanced debugging messages for rfkill subdrivers
+
+Enhance debugging messages for all rfkill subdrivers in thinkpad-acpi.
+
+Also, log a warning if the deprecated sysfs attributes are in use.
+These attributes are going to be removed sometime in 2010.
+
+There is an user-visible side-effect: we now coalesce attempts to
+enable/disable bluetooth or WWAN in the procfs interface, instead of
+hammering the firmware with multiple requests.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ Documentation/laptops/thinkpad-acpi.txt |    2 +
+ drivers/platform/x86/thinkpad_acpi.c    |  117 +++++++++++++++++++++++++------
+ 2 files changed, 98 insertions(+), 21 deletions(-)
+
+diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
+index bce1d95..7daca05 100644
+--- a/Documentation/laptops/thinkpad-acpi.txt
++++ b/Documentation/laptops/thinkpad-acpi.txt
+@@ -1494,6 +1494,8 @@ to enable more than one output class, just add their values.
+                               accessing some functions of the driver
+       0x0001                  Initialization and probing
+       0x0002                  Removal
++      0x0004                  RF Transmitter control (RFKILL)
++                              (bluetooth, WWAN, UWB...)
+ There is also a kernel build option to enable more debugging
+ information, which may be necessary to debug driver problems.
+diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
+index 38c34c7..57ab551 100644
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -189,6 +189,7 @@ enum {
+ #define TPACPI_DBG_DISCLOSETASK       0x8000
+ #define TPACPI_DBG_INIT               0x0001
+ #define TPACPI_DBG_EXIT               0x0002
++#define TPACPI_DBG_RFKILL     0x0004
+ #define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off")
+ #define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
+@@ -1016,10 +1017,13 @@ static int __init tpacpi_new_rfkill(const unsigned int id,
+               /* 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,
++              if (rfkill_set_default(rfktype,
+                               (initial_state == RFKILL_STATE_UNBLOCKED) ?
+                                       RFKILL_STATE_UNBLOCKED :
+-                                      RFKILL_STATE_SOFT_BLOCKED);
++                                      RFKILL_STATE_SOFT_BLOCKED) == -EPERM)
++                      vdbg_printk(TPACPI_DBG_RFKILL,
++                                  "Default state for %s cannot be changed\n",
++                                  name);
+       }
+       *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype);
+@@ -3018,13 +3022,17 @@ enum {
+       TP_ACPI_BLTH_SAVE_STATE         = 0x05, /* Save state for S4/S5 */
+ };
++#define TPACPI_RFK_BLUETOOTH_SW_NAME  "tpacpi_bluetooth_sw"
++
+ static struct rfkill *tpacpi_bluetooth_rfkill;
+ static void bluetooth_suspend(pm_message_t state)
+ {
+       /* Try to make sure radio will resume powered off */
+-      acpi_evalf(NULL, NULL, "\\BLTH", "vd",
+-                 TP_ACPI_BLTH_PWR_OFF_ON_RESUME);
++      if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd",
++                 TP_ACPI_BLTH_PWR_OFF_ON_RESUME))
++              vdbg_printk(TPACPI_DBG_RFKILL,
++                      "bluetooth power down on resume request failed\n");
+ }
+ static int bluetooth_get_radiosw(void)
+@@ -3062,6 +3070,10 @@ static void bluetooth_update_rfk(void)
+       if (status < 0)
+               return;
+       rfkill_force_state(tpacpi_bluetooth_rfkill, status);
++
++      vdbg_printk(TPACPI_DBG_RFKILL,
++              "forced rfkill state to %d\n",
++              status);
+ }
+ static int bluetooth_set_radiosw(int radio_on, int update_rfk)
+@@ -3077,6 +3089,9 @@ static int bluetooth_set_radiosw(int radio_on, int update_rfk)
+           && radio_on)
+               return -EPERM;
++      vdbg_printk(TPACPI_DBG_RFKILL,
++              "will %s bluetooth\n", radio_on ? "enable" : "disable");
++
+ #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+       if (dbg_bluetoothemul) {
+               tpacpi_bluetooth_emulstate = !!radio_on;
+@@ -3129,6 +3144,8 @@ static ssize_t bluetooth_enable_store(struct device *dev,
+       if (parse_strtoul(buf, 1, &t))
+               return -EINVAL;
++      tpacpi_disclose_usertask("bluetooth_enable", "set to %ld\n", t);
++
+       res = bluetooth_set_radiosw(t, 1);
+       return (res) ? res : count;
+@@ -3162,6 +3179,8 @@ static int tpacpi_bluetooth_rfk_get(void *data, enum rfkill_state *state)
+ static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state)
+ {
++      dbg_printk(TPACPI_DBG_RFKILL,
++                 "request to change radio state to %d\n", state);
+       return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
+ }
+@@ -3172,6 +3191,9 @@ static void bluetooth_shutdown(void)
+                       TP_ACPI_BLTH_SAVE_STATE))
+               printk(TPACPI_NOTICE
+                       "failed to save bluetooth state to NVRAM\n");
++      else
++              vdbg_printk(TPACPI_DBG_RFKILL,
++                      "bluestooth state saved to NVRAM\n");
+ }
+ static void bluetooth_exit(void)
+@@ -3190,7 +3212,8 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
+       int res;
+       int status = 0;
+-      vdbg_printk(TPACPI_DBG_INIT, "initializing bluetooth subdriver\n");
++      vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
++                      "initializing bluetooth subdriver\n");
+       TPACPI_ACPIHANDLE_INIT(hkey);
+@@ -3199,7 +3222,8 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
+       tp_features.bluetooth = hkey_handle &&
+           acpi_evalf(hkey_handle, &status, "GBDC", "qd");
+-      vdbg_printk(TPACPI_DBG_INIT, "bluetooth is %s, status 0x%02x\n",
++      vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
++              "bluetooth is %s, status 0x%02x\n",
+               str_supported(tp_features.bluetooth),
+               status);
+@@ -3214,7 +3238,7 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
+           !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) {
+               /* no bluetooth hardware present in system */
+               tp_features.bluetooth = 0;
+-              dbg_printk(TPACPI_DBG_INIT,
++              dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
+                          "bluetooth hardware not installed\n");
+       }
+@@ -3229,7 +3253,7 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
+       res = tpacpi_new_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID,
+                               &tpacpi_bluetooth_rfkill,
+                               RFKILL_TYPE_BLUETOOTH,
+-                              "tpacpi_bluetooth_sw",
++                              TPACPI_RFK_BLUETOOTH_SW_NAME,
+                               true,
+                               tpacpi_bluetooth_rfk_set,
+                               tpacpi_bluetooth_rfk_get);
+@@ -3262,19 +3286,27 @@ static int bluetooth_read(char *p)
+ static int bluetooth_write(char *buf)
+ {
+       char *cmd;
++      int state = -1;
+       if (!tp_features.bluetooth)
+               return -ENODEV;
+       while ((cmd = next_cmd(&buf))) {
+               if (strlencmp(cmd, "enable") == 0) {
+-                      bluetooth_set_radiosw(1, 1);
++                      state = 1;
+               } else if (strlencmp(cmd, "disable") == 0) {
+-                      bluetooth_set_radiosw(0, 1);
++                      state = 0;
+               } else
+                       return -EINVAL;
+       }
++      if (state != -1) {
++              tpacpi_disclose_usertask("procfs bluetooth",
++                      "attempt to %s\n",
++                      state ? "enable" : "disable");
++              bluetooth_set_radiosw(state, 1);
++      }
++
+       return 0;
+ }
+@@ -3299,13 +3331,17 @@ enum {
+                                                  off / last state */
+ };
++#define TPACPI_RFK_WWAN_SW_NAME               "tpacpi_wwan_sw"
++
+ static struct rfkill *tpacpi_wan_rfkill;
+ static void wan_suspend(pm_message_t state)
+ {
+       /* Try to make sure radio will resume powered off */
+-      acpi_evalf(NULL, NULL, "\\WGSV", "qvd",
+-                 TP_ACPI_WGSV_PWR_OFF_ON_RESUME);
++      if (!acpi_evalf(NULL, NULL, "\\WGSV", "qvd",
++                 TP_ACPI_WGSV_PWR_OFF_ON_RESUME))
++              vdbg_printk(TPACPI_DBG_RFKILL,
++                      "WWAN power down on resume request failed\n");
+ }
+ static int wan_get_radiosw(void)
+@@ -3343,6 +3379,10 @@ static void wan_update_rfk(void)
+       if (status < 0)
+               return;
+       rfkill_force_state(tpacpi_wan_rfkill, status);
++
++      vdbg_printk(TPACPI_DBG_RFKILL,
++              "forced rfkill state to %d\n",
++              status);
+ }
+ static int wan_set_radiosw(int radio_on, int update_rfk)
+@@ -3358,6 +3398,9 @@ static int wan_set_radiosw(int radio_on, int update_rfk)
+           && radio_on)
+               return -EPERM;
++      vdbg_printk(TPACPI_DBG_RFKILL,
++              "will %s WWAN\n", radio_on ? "enable" : "disable");
++
+ #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+       if (dbg_wwanemul) {
+               tpacpi_wwan_emulstate = !!radio_on;
+@@ -3410,6 +3453,8 @@ static ssize_t wan_enable_store(struct device *dev,
+       if (parse_strtoul(buf, 1, &t))
+               return -EINVAL;
++      tpacpi_disclose_usertask("wwan_enable", "set to %ld\n", t);
++
+       res = wan_set_radiosw(t, 1);
+       return (res) ? res : count;
+@@ -3443,6 +3488,8 @@ static int tpacpi_wan_rfk_get(void *data, enum rfkill_state *state)
+ static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state)
+ {
++      dbg_printk(TPACPI_DBG_RFKILL,
++                 "request to change radio state to %d\n", state);
+       return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
+ }
+@@ -3453,6 +3500,9 @@ static void wan_shutdown(void)
+                       TP_ACPI_WGSV_SAVE_STATE))
+               printk(TPACPI_NOTICE
+                       "failed to save WWAN state to NVRAM\n");
++      else
++              vdbg_printk(TPACPI_DBG_RFKILL,
++                      "WWAN state saved to NVRAM\n");
+ }
+ static void wan_exit(void)
+@@ -3471,14 +3521,16 @@ static int __init wan_init(struct ibm_init_struct *iibm)
+       int res;
+       int status = 0;
+-      vdbg_printk(TPACPI_DBG_INIT, "initializing wan subdriver\n");
++      vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
++                      "initializing wan subdriver\n");
+       TPACPI_ACPIHANDLE_INIT(hkey);
+       tp_features.wan = hkey_handle &&
+           acpi_evalf(hkey_handle, &status, "GWAN", "qd");
+-      vdbg_printk(TPACPI_DBG_INIT, "wan is %s, status 0x%02x\n",
++      vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
++              "wan is %s, status 0x%02x\n",
+               str_supported(tp_features.wan),
+               status);
+@@ -3493,7 +3545,7 @@ static int __init wan_init(struct ibm_init_struct *iibm)
+           !(status & TP_ACPI_WANCARD_HWPRESENT)) {
+               /* no wan hardware present in system */
+               tp_features.wan = 0;
+-              dbg_printk(TPACPI_DBG_INIT,
++              dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
+                          "wan hardware not installed\n");
+       }
+@@ -3508,7 +3560,7 @@ static int __init wan_init(struct ibm_init_struct *iibm)
+       res = tpacpi_new_rfkill(TPACPI_RFK_WWAN_SW_ID,
+                               &tpacpi_wan_rfkill,
+                               RFKILL_TYPE_WWAN,
+-                              "tpacpi_wwan_sw",
++                              TPACPI_RFK_WWAN_SW_NAME,
+                               true,
+                               tpacpi_wan_rfk_set,
+                               tpacpi_wan_rfk_get);
+@@ -3526,6 +3578,8 @@ static int wan_read(char *p)
+       int len = 0;
+       int status = wan_get_radiosw();
++      tpacpi_disclose_usertask("procfs wan", "read");
++
+       if (!tp_features.wan)
+               len += sprintf(p + len, "status:\t\tnot supported\n");
+       else {
+@@ -3541,19 +3595,27 @@ static int wan_read(char *p)
+ static int wan_write(char *buf)
+ {
+       char *cmd;
++      int state = -1;
+       if (!tp_features.wan)
+               return -ENODEV;
+       while ((cmd = next_cmd(&buf))) {
+               if (strlencmp(cmd, "enable") == 0) {
+-                      wan_set_radiosw(1, 1);
++                      state = 1;
+               } else if (strlencmp(cmd, "disable") == 0) {
+-                      wan_set_radiosw(0, 1);
++                      state = 0;
+               } else
+                       return -EINVAL;
+       }
++      if (state != -1) {
++              tpacpi_disclose_usertask("procfs wan",
++                      "attempt to %s\n",
++                      state ? "enable" : "disable");
++              wan_set_radiosw(state, 1);
++      }
++
+       return 0;
+ }
+@@ -3576,6 +3638,8 @@ enum {
+       TP_ACPI_UWB_RADIOSSW    = 0x02, /* UWB radio enabled */
+ };
++#define TPACPI_RFK_UWB_SW_NAME        "tpacpi_uwb_sw"
++
+ static struct rfkill *tpacpi_uwb_rfkill;
+ static int uwb_get_radiosw(void)
+@@ -3613,6 +3677,10 @@ static void uwb_update_rfk(void)
+       if (status < 0)
+               return;
+       rfkill_force_state(tpacpi_uwb_rfkill, status);
++
++      vdbg_printk(TPACPI_DBG_RFKILL,
++              "forced rfkill state to %d\n",
++              status);
+ }
+ static int uwb_set_radiosw(int radio_on, int update_rfk)
+@@ -3628,6 +3696,9 @@ static int uwb_set_radiosw(int radio_on, int update_rfk)
+           && radio_on)
+               return -EPERM;
++      vdbg_printk(TPACPI_DBG_RFKILL,
++                      "will %s UWB\n", radio_on ? "enable" : "disable");
++
+ #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+       if (dbg_uwbemul) {
+               tpacpi_uwb_emulstate = !!radio_on;
+@@ -3662,6 +3733,8 @@ static int tpacpi_uwb_rfk_get(void *data, enum rfkill_state *state)
+ static int tpacpi_uwb_rfk_set(void *data, enum rfkill_state state)
+ {
++      dbg_printk(TPACPI_DBG_RFKILL,
++                 "request to change radio state to %d\n", state);
+       return uwb_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
+ }
+@@ -3676,14 +3749,16 @@ static int __init uwb_init(struct ibm_init_struct *iibm)
+       int res;
+       int status = 0;
+-      vdbg_printk(TPACPI_DBG_INIT, "initializing uwb subdriver\n");
++      vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
++                      "initializing uwb subdriver\n");
+       TPACPI_ACPIHANDLE_INIT(hkey);
+       tp_features.uwb = hkey_handle &&
+           acpi_evalf(hkey_handle, &status, "GUWB", "qd");
+-      vdbg_printk(TPACPI_DBG_INIT, "uwb is %s, status 0x%02x\n",
++      vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
++              "uwb is %s, status 0x%02x\n",
+               str_supported(tp_features.uwb),
+               status);
+@@ -3708,7 +3783,7 @@ static int __init uwb_init(struct ibm_init_struct *iibm)
+       res = tpacpi_new_rfkill(TPACPI_RFK_UWB_SW_ID,
+                               &tpacpi_uwb_rfkill,
+                               RFKILL_TYPE_UWB,
+-                              "tpacpi_uwb_sw",
++                              TPACPI_RFK_UWB_SW_NAME,
+                               false,
+                               tpacpi_uwb_rfk_set,
+                               tpacpi_uwb_rfk_get);
+-- 
+1.6.2.1
+
diff --git a/releases/upstream/2.6.30-rc1/0012-thinkpad-acpi-enhanced-debugging-messages-for-the-h.patch b/releases/upstream/2.6.30-rc1/0012-thinkpad-acpi-enhanced-debugging-messages-for-the-h.patch
new file mode 100644 (file)
index 0000000..6a80cef
--- /dev/null
@@ -0,0 +1,170 @@
+From 56e2c200945dafafb86169762eb1e88aed0ce69e Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Sat, 4 Apr 2009 04:25:51 +0000
+Subject: thinkpad-acpi: enhanced debugging messages for the hotkey subdriver
+
+Enhance debugging messages for the hotkey subdriver.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ Documentation/laptops/thinkpad-acpi.txt |    1 +
+ drivers/platform/x86/thinkpad_acpi.c    |   39 +++++++++++++++++++++++--------
+ 2 files changed, 30 insertions(+), 10 deletions(-)
+
+diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
+index 7daca05..abbbe78 100644
+--- a/Documentation/laptops/thinkpad-acpi.txt
++++ b/Documentation/laptops/thinkpad-acpi.txt
+@@ -1496,6 +1496,7 @@ to enable more than one output class, just add their values.
+       0x0002                  Removal
+       0x0004                  RF Transmitter control (RFKILL)
+                               (bluetooth, WWAN, UWB...)
++      0x0008                  HKEY event interface, hotkeys
+ There is also a kernel build option to enable more debugging
+ information, which may be necessary to debug driver problems.
+diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
+index 57ab551..0a4796a 100644
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -190,6 +190,7 @@ enum {
+ #define TPACPI_DBG_INIT               0x0001
+ #define TPACPI_DBG_EXIT               0x0002
+ #define TPACPI_DBG_RFKILL     0x0004
++#define TPACPI_DBG_HKEY               0x0008
+ #define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off")
+ #define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
+@@ -1961,6 +1962,8 @@ static ssize_t hotkey_mask_store(struct device *dev,
+       mutex_unlock(&hotkey_mutex);
++      tpacpi_disclose_usertask("hotkey_mask", "set to 0x%08lx\n", t);
++
+       return (res) ? res : count;
+ }
+@@ -2047,6 +2050,8 @@ static ssize_t hotkey_source_mask_store(struct device *dev,
+       mutex_unlock(&hotkey_mutex);
++      tpacpi_disclose_usertask("hotkey_source_mask", "set to 0x%08lx\n", t);
++
+       return count;
+ }
+@@ -2079,6 +2084,8 @@ static ssize_t hotkey_poll_freq_store(struct device *dev,
+       hotkey_poll_setup(1);
+       mutex_unlock(&hotkey_mutex);
++      tpacpi_disclose_usertask("hotkey_poll_freq", "set to %lu\n", t);
++
+       return count;
+ }
+@@ -2248,7 +2255,7 @@ static void hotkey_exit(void)
+       kfree(hotkey_keycode_map);
+       if (tp_features.hotkey) {
+-              dbg_printk(TPACPI_DBG_EXIT,
++              dbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_HKEY,
+                          "restoring original hot key mask\n");
+               /* no short-circuit boolean operator below! */
+               if ((hotkey_mask_set(hotkey_orig_mask) |
+@@ -2378,7 +2385,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
+       int status;
+       int hkeyv;
+-      vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n");
++      vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
++                      "initializing hotkey subdriver\n");
+       BUG_ON(!tpacpi_inputdev);
+       BUG_ON(tpacpi_inputdev->open != NULL ||
+@@ -2395,7 +2403,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
+       /* hotkey not supported on 570 */
+       tp_features.hotkey = hkey_handle != NULL;
+-      vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n",
++      vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
++              "hotkeys are %s\n",
+               str_supported(tp_features.hotkey));
+       if (!tp_features.hotkey)
+@@ -2427,10 +2436,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
+                        * T4x, X31, and later
+                        */
+                       tp_features.hotkey_mask = 1;
++                      vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
++                              "firmware HKEY interface version: 0x%x\n",
++                              hkeyv);
+               }
+       }
+-      vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n",
++      vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
++              "hotkey masks are %s\n",
+               str_supported(tp_features.hotkey_mask));
+       if (tp_features.hotkey_mask) {
+@@ -2469,7 +2482,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
+               hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK;
+       }
+-      vdbg_printk(TPACPI_DBG_INIT,
++      vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
+                   "hotkey source mask 0x%08x, polling freq %d\n",
+                   hotkey_source_mask, hotkey_poll_freq);
+ #endif
+@@ -2523,12 +2536,12 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
+       }
+       if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
+-              dbg_printk(TPACPI_DBG_INIT,
++              dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
+                          "using Lenovo default hot key map\n");
+               memcpy(hotkey_keycode_map, &lenovo_keycode_map,
+                       TPACPI_HOTKEY_MAP_SIZE);
+       } else {
+-              dbg_printk(TPACPI_DBG_INIT,
++              dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
+                          "using IBM default hot key map\n");
+               memcpy(hotkey_keycode_map, &ibm_keycode_map,
+                       TPACPI_HOTKEY_MAP_SIZE);
+@@ -2585,7 +2598,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
+                       | (1 << TP_ACPI_HOTKEYSCAN_FNEND);
+       }
+-      dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n");
++      dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
++                      "enabling firmware HKEY event interface...\n");
+       res = hotkey_status_set(true);
+       if (res) {
+               hotkey_exit();
+@@ -2599,8 +2613,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
+               return res;
+       }
+-      dbg_printk(TPACPI_DBG_INIT,
+-                      "legacy hot key reporting over procfs %s\n",
++      dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
++                      "legacy ibm/hotkey event reporting over procfs %s\n",
+                       (hotkey_report_mode < 2) ?
+                               "enabled" : "disabled");
+@@ -2971,6 +2985,11 @@ static int hotkey_write(char *buf)
+                       goto errexit;
+               }
+       }
++
++      if (!res)
++              tpacpi_disclose_usertask("procfs hotkey",
++                      "set mask to 0x%08x\n", mask);
++
+       if (!res && mask != hotkey_mask)
+               res = hotkey_mask_set(mask);
+-- 
+1.6.2.1
+
diff --git a/releases/upstream/2.6.30-rc1/0013-thinkpad-acpi-enhanced-debugging-messages-for-the-f.patch b/releases/upstream/2.6.30-rc1/0013-thinkpad-acpi-enhanced-debugging-messages-for-the-f.patch
new file mode 100644 (file)
index 0000000..2942d72
--- /dev/null
@@ -0,0 +1,192 @@
+From 74a60c0f828016456fc635feae388ffd12bb3bb9 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Sat, 4 Apr 2009 04:25:52 +0000
+Subject: thinkpad-acpi: enhanced debugging messages for the fan subdriver
+
+Enhance debugging messages for the fan subdriver.
+
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ Documentation/laptops/thinkpad-acpi.txt |    1 +
+ drivers/platform/x86/thinkpad_acpi.c    |   46 +++++++++++++++++++++++++++---
+ 2 files changed, 42 insertions(+), 5 deletions(-)
+
+diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
+index abbbe78..25ed43d 100644
+--- a/Documentation/laptops/thinkpad-acpi.txt
++++ b/Documentation/laptops/thinkpad-acpi.txt
+@@ -1497,6 +1497,7 @@ to enable more than one output class, just add their values.
+       0x0004                  RF Transmitter control (RFKILL)
+                               (bluetooth, WWAN, UWB...)
+       0x0008                  HKEY event interface, hotkeys
++      0x0010                  Fan control
+ There is also a kernel build option to enable more debugging
+ information, which may be necessary to debug driver problems.
+diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
+index 0a4796a..4eec770 100644
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -191,6 +191,7 @@ enum {
+ #define TPACPI_DBG_EXIT               0x0002
+ #define TPACPI_DBG_RFKILL     0x0004
+ #define TPACPI_DBG_HKEY               0x0008
++#define TPACPI_DBG_FAN                0x0010
+ #define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off")
+ #define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
+@@ -6271,6 +6272,9 @@ static int fan_set_level(int level)
+       default:
+               return -ENXIO;
+       }
++
++      vdbg_printk(TPACPI_DBG_FAN,
++              "fan control: set fan control register to 0x%02x\n", level);
+       return 0;
+ }
+@@ -6348,6 +6352,11 @@ static int fan_set_enable(void)
+       }
+       mutex_unlock(&fan_mutex);
++
++      if (!rc)
++              vdbg_printk(TPACPI_DBG_FAN,
++                      "fan control: set fan control register to 0x%02x\n",
++                      s);
+       return rc;
+ }
+@@ -6384,6 +6393,9 @@ static int fan_set_disable(void)
+               rc = -ENXIO;
+       }
++      if (!rc)
++              vdbg_printk(TPACPI_DBG_FAN,
++                      "fan control: set fan control register to 0\n");
+       mutex_unlock(&fan_mutex);
+       return rc;
+@@ -6512,6 +6524,9 @@ static ssize_t fan_pwm1_enable_store(struct device *dev,
+       if (parse_strtoul(buf, 2, &t))
+               return -EINVAL;
++      tpacpi_disclose_usertask("hwmon pwm1_enable",
++                      "set fan mode to %lu\n", t);
++
+       switch (t) {
+       case 0:
+               level = TP_EC_FAN_FULLSPEED;
+@@ -6577,6 +6592,9 @@ static ssize_t fan_pwm1_store(struct device *dev,
+       if (parse_strtoul(buf, 255, &s))
+               return -EINVAL;
++      tpacpi_disclose_usertask("hwmon pwm1",
++                      "set fan speed to %lu\n", s);
++
+       /* scale down from 0-255 to 0-7 */
+       newlevel = (s >> 5) & 0x07;
+@@ -6643,6 +6661,8 @@ static ssize_t fan_fan_watchdog_store(struct device_driver *drv,
+       fan_watchdog_maxinterval = t;
+       fan_watchdog_reset();
++      tpacpi_disclose_usertask("fan_watchdog", "set to %lu\n", t);
++
+       return count;
+ }
+@@ -6664,7 +6684,8 @@ static int __init fan_init(struct ibm_init_struct *iibm)
+ {
+       int rc;
+-      vdbg_printk(TPACPI_DBG_INIT, "initializing fan subdriver\n");
++      vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
++                      "initializing fan subdriver\n");
+       mutex_init(&fan_mutex);
+       fan_status_access_mode = TPACPI_FAN_NONE;
+@@ -6723,7 +6744,8 @@ static int __init fan_init(struct ibm_init_struct *iibm)
+               }
+       }
+-      vdbg_printk(TPACPI_DBG_INIT, "fan is %s, modes %d, %d\n",
++      vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
++              "fan is %s, modes %d, %d\n",
+               str_supported(fan_status_access_mode != TPACPI_FAN_NONE ||
+                 fan_control_access_mode != TPACPI_FAN_WR_NONE),
+               fan_status_access_mode, fan_control_access_mode);
+@@ -6732,7 +6754,7 @@ static int __init fan_init(struct ibm_init_struct *iibm)
+       if (!fan_control_allowed) {
+               fan_control_access_mode = TPACPI_FAN_WR_NONE;
+               fan_control_commands = 0;
+-              dbg_printk(TPACPI_DBG_INIT,
++              dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
+                          "fan control features disabled by parameter\n");
+       }
+@@ -6761,7 +6783,7 @@ static int __init fan_init(struct ibm_init_struct *iibm)
+ static void fan_exit(void)
+ {
+-      vdbg_printk(TPACPI_DBG_EXIT,
++      vdbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_FAN,
+                   "cancelling any pending fan watchdog tasks\n");
+       /* FIXME: can we really do this unconditionally? */
+@@ -6942,6 +6964,9 @@ static int fan_write_cmd_level(const char *cmd, int *rc)
+       if (*rc == -ENXIO)
+               printk(TPACPI_ERR "level command accepted for unsupported "
+                      "access mode %d", fan_control_access_mode);
++      else if (!*rc)
++              tpacpi_disclose_usertask("procfs fan",
++                      "set level to %d\n", level);
+       return 1;
+ }
+@@ -6955,6 +6980,8 @@ static int fan_write_cmd_enable(const char *cmd, int *rc)
+       if (*rc == -ENXIO)
+               printk(TPACPI_ERR "enable command accepted for unsupported "
+                      "access mode %d", fan_control_access_mode);
++      else if (!*rc)
++              tpacpi_disclose_usertask("procfs fan", "enable\n");
+       return 1;
+ }
+@@ -6968,6 +6995,8 @@ static int fan_write_cmd_disable(const char *cmd, int *rc)
+       if (*rc == -ENXIO)
+               printk(TPACPI_ERR "disable command accepted for unsupported "
+                      "access mode %d", fan_control_access_mode);
++      else if (!*rc)
++              tpacpi_disclose_usertask("procfs fan", "disable\n");
+       return 1;
+ }
+@@ -6986,6 +7015,9 @@ static int fan_write_cmd_speed(const char *cmd, int *rc)
+       if (*rc == -ENXIO)
+               printk(TPACPI_ERR "speed command accepted for unsupported "
+                      "access mode %d", fan_control_access_mode);
++      else if (!*rc)
++              tpacpi_disclose_usertask("procfs fan",
++                      "set speed to %d\n", speed);
+       return 1;
+ }
+@@ -6999,8 +7031,12 @@ static int fan_write_cmd_watchdog(const char *cmd, int *rc)
+       if (interval < 0 || interval > 120)
+               *rc = -EINVAL;
+-      else
++      else {
+               fan_watchdog_maxinterval = interval;
++              tpacpi_disclose_usertask("procfs fan",
++                      "set watchdog timer to %d\n",
++                      interval);
++      }
+       return 1;
+ }
+-- 
+1.6.2.1
+
diff --git a/releases/upstream/2.6.30-rc1/0014-thinkpad-acpi-rework-brightness-support.patch b/releases/upstream/2.6.30-rc1/0014-thinkpad-acpi-rework-brightness-support.patch
new file mode 100644 (file)
index 0000000..08364c6
--- /dev/null
@@ -0,0 +1,513 @@
+From 0e501834f8c2ba7de2a56e332d346dcf4ac0b593 Mon Sep 17 00:00:00 2001
+From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Date: Sat, 4 Apr 2009 04:25:53 +0000
+Subject: thinkpad-acpi: rework brightness support
+
+Refactor and redesign the brightness control backend...
+
+In order to fix bugzilla #11750...
+
+Add a new brightness control mode: support direct NVRAM checkpointing
+of the backlight level (i.e. store directly to NVRAM without the need
+for UCMS calls), and use that together with the EC-based control.
+Disallow UCMS+EC, thus avoiding races with the SMM firmware.
+
+Switch the models that define HBRV (EC Brightness Value) in the DSDT
+to the new mode.  These are: T40-T43, R50-R52, R50e, R51e, X31-X41.
+
+Change the default for all other IBM ThinkPads to UCMS-only.  The
+Lenovo models already default to UCMS-only.
+
+Reported-by: Alexey Fisher <bug-track@fisher-privat.net>
+Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
+Signed-off-by: Len Brown <len.brown@intel.com>
+---
+ Documentation/laptops/thinkpad-acpi.txt |   12 +-
+ drivers/platform/x86/thinkpad_acpi.c    |  317 +++++++++++++++++++++----------
+ 2 files changed, 227 insertions(+), 102 deletions(-)
+
+diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
+index 25ed43d..3d76507 100644
+--- a/Documentation/laptops/thinkpad-acpi.txt
++++ b/Documentation/laptops/thinkpad-acpi.txt
+@@ -1157,10 +1157,15 @@ display backlight brightness control methods have 16 levels, ranging
+ from 0 to 15.
+ There are two interfaces to the firmware for direct brightness control,
+-EC and CMOS.  To select which one should be used, use the
++EC and UCMS (or CMOS).  To select which one should be used, use the
+ brightness_mode module parameter: brightness_mode=1 selects EC mode,
+-brightness_mode=2 selects CMOS mode, brightness_mode=3 selects both EC
+-and CMOS.  The driver tries to auto-detect which interface to use.
++brightness_mode=2 selects UCMS mode, brightness_mode=3 selects EC
++mode with NVRAM backing (so that brightness changes are remembered
++across shutdown/reboot).
++
++The driver tries to select which interface to use from a table of
++defaults for each ThinkPad model.  If it makes a wrong choice, please
++report this as a bug, so that we can fix it.
+ When display backlight brightness controls are available through the
+ standard ACPI interface, it is best to use it instead of this direct
+@@ -1498,6 +1503,7 @@ to enable more than one output class, just add their values.
+                               (bluetooth, WWAN, UWB...)
+       0x0008                  HKEY event interface, hotkeys
+       0x0010                  Fan control
++      0x0020                  Backlight brightness
+ There is also a kernel build option to enable more debugging
+ information, which may be necessary to debug driver problems.
+diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
+index 4eec770..ba3682c 100644
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -192,6 +192,7 @@ enum {
+ #define TPACPI_DBG_RFKILL     0x0004
+ #define TPACPI_DBG_HKEY               0x0008
+ #define TPACPI_DBG_FAN                0x0010
++#define TPACPI_DBG_BRGHT      0x0020
+ #define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off")
+ #define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
+@@ -274,7 +275,6 @@ static struct {
+ static struct {
+       u16 hotkey_mask_ff:1;
+-      u16 bright_cmos_ec_unsync:1;
+ } tp_warned;
+ struct thinkpad_id_data {
+@@ -5526,6 +5526,20 @@ static struct ibm_struct ecdump_driver_data = {
+ #define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen"
++/*
++ * ThinkPads can read brightness from two places: EC HBRV (0x31), or
++ * CMOS NVRAM byte 0x5E, bits 0-3.
++ *
++ * EC HBRV (0x31) has the following layout
++ *   Bit 7: unknown function
++ *   Bit 6: unknown function
++ *   Bit 5: Z: honour scale changes, NZ: ignore scale changes
++ *   Bit 4: must be set to zero to avoid problems
++ *   Bit 3-0: backlight brightness level
++ *
++ * brightness_get_raw returns status data in the HBRV layout
++ */
++
+ enum {
+       TP_EC_BACKLIGHT = 0x31,
+@@ -5535,108 +5549,164 @@ enum {
+       TP_EC_BACKLIGHT_MAPSW = 0x20,
+ };
++enum tpacpi_brightness_access_mode {
++      TPACPI_BRGHT_MODE_AUTO = 0,     /* Not implemented yet */
++      TPACPI_BRGHT_MODE_EC,           /* EC control */
++      TPACPI_BRGHT_MODE_UCMS_STEP,    /* UCMS step-based control */
++      TPACPI_BRGHT_MODE_ECNVRAM,      /* EC control w/ NVRAM store */
++      TPACPI_BRGHT_MODE_MAX
++};
++
+ static struct backlight_device *ibm_backlight_device;
+-static int brightness_mode;
++
++static enum tpacpi_brightness_access_mode brightness_mode =
++              TPACPI_BRGHT_MODE_MAX;
++
+ static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */
+ static struct mutex brightness_mutex;
+-/*
+- * ThinkPads can read brightness from two places: EC 0x31, or
+- * CMOS NVRAM byte 0x5E, bits 0-3.
+- *
+- * EC 0x31 has the following layout
+- *   Bit 7: unknown function
+- *   Bit 6: unknown function
+- *   Bit 5: Z: honour scale changes, NZ: ignore scale changes
+- *   Bit 4: must be set to zero to avoid problems
+- *   Bit 3-0: backlight brightness level
+- *
+- * brightness_get_raw returns status data in the EC 0x31 layout
+- */
+-static int brightness_get_raw(int *status)
++/* NVRAM brightness access,
++ * call with brightness_mutex held! */
++static unsigned int tpacpi_brightness_nvram_get(void)
+ {
+-      u8 lec = 0, lcmos = 0, level = 0;
++      u8 lnvram;
+-      if (brightness_mode & 1) {
+-              if (!acpi_ec_read(TP_EC_BACKLIGHT, &lec))
+-                      return -EIO;
+-              level = lec & TP_EC_BACKLIGHT_LVLMSK;
+-      };
+-      if (brightness_mode & 2) {
+-              lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS)
+-                       & TP_NVRAM_MASK_LEVEL_BRIGHTNESS)
+-                      >> TP_NVRAM_POS_LEVEL_BRIGHTNESS;
+-              lcmos &= (tp_features.bright_16levels)? 0x0f : 0x07;
+-              level = lcmos;
+-      }
+-
+-      if (brightness_mode == 3) {
+-              *status = lec;  /* Prefer EC, CMOS is just a backing store */
+-              lec &= TP_EC_BACKLIGHT_LVLMSK;
+-              if (lec == lcmos)
+-                      tp_warned.bright_cmos_ec_unsync = 0;
+-              else {
+-                      if (!tp_warned.bright_cmos_ec_unsync) {
+-                              printk(TPACPI_ERR
+-                                      "CMOS NVRAM (%u) and EC (%u) do not "
+-                                      "agree on display brightness level\n",
+-                                      (unsigned int) lcmos,
+-                                      (unsigned int) lec);
+-                              tp_warned.bright_cmos_ec_unsync = 1;
+-                      }
++      lnvram = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS)
++                & TP_NVRAM_MASK_LEVEL_BRIGHTNESS)
++                >> TP_NVRAM_POS_LEVEL_BRIGHTNESS;
++      lnvram &= (tp_features.bright_16levels) ? 0x0f : 0x07;
++
++      return lnvram;
++}
++
++static void tpacpi_brightness_checkpoint_nvram(void)
++{
++      u8 lec = 0;
++      u8 b_nvram;
++
++      if (brightness_mode != TPACPI_BRGHT_MODE_ECNVRAM)
++              return;
++
++      vdbg_printk(TPACPI_DBG_BRGHT,
++              "trying to checkpoint backlight level to NVRAM...\n");
++
++      if (mutex_lock_killable(&brightness_mutex) < 0)
++              return;
++
++      if (unlikely(!acpi_ec_read(TP_EC_BACKLIGHT, &lec)))
++              goto unlock;
++      lec &= TP_EC_BACKLIGHT_LVLMSK;
++      b_nvram = nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS);
++
++      if (lec != ((b_nvram & TP_NVRAM_MASK_LEVEL_BRIGHTNESS)
++                           >> TP_NVRAM_POS_LEVEL_BRIGHTNESS)) {
++              /* NVRAM needs update */
++              b_nvram &= ~(TP_NVRAM_MASK_LEVEL_BRIGHTNESS <<
++                              TP_NVRAM_POS_LEVEL_BRIGHTNESS);
++              b_nvram |= lec;
++              nvram_write_byte(b_nvram, TP_NVRAM_ADDR_BRIGHTNESS);
++              dbg_printk(TPACPI_DBG_BRGHT,
++                         "updated NVRAM backlight level to %u (0x%02x)\n",
++                         (unsigned int) lec, (unsigned int) b_nvram);
++      } else
++              vdbg_printk(TPACPI_DBG_BRGHT,
++                         "NVRAM backlight level already is %u (0x%02x)\n",
++                         (unsigned int) lec, (unsigned int) b_nvram);
++
++unlock:
++      mutex_unlock(&brightness_mutex);
++}
++
++
++/* call with brightness_mutex held! */
++static int tpacpi_brightness_get_raw(int *status)
++{
++      u8 lec = 0;
++
++      switch (brightness_mode) {
++      case TPACPI_BRGHT_MODE_UCMS_STEP:
++              *status = tpacpi_brightness_nvram_get();
++              return 0;
++      case TPACPI_BRGHT_MODE_EC:
++      case TPACPI_BRGHT_MODE_ECNVRAM:
++              if (unlikely(!acpi_ec_read(TP_EC_BACKLIGHT, &lec)))
+                       return -EIO;
+-              }
+-      } else {
+-              *status = level;
++              *status = lec;
++              return 0;
++      default:
++              return -ENXIO;
+       }
++}
++
++/* call with brightness_mutex held! */
++/* do NOT call with illegal backlight level value */
++static int tpacpi_brightness_set_ec(unsigned int value)
++{
++      u8 lec = 0;
++
++      if (unlikely(!acpi_ec_read(TP_EC_BACKLIGHT, &lec)))
++              return -EIO;
++
++      if (unlikely(!acpi_ec_write(TP_EC_BACKLIGHT,
++                              (lec & TP_EC_BACKLIGHT_CMDMSK) |
++                              (value & TP_EC_BACKLIGHT_LVLMSK))))
++              return -EIO;
++
++      return 0;
++}
++
++/* call with brightness_mutex held! */
++static int tpacpi_brightness_set_ucmsstep(unsigned int value)
++{
++      int cmos_cmd, inc;
++      unsigned int current_value, i;
++
++      current_value = tpacpi_brightness_nvram_get();
++
++      if (value == current_value)
++              return 0;
++
++      cmos_cmd = (value > current_value) ?
++                      TP_CMOS_BRIGHTNESS_UP :
++                      TP_CMOS_BRIGHTNESS_DOWN;
++      inc = (value > current_value) ? 1 : -1;
++
++      for (i = current_value; i != value; i += inc)
++              if (issue_thinkpad_cmos_command(cmos_cmd))
++                      return -EIO;
+       return 0;
+ }
+ /* May return EINTR which can always be mapped to ERESTARTSYS */
+-static int brightness_set(int value)
++static int brightness_set(unsigned int value)
+ {
+-      int cmos_cmd, inc, i, res;
+-      int current_value;
+-      int command_bits;
++      int res;
+       if (value > ((tp_features.bright_16levels)? 15 : 7) ||
+           value < 0)
+               return -EINVAL;
++      vdbg_printk(TPACPI_DBG_BRGHT,
++                      "set backlight level to %d\n", value);
++
+       res = mutex_lock_killable(&brightness_mutex);
+       if (res < 0)
+               return res;
+-      res = brightness_get_raw(&current_value);
+-      if (res < 0)
+-              goto errout;
+-
+-      command_bits = current_value & TP_EC_BACKLIGHT_CMDMSK;
+-      current_value &= TP_EC_BACKLIGHT_LVLMSK;
+-
+-      cmos_cmd = value > current_value ?
+-                      TP_CMOS_BRIGHTNESS_UP :
+-                      TP_CMOS_BRIGHTNESS_DOWN;
+-      inc = (value > current_value)? 1 : -1;
+-
+-      res = 0;
+-      for (i = current_value; i != value; i += inc) {
+-              if ((brightness_mode & 2) &&
+-                  issue_thinkpad_cmos_command(cmos_cmd)) {
+-                      res = -EIO;
+-                      goto errout;
+-              }
+-              if ((brightness_mode & 1) &&
+-                  !acpi_ec_write(TP_EC_BACKLIGHT,
+-                                 (i + inc) | command_bits)) {
+-                      res = -EIO;
+-                      goto errout;;
+-              }
++      switch (brightness_mode) {
++      case TPACPI_BRGHT_MODE_EC:
++      case TPACPI_BRGHT_MODE_ECNVRAM:
++              res = tpacpi_brightness_set_ec(value);
++              break;
++      case TPACPI_BRGHT_MODE_UCMS_STEP:
++              res = tpacpi_brightness_set_ucmsstep(value);
++              break;
++      default:
++              res = -ENXIO;
+       }
+-errout:
+       mutex_unlock(&brightness_mutex);
+       return res;
+ }
+@@ -5645,21 +5715,34 @@ errout:
+ static int brightness_update_status(struct backlight_device *bd)
+ {
+-      /* it is the backlight class's job (caller) to handle
+-       * EINTR and other errors properly */
+-      return brightness_set(
++      unsigned int level =
+               (bd->props.fb_blank == FB_BLANK_UNBLANK &&
+                bd->props.power == FB_BLANK_UNBLANK) ?
+-                              bd->props.brightness : 0);
++                              bd->props.brightness : 0;
++
++      dbg_printk(TPACPI_DBG_BRGHT,
++                      "backlight: attempt to set level to %d\n",
++                      level);
++
++      /* it is the backlight class's job (caller) to handle
++       * EINTR and other errors properly */
++      return brightness_set(level);
+ }
+ static int brightness_get(struct backlight_device *bd)
+ {
+       int status, res;
+-      res = brightness_get_raw(&status);
++      res = mutex_lock_killable(&brightness_mutex);
+       if (res < 0)
+-              return 0; /* FIXME: teach backlight about error handling */
++              return 0;
++
++      res = tpacpi_brightness_get_raw(&status);
++
++      mutex_unlock(&brightness_mutex);
++
++      if (res < 0)
++              return 0;
+       return status & TP_EC_BACKLIGHT_LVLMSK;
+ }
+@@ -5709,7 +5792,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
+       }
+       if (!brightness_enable) {
+-              dbg_printk(TPACPI_DBG_INIT,
++              dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
+                          "brightness support disabled by "
+                          "module parameter\n");
+               return 1;
+@@ -5724,20 +5807,38 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
+       if (b == 16)
+               tp_features.bright_16levels = 1;
+-      if (!brightness_mode) {
+-              if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO)
+-                      brightness_mode = 2;
+-              else
+-                      brightness_mode = 3;
++      /*
++       * Check for module parameter bogosity, note that we
++       * init brightness_mode to TPACPI_BRGHT_MODE_MAX in order to be
++       * able to detect "unspecified"
++       */
++      if (brightness_mode > TPACPI_BRGHT_MODE_MAX)
++              return -EINVAL;
+-              dbg_printk(TPACPI_DBG_INIT, "selected brightness_mode=%d\n",
+-                      brightness_mode);
+-      }
++      /* TPACPI_BRGHT_MODE_AUTO not implemented yet, just use default */
++      if (brightness_mode == TPACPI_BRGHT_MODE_AUTO ||
++          brightness_mode == TPACPI_BRGHT_MODE_MAX) {
++              if (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) {
++                      /*
++                       * IBM models that define HBRV probably have
++                       * EC-based backlight level control
++                       */
++                      if (acpi_evalf(ec_handle, NULL, "HBRV", "qd"))
++                              /* T40-T43, R50-R52, R50e, R51e, X31-X41 */
++                              brightness_mode = TPACPI_BRGHT_MODE_ECNVRAM;
++                      else
++                              /* all other IBM ThinkPads */
++                              brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP;
++              } else
++                      /* All Lenovo ThinkPads */
++                      brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP;
+-      if (brightness_mode > 3)
+-              return -EINVAL;
++              dbg_printk(TPACPI_DBG_BRGHT,
++                         "selected brightness_mode=%d\n",
++                         brightness_mode);
++      }
+-      if (brightness_get_raw(&b) < 0)
++      if (tpacpi_brightness_get_raw(&b) < 0)
+               return 1;
+       if (tp_features.bright_16levels)
+@@ -5751,7 +5852,8 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
+               printk(TPACPI_ERR "Could not register backlight device\n");
+               return PTR_ERR(ibm_backlight_device);
+       }
+-      vdbg_printk(TPACPI_DBG_INIT, "brightness is supported\n");
++      vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
++                      "brightness is supported\n");
+       ibm_backlight_device->props.max_brightness =
+                               (tp_features.bright_16levels)? 15 : 7;
+@@ -5761,13 +5863,25 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
+       return 0;
+ }
++static void brightness_suspend(pm_message_t state)
++{
++      tpacpi_brightness_checkpoint_nvram();
++}
++
++static void brightness_shutdown(void)
++{
++      tpacpi_brightness_checkpoint_nvram();
++}
++
+ static void brightness_exit(void)
+ {
+       if (ibm_backlight_device) {
+-              vdbg_printk(TPACPI_DBG_EXIT,
++              vdbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_BRGHT,
+                           "calling backlight_device_unregister()\n");
+               backlight_device_unregister(ibm_backlight_device);
+       }
++
++      tpacpi_brightness_checkpoint_nvram();
+ }
+ static int brightness_read(char *p)
+@@ -5814,6 +5928,9 @@ static int brightness_write(char *buf)
+                       return -EINVAL;
+       }
++      tpacpi_disclose_usertask("procfs brightness",
++                      "set level to %d\n", level);
++
+       /*
+        * Now we know what the final level should be, so we try to set it.
+        * Doing it this way makes the syscall restartable in case of EINTR
+@@ -5827,6 +5944,8 @@ static struct ibm_struct brightness_driver_data = {
+       .read = brightness_read,
+       .write = brightness_write,
+       .exit = brightness_exit,
++      .suspend = brightness_suspend,
++      .shutdown = brightness_shutdown,
+ };
+ /*************************************************************************
+@@ -7465,10 +7584,10 @@ module_param_named(fan_control, fan_control_allowed, bool, 0);
+ MODULE_PARM_DESC(fan_control,
+                "Enables setting fan parameters features when true");
+-module_param_named(brightness_mode, brightness_mode, int, 0);
++module_param_named(brightness_mode, brightness_mode, uint, 0);
+ MODULE_PARM_DESC(brightness_mode,
+                "Selects brightness control strategy: "
+-               "0=auto, 1=EC, 2=CMOS, 3=both");
++               "0=auto, 1=EC, 2=UCMS, 3=EC+NVRAM");
+ module_param(brightness_enable, uint, 0);
+ MODULE_PARM_DESC(brightness_enable,
+-- 
+1.6.2.1
+