sonypi: try to detect if sony-laptop has already taken one of the known ioports
authormalattia@linux.it <malattia@linux.it>
Sat, 28 Apr 2007 14:34:10 +0000 (23:34 +0900)
committerLen Brown <len.brown@intel.com>
Sun, 29 Apr 2007 02:05:59 +0000 (22:05 -0400)
Get the IO resources list in sony-laptop in the same order as listed
in sonypi and make sonypi check if one of those is already busy.
The sonypi check can be disabled by a module parameter in case the user
thinks we are plainly wrong (check_ioport=0).

Signed-off-by: Mattia Dongili <malattia@linux.it>
Signed-off-by: Len Brown <len.brown@intel.com>
drivers/char/sonypi.c
drivers/misc/sony-laptop.c

index 72cdddb0ee6f47883c0ecdd98370b32456446d25..b6998906b214b545d9b41feafa1054dbe6920b98 100644 (file)
@@ -97,6 +97,11 @@ module_param(useinput, int, 0444);
 MODULE_PARM_DESC(useinput,
                 "set this if you would like sonypi to feed events to the input subsystem");
 
+static int check_ioport = 1;
+module_param(check_ioport, int, 0444);
+MODULE_PARM_DESC(check_ioport,
+                "set this to 0 if you think the automatic ioport check for sony-laptop is wrong");
+
 #define SONYPI_DEVICE_MODEL_TYPE1      1
 #define SONYPI_DEVICE_MODEL_TYPE2      2
 #define SONYPI_DEVICE_MODEL_TYPE3      3
@@ -1262,6 +1267,28 @@ static int __devinit sonypi_create_input_devices(void)
 static int __devinit sonypi_setup_ioports(struct sonypi_device *dev,
                                const struct sonypi_ioport_list *ioport_list)
 {
+       /* try to detect if sony-laptop is being used and thus
+        * has already requested one of the known ioports.
+        * As in the deprecated check_region this is racy has we have
+        * multiple ioports available and one of them can be requested
+        * between this check and the subsequent request. Anyway, as an
+        * attempt to be some more user-friendly as we currently are,
+        * this is enough.
+        */
+       const struct sonypi_ioport_list *check = ioport_list;
+       while (check_ioport && check->port1) {
+               if (!request_region(check->port1,
+                                  sonypi_device.region_size,
+                                  "Sony Programable I/O Device Check")) {
+                       printk(KERN_ERR "sonypi: ioport 0x%.4x busy, using sony-laptop? "
+                                       "if not use check_ioport=0\n",
+                                       check->port1);
+                       return -EBUSY;
+               }
+               release_region(check->port1, sonypi_device.region_size);
+               check++;
+       }
+
        while (ioport_list->port1) {
 
                if (request_region(ioport_list->port1,
index 141284dee1a193be5b9d65fd5659a7e4d96e4936..2787e1ce8911e14a9e18344441d97548b21bf29f 100644 (file)
@@ -1801,7 +1801,7 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
                                if (!interrupt)
                                        return AE_ERROR;
 
-                               list_add(&interrupt->list, &dev->interrupts);
+                               list_add_tail(&interrupt->list, &dev->interrupts);
                                interrupt->irq.triggering = p->triggering;
                                interrupt->irq.polarity = p->polarity;
                                interrupt->irq.sharable = p->sharable;
@@ -1823,7 +1823,7 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
                        if (!ioport)
                                return AE_ERROR;
 
-                       list_add(&ioport->list, &dev->ioports);
+                       list_add_tail(&ioport->list, &dev->ioports);
                        memcpy(&ioport->io, io, sizeof(*io));
                        return AE_OK;
                }