Ver código fonte

Merge branches 'release' and 'autoload' into release

Len Brown 17 anos atrás
pai
commit
8f859016ea
4 arquivos alterados com 98 adições e 15 exclusões
  1. 6 0
      drivers/acpi/bay.c
  2. 6 0
      drivers/acpi/dock.c
  3. 85 15
      drivers/acpi/scan.c
  4. 1 0
      include/acpi/acpi_drivers.h

+ 6 - 0
drivers/acpi/bay.c

@@ -46,6 +46,12 @@ MODULE_LICENSE("GPL");
 	printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); }
 static void bay_notify(acpi_handle handle, u32 event, void *data);
 
+static const struct acpi_device_id bay_device_ids[] = {
+	{"LNXIOBAY", 0},
+	{"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, bay_device_ids);
+
 struct bay {
 	acpi_handle handle;
 	char *name;

+ 6 - 0
drivers/acpi/dock.c

@@ -51,6 +51,12 @@ static struct atomic_notifier_head dock_notifier_list;
 static struct platform_device *dock_device;
 static char dock_device_name[] = "dock";
 
+static const struct acpi_device_id dock_device_ids[] = {
+	{"LNXDOCK", 0},
+	{"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, dock_device_ids);
+
 struct dock_station {
 	acpi_handle handle;
 	unsigned long last_dock_time;

+ 85 - 15
drivers/acpi/scan.c

@@ -941,6 +941,15 @@ static int acpi_bay_match(struct acpi_device *device){
 	return -ENODEV;
 }
 
+/*
+ * acpi_dock_match - see if a device has a _DCK method
+ */
+static int acpi_dock_match(struct acpi_device *device)
+{
+	acpi_handle tmp;
+	return acpi_get_handle(device->handle, "_DCK", &tmp);
+}
+
 static void acpi_device_set_id(struct acpi_device *device,
 			       struct acpi_device *parent, acpi_handle handle,
 			       int type)
@@ -950,6 +959,7 @@ static void acpi_device_set_id(struct acpi_device *device,
 	char *hid = NULL;
 	char *uid = NULL;
 	struct acpi_compatible_id_list *cid_list = NULL;
+	const char *cid_add = NULL;
 	acpi_status status;
 
 	switch (type) {
@@ -972,15 +982,18 @@ static void acpi_device_set_id(struct acpi_device *device,
 			device->flags.bus_address = 1;
 		}
 
-		if(!(info->valid & (ACPI_VALID_HID | ACPI_VALID_CID))){
-			status = acpi_video_bus_match(device);
-			if(ACPI_SUCCESS(status))
-				hid = ACPI_VIDEO_HID;
+		/* If we have a video/bay/dock device, add our selfdefined
+		   HID to the CID list. Like that the video/bay/dock drivers
+		   will get autoloaded and the device might still match
+		   against another driver.
+		*/
+		if (ACPI_SUCCESS(acpi_video_bus_match(device)))
+			cid_add = ACPI_VIDEO_HID;
+		else if (ACPI_SUCCESS(acpi_bay_match(device)))
+			cid_add = ACPI_BAY_HID;
+		else if (ACPI_SUCCESS(acpi_dock_match(device)))
+			cid_add = ACPI_DOCK_HID;
 
-			status = acpi_bay_match(device);
-			if (ACPI_SUCCESS(status))
-				hid = ACPI_BAY_HID;
-		}
 		break;
 	case ACPI_BUS_TYPE_POWER:
 		hid = ACPI_POWER_HID;
@@ -1021,11 +1034,44 @@ static void acpi_device_set_id(struct acpi_device *device,
 		strcpy(device->pnp.unique_id, uid);
 		device->flags.unique_id = 1;
 	}
-	if (cid_list) {
-		device->pnp.cid_list = kmalloc(cid_list->size, GFP_KERNEL);
-		if (device->pnp.cid_list)
-			memcpy(device->pnp.cid_list, cid_list, cid_list->size);
-		else
+	if (cid_list || cid_add) {
+		struct  acpi_compatible_id_list *list;
+		int size = 0;
+		int count = 0;
+
+		if (cid_list) {
+			size = cid_list->size;
+		} else if (cid_add) {
+			size = sizeof(struct acpi_compatible_id_list);
+			cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size);
+			if (!cid_list) {
+				printk(KERN_ERR "Memory allocation error\n");
+				kfree(buffer.pointer);
+				return;
+			} else {
+				cid_list->count = 0;
+				cid_list->size = size;
+			}
+		}
+		if (cid_add)
+			size += sizeof(struct acpi_compatible_id);
+		list = kmalloc(size, GFP_KERNEL);
+
+		if (list) {
+			if (cid_list) {
+				memcpy(list, cid_list, cid_list->size);
+				count = cid_list->count;
+			}
+			if (cid_add) {
+				strncpy(list->id[count].value, cid_add,
+					ACPI_MAX_CID_LENGTH);
+				count++;
+				device->flags.compatible_ids = 1;
+			}
+			list->size = size;
+			list->count = count;
+			device->pnp.cid_list = list;
+		} else
 			printk(KERN_ERR "Memory allocation error\n");
 	}
 
@@ -1080,6 +1126,20 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
 	return 0;
 }
 
+static int
+acpi_is_child_device(struct acpi_device *device,
+			int (*matcher)(struct acpi_device *))
+{
+	int result = -ENODEV;
+
+	do {
+		if (ACPI_SUCCESS(matcher(device)))
+			return AE_OK;
+	} while ((device = device->parent));
+
+	return result;
+}
+
 static int
 acpi_add_single_object(struct acpi_device **child,
 		       struct acpi_device *parent, acpi_handle handle, int type,
@@ -1131,10 +1191,20 @@ acpi_add_single_object(struct acpi_device **child,
 	case ACPI_BUS_TYPE_PROCESSOR:
 	case ACPI_BUS_TYPE_DEVICE:
 		result = acpi_bus_get_status(device);
-		if (ACPI_FAILURE(result) || !device->status.present) {
-			result = -ENOENT;
+		if (ACPI_FAILURE(result)) {
+			result = -ENODEV;
 			goto end;
 		}
+		if (!device->status.present) {
+			/* Bay and dock should be handled even if absent */
+			if (!ACPI_SUCCESS(
+			     acpi_is_child_device(device, acpi_bay_match)) &&
+			    !ACPI_SUCCESS(
+			     acpi_is_child_device(device, acpi_dock_match))) {
+					result = -ENODEV;
+					goto end;
+			}
+		}
 		break;
 	default:
 		STRUCT_TO_INT(device->status) =

+ 1 - 0
include/acpi/acpi_drivers.h

@@ -48,6 +48,7 @@
 #define ACPI_BUTTON_HID_SLEEPF		"LNXSLPBN"
 #define ACPI_VIDEO_HID			"LNXVIDEO"
 #define ACPI_BAY_HID			"LNXIOBAY"
+#define ACPI_DOCK_HID			"LNXDOCK"
 
 /* --------------------------------------------------------------------------
                                        PCI