Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7f47fa6c authored by Bjorn Helgaas's avatar Bjorn Helgaas Committed by Len Brown
Browse files

ACPI: maintain a single list of _HID and _CID IDs



There's no need to treat _HID and _CID differently.  Keeping them in
a single list makes code that uses the IDs a little simpler because it
can just traverse the list rather than checking "do we have a HID?",
"do we have any CIDs?"

Signed-off-by: default avatarBjorn Helgaas <bjorn.helgaas@hp.com>
Reviewed-by: default avatarAlex Chiang <achiang@hp.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent b1fbfb2a
Loading
Loading
Loading
Loading
+46 −120
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
{
	int len;
	int count;
	struct acpi_hardware_id *id;

	if (!acpi_dev->flags.hardware_id && !acpi_dev->flags.compatible_ids)
		return -ENODEV;
@@ -52,33 +53,14 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
	len = snprintf(modalias, size, "acpi:");
	size -= len;

	if (acpi_dev->flags.hardware_id) {
		count = snprintf(&modalias[len], size, "%s:",
				 acpi_dev->pnp.hardware_id);
	list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
		count = snprintf(&modalias[len], size, "%s:", id->id);
		if (count < 0 || count >= size)
			return -EINVAL;
		len += count;
		size -= count;
	}

	if (acpi_dev->flags.compatible_ids) {
		struct acpica_device_id_list *cid_list;
		int i;

		cid_list = acpi_dev->pnp.cid_list;
		for (i = 0; i < cid_list->count; i++) {
			count = snprintf(&modalias[len], size, "%s:",
					 cid_list->ids[i].string);
			if (count < 0 || count >= size) {
				printk(KERN_ERR PREFIX "%s cid[%i] exceeds event buffer size",
				       acpi_dev->pnp.device_name, i);
				break;
			}
			len += count;
			size -= count;
		}
	}

	modalias[len] = '\0';
	return len;
}
@@ -273,6 +255,7 @@ int acpi_match_device_ids(struct acpi_device *device,
			  const struct acpi_device_id *ids)
{
	const struct acpi_device_id *id;
	struct acpi_hardware_id *hwid;

	/*
	 * If the device is not present, it is unnecessary to load device
@@ -281,40 +264,30 @@ int acpi_match_device_ids(struct acpi_device *device,
	if (!device->status.present)
		return -ENODEV;

	if (device->flags.hardware_id) {
		for (id = ids; id->id[0]; id++) {
			if (!strcmp((char*)id->id, device->pnp.hardware_id))
	for (id = ids; id->id[0]; id++)
		list_for_each_entry(hwid, &device->pnp.ids, list)
			if (!strcmp((char *) id->id, hwid->id))
				return 0;

	return -ENOENT;
}
	}
EXPORT_SYMBOL(acpi_match_device_ids);

	if (device->flags.compatible_ids) {
		struct acpica_device_id_list *cid_list = device->pnp.cid_list;
		int i;
static void acpi_free_ids(struct acpi_device *device)
{
	struct acpi_hardware_id *id, *tmp;

		for (id = ids; id->id[0]; id++) {
			/* compare multiple _CID entries against driver ids */
			for (i = 0; i < cid_list->count; i++) {
				if (!strcmp((char*)id->id,
					    cid_list->ids[i].string))
					return 0;
			}
	list_for_each_entry_safe(id, tmp, &device->pnp.ids, list) {
		kfree(id->id);
		kfree(id);
	}
}

	return -ENOENT;
}
EXPORT_SYMBOL(acpi_match_device_ids);

static void acpi_device_release(struct device *dev)
{
	struct acpi_device *acpi_dev = to_acpi_device(dev);

	kfree(acpi_dev->pnp.cid_list);
	if (acpi_dev->flags.hardware_id)
		kfree(acpi_dev->pnp.hardware_id);
	if (acpi_dev->flags.unique_id)
		kfree(acpi_dev->pnp.unique_id);
	acpi_free_ids(acpi_dev);
	kfree(acpi_dev);
}

@@ -1028,62 +1001,31 @@ static int acpi_dock_match(struct acpi_device *device)
	return acpi_get_handle(device->handle, "_DCK", &tmp);
}

static struct acpica_device_id_list*
acpi_add_cid(
	struct acpi_device_info         *info,
	struct acpica_device_id         *new_cid)
char *acpi_device_hid(struct acpi_device *device)
{
	struct acpica_device_id_list    *cid;
	char                            *next_id_string;
	acpi_size                       cid_length;
	acpi_size                       new_cid_length;
	u32                             i;

	struct acpi_hardware_id *hid;

	/* Allocate new CID list with room for the new CID */

	if (!new_cid)
		new_cid_length = info->compatible_id_list.list_size;
	else if (info->compatible_id_list.list_size)
		new_cid_length = info->compatible_id_list.list_size +
			new_cid->length + sizeof(struct acpica_device_id);
	else
		new_cid_length = sizeof(struct acpica_device_id_list) + new_cid->length;

	cid = ACPI_ALLOCATE_ZEROED(new_cid_length);
	if (!cid) {
		return NULL;
	hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list);
	return hid->id;
}
EXPORT_SYMBOL(acpi_device_hid);

	cid->list_size = new_cid_length;
	cid->count = info->compatible_id_list.count;
	if (new_cid)
		cid->count++;
	next_id_string = (char *) cid->ids + (cid->count * sizeof(struct acpica_device_id));

	/* Copy all existing CIDs */

	for (i = 0; i < info->compatible_id_list.count; i++) {
		cid_length = info->compatible_id_list.ids[i].length;
		cid->ids[i].string = next_id_string;
		cid->ids[i].length = cid_length;

		ACPI_MEMCPY(next_id_string, info->compatible_id_list.ids[i].string,
			cid_length);

		next_id_string += cid_length;
	}

	/* Append the new CID */
