On Wed, Mar 25, 2015 at 03:46:07PM -0500, Suravee Suthikulpanit wrote: > Device drivers typically use ACPI _HIDs/_CIDs listed in struct device_driver > acpi_match_table to match devices. However, for generic drivers, we do not > want to list _HID for all supported devices. Also, certain classes of devices > do not have _CID (e.g. SATA, USB). Instead, we can leverage ACPI _CLS, > which specifies PCI-defined class code (i.e. base-class, subclass and > programming interface). This patch adds support for matching ACPI devices using > the _CLS method. > > To support loadable module, current design uses _HID or _CID to match device's > modalias. With the new way of matching with _CLS this would requires modification > to the current ACPI modalias key to include _CLS. This patch appends PCI-defined > class-code to the existing ACPI modalias as following. > > acpi:<HID>:<CID1>:<CID2>:..:<CIDn>:<bbsspp>: > E.g: > # cat /sys/devices/platform/AMDI0600:00/modalias > acpi:AMDI0600:010601: > > where bb is th base-class code, ss is te sub-class code, and pp is the > programming interface code > > Since there would not be _HID/_CID in the ACPI matching table of the driver, > this patch adds a field to acpi_device_id to specify the matching _CLS. > > static const struct acpi_device_id ahci_acpi_match[] = { > { ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xFFFFFF) }, > {}, > }; > > In this case, the corresponded entry in modules.alias file would be: > > alias acpi*:010601:* ahci_platform > > Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@xxxxxxx> > --- > drivers/acpi/scan.c | 39 +++++++++++++++++++++++++++++++++++---- > include/acpi/acnames.h | 1 + > include/acpi/actypes.h | 4 +++- > include/linux/mod_devicetable.h | 4 ++++ > scripts/mod/devicetable-offsets.c | 2 ++ > scripts/mod/file2alias.c | 32 ++++++++++++++++++++++++++++++-- > 6 files changed, 75 insertions(+), 7 deletions(-) > > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c > index 52a62aa..f26bf80 100644 > --- a/drivers/acpi/scan.c > +++ b/drivers/acpi/scan.c > @@ -895,6 +895,32 @@ static void acpi_device_remove_files(struct acpi_device *dev) > ACPI Bus operations > -------------------------------------------------------------------------- */ > > +static bool __acpi_match_device_cls(const struct acpi_device_id *id, > + struct acpi_hardware_id *hwid) > +{ > + int i, msk, byte_shift; > + bool found = true; > + char buf[3]; > + > + if (!id->cls) > + return false; > + > + /* Apply class-code bitmask, before checking each class-code byte */ > + for (i = 1; i <= 3; i++) { > + byte_shift = 8 * (3 - i); > + msk = (id->cls_msk >> byte_shift) & 0xFF; > + if (!msk) > + continue; > + > + sprintf(buf, "%02x", (id->cls >> byte_shift) & msk); > + if (strncmp(buf, &hwid->id[(i - 1) * 2], 2)) { > + found = false; > + break; You can return false directly here. > + } > + } > + return found; > +} > + > static const struct acpi_device_id *__acpi_match_device( > struct acpi_device *device, const struct acpi_device_id *ids) > { > @@ -908,11 +934,14 @@ static const struct acpi_device_id *__acpi_match_device( > if (!device->status.present) > return NULL; > > - for (id = ids; id->id[0]; id++) > - list_for_each_entry(hwid, &device->pnp.ids, list) > - if (!strcmp((char *) id->id, hwid->id)) > + for (id = ids; id->id[0] || id->cls; id++) { > + list_for_each_entry(hwid, &device->pnp.ids, list) { > + if (id->id[0] && !strcmp((char *) id->id, hwid->id)) > return id; > - > + else if (__acpi_match_device_cls(id, hwid)) > + return id; > + } > + } > return NULL; > } > > @@ -2005,6 +2034,8 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, > if (info->valid & ACPI_VALID_UID) > pnp->unique_id = kstrdup(info->unique_id.string, > GFP_KERNEL); > + if (info->valid & ACPI_VALID_CLS) > + acpi_add_id(pnp, info->cls.string); > > kfree(info); > > diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h > index 273de70..b52c0dc 100644 > --- a/include/acpi/acnames.h > +++ b/include/acpi/acnames.h > @@ -51,6 +51,7 @@ > #define METHOD_NAME__BBN "_BBN" > #define METHOD_NAME__CBA "_CBA" > #define METHOD_NAME__CID "_CID" > +#define METHOD_NAME__CLS "_CLS" > #define METHOD_NAME__CRS "_CRS" > #define METHOD_NAME__DDN "_DDN" > #define METHOD_NAME__HID "_HID" > diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h > index b034f10..ab3dac8 100644 > --- a/include/acpi/actypes.h > +++ b/include/acpi/actypes.h > @@ -1148,7 +1148,7 @@ struct acpi_device_info { > u32 name; /* ACPI object Name */ > acpi_object_type type; /* ACPI object Type */ > u8 param_count; /* If a method, required parameter count */ > - u8 valid; /* Indicates which optional fields are valid */ > + u16 valid; /* Indicates which optional fields are valid */ > u8 flags; /* Miscellaneous info */ > u8 highest_dstates[4]; /* _sx_d values: 0xFF indicates not valid */ > u8 lowest_dstates[5]; /* _sx_w values: 0xFF indicates not valid */ > @@ -1157,6 +1157,7 @@ struct acpi_device_info { > struct acpi_pnp_device_id hardware_id; /* _HID value */ > struct acpi_pnp_device_id unique_id; /* _UID value */ > struct acpi_pnp_device_id subsystem_id; /* _SUB value */ > + struct acpi_pnp_device_id cls; /* _CLS value */ > struct acpi_pnp_device_id_list compatible_id_list; /* _CID list <must be last> */ > }; > > @@ -1174,6 +1175,7 @@ struct acpi_device_info { > #define ACPI_VALID_CID 0x20 > #define ACPI_VALID_SXDS 0x40 > #define ACPI_VALID_SXWS 0x80 > +#define ACPI_VALID_CLS 0x100 > > /* Flags for _STA return value (current_status above) */ > > diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h > index e530533..9563abe 100644 > --- a/include/linux/mod_devicetable.h > +++ b/include/linux/mod_devicetable.h > @@ -189,8 +189,12 @@ struct css_device_id { > struct acpi_device_id { > __u8 id[ACPI_ID_LEN]; > kernel_ulong_t driver_data; > + __u32 cls; > + __u32 cls_msk; > }; > > +#define ACPI_DEVICE_CLASS(cls, msk) "", 0, cls, msk Consider moving this to <linux/acpi.h>, just like PCI_DEVICE_CLASS() is defined in <linux/pci.h>. Also please use designated initializers here, eg: #define ACPI_DEVICE_CLASS(cls, msk) .cls = (cls), .cls_mask = (msk) Once done you can add my, Acked-by: Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx> > + > #define PNP_ID_LEN 8 > #define PNP_MAX_DEVICES 8 -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html