Re: [PATCH 1/2] applesmc: Use PnP rather than hardcoding resources and devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Dec 16, 2010 at 10:33:08AM -0500, Matthew Garrett wrote:
> The AppleSMC device is described in ACPI, including a list of its resources.
> We should use those rather than hardcoding the ports. A side-effect is that
> we can then remove the DMI matching, since there's a unique identifier to
> indicate that the machine has one of these devices.
> 
> Signed-off-by: Matthew Garrett <mjg@xxxxxxxxxx>

Matthew,

I am having trouble applying this patch to my -next tree. The driver there
(and in the official -next tree) has subtle differences to your version.
What tree is your patch based on ? Can you rebase it to the -next tree and resubmit ?

Couple of comments below; not necessarily complete, since I can not apply the patch.
I hope Henrik can comment on the merits of the patch itself, ie if it is known to work
with all systems.

Thanks,
Guenter

> ---
>  drivers/hwmon/applesmc.c |  185 +++++++++++++++++++++++-----------------------
>  1 files changed, 91 insertions(+), 94 deletions(-)
> 
> diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
> index ee91d69..dbe3fa6 100644
> --- a/drivers/hwmon/applesmc.c
> +++ b/drivers/hwmon/applesmc.c
> @@ -30,7 +30,6 @@
>  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> 
>  #include <linux/delay.h>
> -#include <linux/platform_device.h>
>  #include <linux/input-polldev.h>
>  #include <linux/kernel.h>
>  #include <linux/slab.h>
> @@ -43,11 +42,13 @@
>  #include <linux/leds.h>
>  #include <linux/hwmon.h>
>  #include <linux/workqueue.h>
> +#include <linux/slab.h>
> +#include <linux/pnp.h>
> 
>  /* data port used by Apple SMC */
> -#define APPLESMC_DATA_PORT     0x300
> +#define APPLESMC_DATA_PORT     0x0
>  /* command/status port used by Apple SMC */
> -#define APPLESMC_CMD_PORT      0x304
> +#define APPLESMC_CMD_PORT      0x4
> 
>  #define APPLESMC_NR_PORTS      32 /* 0x300-0x31f */
> 
> @@ -76,6 +77,8 @@
>  #define MOTION_SENSOR_Z_KEY    "MO_Z" /* r-o sp78 (2 bytes) */
>  #define MOTION_SENSOR_KEY      "MOCN" /* r/w ui16 */
> 
> +#define NOTIFICATION_KEY       "NTOK"
> +
>  #define FANS_COUNT             "FNum" /* r-o ui8 */
>  #define FANS_MANUAL            "FS! " /* r-w ui16 */
>  #define FAN_ID_FMT             "F%dID" /* r-o char[16] */
> @@ -103,6 +106,14 @@ static const char *const fan_speed_fmt[] = {
>  #define to_index(attr) (to_sensor_dev_attr(attr)->index & 0xffff)
>  #define to_option(attr) (to_sensor_dev_attr(attr)->index >> 16)
> 
> +struct applesmc_pnp_device {
> +       int iobase;
> +       int iolen;
> +};
> +
> +struct pnp_dev *pdev;
> +struct applesmc_pnp_device *pnp_device;
> +
Please make those variables static.

>  /* Dynamic device node attributes */
>  struct applesmc_dev_attr {
>         struct sensor_device_attribute sda;     /* hwmon attributes */
> @@ -143,7 +154,6 @@ static struct applesmc_registers {
>  } smcreg;
> 
>  static const int debug;
> -static struct platform_device *pdev;
>  static s16 rest_x;
>  static s16 rest_y;
>  static u8 backlight_state[2];
> @@ -159,6 +169,16 @@ static unsigned int key_at_index;
> 
>  static struct workqueue_struct *applesmc_led_wq;
> 
> +static u8 applesmc_read_reg(u8 reg)
> +{
> +       return inb(pnp_device->iobase + reg);
> +}
> +
> +static void applesmc_write_reg(u8 val, u8 reg)
> +{
> +       outb(val, pnp_device->iobase + reg);
> +}
> +
>  /*
>   * __wait_status - Wait up to 32ms for the status port to get a certain value
>   * (masked with 0x0f), returning zero if the value is obtained.  Callers must
> @@ -172,7 +192,8 @@ static int __wait_status(u8 val)
> 
>         for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
>                 udelay(us);
> -               if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) {
> +               if ((applesmc_read_reg(APPLESMC_CMD_PORT)
> +                    & APPLESMC_STATUS_MASK) == val) {
>                         return 0;
>                 }
>         }
> @@ -189,9 +210,10 @@ static int send_command(u8 cmd)
>  {
>         int us;
>         for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
> -               outb(cmd, APPLESMC_CMD_PORT);
> +               applesmc_write_reg(cmd, APPLESMC_CMD_PORT);
>                 udelay(us);
> -               if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c)
> +               if ((applesmc_read_reg(APPLESMC_CMD_PORT)
> +                    & APPLESMC_STATUS_MASK) == 0x0c)
>                         return 0;
>         }
>         return -EIO;
> @@ -202,7 +224,7 @@ static int send_argument(const char *key)
>         int i;
> 
>         for (i = 0; i < 4; i++) {
> -               outb(key[i], APPLESMC_DATA_PORT);
> +               applesmc_write_reg(key[i], APPLESMC_DATA_PORT);
>                 if (__wait_status(0x04))
>                         return -EIO;
>         }
> @@ -218,14 +240,14 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
>                 return -EIO;
>         }
> 
> -       outb(len, APPLESMC_DATA_PORT);
> +       applesmc_write_reg(len, APPLESMC_DATA_PORT);
> 
>         for (i = 0; i < len; i++) {
>                 if (__wait_status(0x05)) {
>                         pr_warn("%s: read data fail\n", key);
>                         return -EIO;
>                 }
> -               buffer[i] = inb(APPLESMC_DATA_PORT);
> +               buffer[i] = applesmc_read_reg(APPLESMC_DATA_PORT);
>         }
> 
>         return 0;
> @@ -240,14 +262,14 @@ static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
>                 return -EIO;
>         }
> 
> -       outb(len, APPLESMC_DATA_PORT);
> +       applesmc_write_reg(len, APPLESMC_DATA_PORT);
> 
>         for (i = 0; i < len; i++) {
>                 if (__wait_status(0x04)) {
>                         pr_warn("%s: write data fail\n", key);
>                         return -EIO;
>                 }
> -               outb(buffer[i], APPLESMC_DATA_PORT);
> +               applesmc_write_reg(buffer[i], APPLESMC_DATA_PORT);
>         }
> 
>         return 0;
> @@ -566,20 +588,6 @@ static void applesmc_destroy_smcreg(void)
>         memset(&smcreg, 0, sizeof(smcreg));
>  }
> 
> -/* Device model stuff */
> -static int applesmc_probe(struct platform_device *dev)
> -{
> -       int ret;
> -
> -       ret = applesmc_init_smcreg();
> -       if (ret)
> -               return ret;
> -
> -       applesmc_device_init();
> -
> -       return 0;
> -}
> -
>  /* Synchronize device with memorized backlight state */
>  static int applesmc_pm_resume(struct device *dev)
>  {
> @@ -600,15 +608,6 @@ static const struct dev_pm_ops applesmc_pm_ops = {
>         .restore = applesmc_pm_restore,
>  };
> 
> -static struct platform_driver applesmc_driver = {
> -       .probe = applesmc_probe,
> -       .driver = {
> -               .name = "applesmc",
> -               .owner = THIS_MODULE,
> -               .pm = &applesmc_pm_ops,
> -       },
> -};
> -
>  /*
>   * applesmc_calibrate - Set our "resting" values.  Callers must
>   * hold applesmc_lock.
> @@ -1174,72 +1173,48 @@ static void applesmc_release_key_backlight(void)
>         destroy_workqueue(applesmc_led_wq);
>  }
> 
> -static int applesmc_dmi_match(const struct dmi_system_id *id)
> +static int __devinit applesmc_pnp_probe(struct pnp_dev *dev,
> +                                       const struct pnp_device_id *dev_id)
>  {
> -       return 1;
> -}
> +       int ret;
> +       struct resource *res;
> +       struct applesmc_pnp_device *applesmc_pnp_device;
> 
> -/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
> - * So we need to put "Apple MacBook Pro" before "Apple MacBook". */
> -static __initdata struct dmi_system_id applesmc_whitelist[] = {
> -       { applesmc_dmi_match, "Apple MacBook Air", {
> -         DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
> -         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") },
> -       },
> -       { applesmc_dmi_match, "Apple MacBook Pro", {
> -         DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
> -         DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") },
> -       },
> -       { applesmc_dmi_match, "Apple MacBook", {
> -         DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
> -         DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") },
> -       },
> -       { applesmc_dmi_match, "Apple Macmini", {
> -         DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
> -         DMI_MATCH(DMI_PRODUCT_NAME,"Macmini") },
> -       },
> -       { applesmc_dmi_match, "Apple MacPro", {
> -         DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
> -         DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") },
> -       },
> -       { applesmc_dmi_match, "Apple iMac", {
> -         DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
> -         DMI_MATCH(DMI_PRODUCT_NAME,"iMac") },
> -       },
> -       { .ident = NULL }
> -};
> +       pdev = dev;
> 
> -static int __init applesmc_init(void)
> -{
> -       int ret;
> +       applesmc_pnp_device = kzalloc(sizeof(struct applesmc_pnp_device),
> +                                     GFP_KERNEL);
> 
> -       if (!dmi_check_system(applesmc_whitelist)) {
> -               pr_warn("supported laptop not found!\n");
> -               ret = -ENODEV;
> +       if (!applesmc_pnp_device) {
> +               ret = -ENOMEM;
>                 goto out;
>         }
> 
> -       if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS,
> -                                                               "applesmc")) {
> +       pnp_device = applesmc_pnp_device;
> +
Just wondering ...  applesmc_pnp_device doesn't seem to be necessary. 
Why not just use the global variable directly if you have it anyway ?

> +       pnp_set_drvdata(dev, applesmc_pnp_device);
> +

... but then since you assign it to drvdata, can you get rid of the global variable 
and use pnp_get_drvdata() whereever it is needed instead ?

> +       res = pnp_get_resource(dev, IORESOURCE_IO, 0);
> +
> +       if (!res) {
>                 ret = -ENXIO;
>                 goto out;
>         }
> 
> -       ret = platform_driver_register(&applesmc_driver);
> -       if (ret)
> -               goto out_region;
> +       applesmc_pnp_device->iobase = res->start;
> +       applesmc_pnp_device->iolen = res->end - res->start + 1;
> 
> -       pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT,
> -                                              NULL, 0);
> -       if (IS_ERR(pdev)) {
> -               ret = PTR_ERR(pdev);
> -               goto out_driver;
> +       if (!request_region(pnp_device->iobase, pnp_device->iolen, "applesmc")) {

This line has more than 80 columns.

> +               ret = -ENXIO;
> +               goto out;
>         }
> 
>         /* create register cache */
>         ret = applesmc_init_smcreg();
>         if (ret)
> -               goto out_device;
> +               goto out_region;
> +
> +       applesmc_device_init();
> 
>         ret = applesmc_create_nodes(info_group, 1);
>         if (ret)
> @@ -1287,19 +1262,17 @@ out_info:
>         applesmc_destroy_nodes(info_group);
>  out_smcreg:
>         applesmc_destroy_smcreg();
> -out_device:
> -       platform_device_unregister(pdev);
> -out_driver:
> -       platform_driver_unregister(&applesmc_driver);
>  out_region:
> -       release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
> +       release_region(pnp_device->iobase, pnp_device->iolen);

No kfree() of applesmc_pnp_device, so you are leaking memory here.

>  out:
>         pr_warn("driver init failed (ret=%d)!\n", ret);
>         return ret;
>  }
> 
> -static void __exit applesmc_exit(void)
> +static void __devexit applesmc_pnp_remove(struct pnp_dev *dev)
>  {
> +       struct applesmc_pnp_device *applesmc_pnp_device = pnp_get_drvdata(dev);
> +

Why bother with this, as it is assigned to pnp_device ?

>         hwmon_device_unregister(hwmon_dev);
>         applesmc_release_key_backlight();
>         applesmc_release_light_sensor();
> @@ -1308,9 +1281,33 @@ static void __exit applesmc_exit(void)
>         applesmc_destroy_nodes(fan_group);
>         applesmc_destroy_nodes(info_group);
>         applesmc_destroy_smcreg();
> -       platform_device_unregister(pdev);
> -       platform_driver_unregister(&applesmc_driver);
> -       release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
> +       release_region(pnp_device->iobase, pnp_device->iolen);
> +       kfree(applesmc_pnp_device);
> +}
> +
> +static const struct pnp_device_id applesmc_dev_table[] = {
> +       {"APP0001", 0},
> +       {"", 0},
> +};
> +
> +static struct pnp_driver applesmc_pnp_driver = {
> +       .name           = "Apple SMC",
> +       .probe          = applesmc_pnp_probe,
> +       .remove         = applesmc_pnp_remove,
> +       .id_table       = applesmc_dev_table,
> +       .driver = {
> +               .pm     = &applesmc_pm_ops,
> +       },
> +};
> +
> +static int __init applesmc_init(void)
> +{
> +       return pnp_register_driver(&applesmc_pnp_driver);
> +}
> +
> +static void __exit applesmc_exit(void)
> +{
> +       pnp_unregister_driver(&applesmc_pnp_driver);
>  }
> 
>  module_init(applesmc_init);
> @@ -1319,4 +1316,4 @@ module_exit(applesmc_exit);
>  MODULE_AUTHOR("Nicolas Boichat");
>  MODULE_DESCRIPTION("Apple SMC");
>  MODULE_LICENSE("GPL v2");
> -MODULE_DEVICE_TABLE(dmi, applesmc_whitelist);
> +MODULE_DEVICE_TABLE(pnp, applesmc_dev_table);
> --
> 1.7.3.3
> 
> 
> _______________________________________________
> lm-sensors mailing list
> lm-sensors@xxxxxxxxxxxxxx
> http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

_______________________________________________
lm-sensors mailing list
lm-sensors@xxxxxxxxxxxxxx
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors


[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux