lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 16 Dec 2010 10:33:08 -0500
From:	Matthew Garrett <mjg@...hat.com>
To:	rydberg@...omail.se
Cc:	linux-kernel@...r.kernel.org, lm-sensors@...sensors.org,
	Matthew Garrett <mjg@...hat.com>
Subject: [PATCH 1/2] applesmc: Use PnP rather than hardcoding resources and devices

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@...hat.com>
---
 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;
+
 /* 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;
+
+	pnp_set_drvdata(dev, applesmc_pnp_device);
+
+	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")) {
+		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);
 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);
+
 	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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