static void acpi_add_id(struct acpi_device *device, const char *dev_id)
{
	struct acpi_hardware_id *id;

	if (new_cid) {
		cid->ids[i].string = next_id_string;
		cid->ids[i].length = new_cid->length;
	id = kmalloc(sizeof(*id), GFP_KERNEL);
	if (!id)
		return;

		ACPI_MEMCPY(next_id_string, new_cid->string, new_cid->length);
	id->id = kmalloc(strlen(dev_id) + 1, GFP_KERNEL);
	if (!id->id) {
		kfree(id);
		return;
	}

	return cid;
	strcpy(id->id, dev_id);
	list_add_tail(&id->list, &device->pnp.ids);
}

static void acpi_device_set_id(struct acpi_device *device)
@@ -1094,6 +1036,7 @@ static void acpi_device_set_id(struct acpi_device *device)
	struct acpica_device_id_list *cid_list = NULL;
	char *cid_add = NULL;
	acpi_status status;
	int i;

	switch (device->device_type) {
	case ACPI_BUS_TYPE_DEVICE:
@@ -1166,15 +1109,9 @@ static void acpi_device_set_id(struct acpi_device *device)
		hid = "device";

	if (hid) {
		device->pnp.hardware_id = ACPI_ALLOCATE_ZEROED(strlen (hid) + 1);
		if (device->pnp.hardware_id) {
			strcpy(device->pnp.hardware_id, hid);
		acpi_add_id(device, hid);
		device->flags.hardware_id = 1;
	}
	}
	if (!device->flags.hardware_id)
		device->pnp.hardware_id = "";

	if (uid) {
		device->pnp.unique_id = ACPI_ALLOCATE_ZEROED(strlen (uid) + 1);
		if (device->pnp.unique_id) {
@@ -1185,25 +1122,13 @@ static void acpi_device_set_id(struct acpi_device *device)
	if (!device->flags.unique_id)
		device->pnp.unique_id = "";

	if (cid_list || cid_add) {
		struct acpica_device_id_list *list;

	if (cid_list)
		for (i = 0; i < cid_list->count; i++)
			acpi_add_id(device, cid_list->ids[i].string);
	if (cid_add) {
			struct acpica_device_id cid;
			cid.length = strlen (cid_add) + 1;
			cid.string = cid_add;

			list = acpi_add_cid(info, &cid);
		} else {
			list = acpi_add_cid(info, NULL);
		}

		if (list) {
			device->pnp.cid_list = list;
			if (cid_add)
		acpi_add_id(device, cid_add);
		device->flags.compatible_ids = 1;
	}
	}

	kfree(info);
}
@@ -1269,6 +1194,7 @@ static int acpi_add_single_object(struct acpi_device **child,
		return -ENOMEM;
	}

	INIT_LIST_HEAD(&device->pnp.ids);
	device->device_type = type;
	device->handle = handle;
	device->parent = acpi_bus_get_parent(handle);
+7 −9
Original line number Diff line number Diff line
@@ -153,6 +153,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
	acpi_handle temp = NULL;
	acpi_status status;
	struct pnp_dev *dev;
	struct acpi_hardware_id *id;

	/*
	 * If a PnPacpi device is not present , the device
@@ -193,15 +194,12 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
	if (dev->capabilities & PNP_CONFIGURABLE)
		pnpacpi_parse_resource_option_data(dev);

	if (device->flags.compatible_ids) {
		struct acpica_device_id_list *cid_list = device->pnp.cid_list;
		int i;

		for (i = 0; i < cid_list->count; i++) {
			if (!ispnpidacpi(cid_list->ids[i].string))
	list_for_each_entry(id, &device->pnp.ids, list) {
		if (!strcmp(id->id, acpi_device_hid(device)))
			continue;
			pnp_add_id(dev, cid_list->ids[i].string);
		}
		if (!ispnpidacpi(id->id))
			continue;
		pnp_add_id(dev, id->id);
	}

	/* clear out the damaged flags */
+7 −3
Original line number Diff line number Diff line
@@ -171,19 +171,23 @@ typedef unsigned long acpi_bus_address;
typedef char acpi_device_name[40];
typedef char acpi_device_class[20];

struct acpi_hardware_id {
	struct list_head list;
	char *id;
};

struct acpi_device_pnp {
	acpi_bus_id bus_id;	/* Object name */
	acpi_bus_address bus_address;	/* _ADR */
	char *hardware_id;	/* _HID */
	struct acpica_device_id_list *cid_list;	/* _CIDs */
	char *unique_id;	/* _UID */
	struct list_head ids;		/* _HID and _CIDs */
	acpi_device_name device_name;	/* Driver-determined */
	acpi_device_class device_class;	/*        "          */
};

#define acpi_device_bid(d)	((d)->pnp.bus_id)
#define acpi_device_adr(d)	((d)->pnp.bus_address)
#define acpi_device_hid(d)	((d)->pnp.hardware_id)
char *acpi_device_hid(struct acpi_device *device);
#define acpi_device_uid(d)	((d)->pnp.unique_id)
#define acpi_device_name(d)	((d)->pnp.device_name)
#define acpi_device_class(d)	((d)->pnp.device_class)