mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-09 22:50:41 +00:00
firewire: core: align driver match with modalias
The driver match strategy was: - Match vendor/model/specifier/version of the unit directory. - If that was a miss, match vendor from the root directory and model/specifier/version of the unit directory. This was inconsistent with how the modalias string was constructed until recently (take vendor/model from root directory and specifier/ version from unit directory). It was also inconsistent with how it is done since the parent commit: - Use vendor/model/specifier/version of the unit directory if possible, - fall back to one or more of vendor/model/specifier/version from the root directory depending on which ones are not present at the unit directory. Fix this inconsistency by sharing the ROM scanner function between modalias printer function and driver match function. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
This commit is contained in:
parent
5ae73518cb
commit
fe43d6d9cf
@ -127,60 +127,7 @@ int fw_csr_string(const u32 *directory, int key, char *buf, size_t size)
|
||||
}
|
||||
EXPORT_SYMBOL(fw_csr_string);
|
||||
|
||||
static bool is_fw_unit(struct device *dev);
|
||||
|
||||
static int match_unit_directory(const u32 *directory, u32 match_flags,
|
||||
const struct ieee1394_device_id *id)
|
||||
{
|
||||
struct fw_csr_iterator ci;
|
||||
int key, value, match;
|
||||
|
||||
match = 0;
|
||||
fw_csr_iterator_init(&ci, directory);
|
||||
while (fw_csr_iterator_next(&ci, &key, &value)) {
|
||||
if (key == CSR_VENDOR && value == id->vendor_id)
|
||||
match |= IEEE1394_MATCH_VENDOR_ID;
|
||||
if (key == CSR_MODEL && value == id->model_id)
|
||||
match |= IEEE1394_MATCH_MODEL_ID;
|
||||
if (key == CSR_SPECIFIER_ID && value == id->specifier_id)
|
||||
match |= IEEE1394_MATCH_SPECIFIER_ID;
|
||||
if (key == CSR_VERSION && value == id->version)
|
||||
match |= IEEE1394_MATCH_VERSION;
|
||||
}
|
||||
|
||||
return (match & match_flags) == match_flags;
|
||||
}
|
||||
|
||||
static int fw_unit_match(struct device *dev, struct device_driver *drv)
|
||||
{
|
||||
struct fw_unit *unit = fw_unit(dev);
|
||||
struct fw_device *device;
|
||||
const struct ieee1394_device_id *id;
|
||||
|
||||
/* We only allow binding to fw_units. */
|
||||
if (!is_fw_unit(dev))
|
||||
return 0;
|
||||
|
||||
device = fw_parent_device(unit);
|
||||
id = container_of(drv, struct fw_driver, driver)->id_table;
|
||||
|
||||
for (; id->match_flags != 0; id++) {
|
||||
if (match_unit_directory(unit->directory, id->match_flags, id))
|
||||
return 1;
|
||||
|
||||
/* Also check vendor ID in the root directory. */
|
||||
if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
|
||||
match_unit_directory(&device->config_rom[5],
|
||||
IEEE1394_MATCH_VENDOR_ID, id) &&
|
||||
match_unit_directory(unit->directory, id->match_flags
|
||||
& ~IEEE1394_MATCH_VENDOR_ID, id))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void get_modalias_ids(const u32 *directory, int *id)
|
||||
static void get_ids(const u32 *directory, int *id)
|
||||
{
|
||||
struct fw_csr_iterator ci;
|
||||
int key, value;
|
||||
@ -196,12 +143,54 @@ static void get_modalias_ids(const u32 *directory, int *id)
|
||||
}
|
||||
}
|
||||
|
||||
static void get_modalias_ids(struct fw_unit *unit, int *id)
|
||||
{
|
||||
get_ids(&fw_parent_device(unit)->config_rom[5], id);
|
||||
get_ids(unit->directory, id);
|
||||
}
|
||||
|
||||
static bool match_ids(const struct ieee1394_device_id *id_table, int *id)
|
||||
{
|
||||
int match = 0;
|
||||
|
||||
if (id[0] == id_table->vendor_id)
|
||||
match |= IEEE1394_MATCH_VENDOR_ID;
|
||||
if (id[1] == id_table->model_id)
|
||||
match |= IEEE1394_MATCH_MODEL_ID;
|
||||
if (id[2] == id_table->specifier_id)
|
||||
match |= IEEE1394_MATCH_SPECIFIER_ID;
|
||||
if (id[3] == id_table->version)
|
||||
match |= IEEE1394_MATCH_VERSION;
|
||||
|
||||
return (match & id_table->match_flags) == id_table->match_flags;
|
||||
}
|
||||
|
||||
static bool is_fw_unit(struct device *dev);
|
||||
|
||||
static int fw_unit_match(struct device *dev, struct device_driver *drv)
|
||||
{
|
||||
const struct ieee1394_device_id *id_table =
|
||||
container_of(drv, struct fw_driver, driver)->id_table;
|
||||
int id[] = {0, 0, 0, 0};
|
||||
|
||||
/* We only allow binding to fw_units. */
|
||||
if (!is_fw_unit(dev))
|
||||
return 0;
|
||||
|
||||
get_modalias_ids(fw_unit(dev), id);
|
||||
|
||||
for (; id_table->match_flags != 0; id_table++)
|
||||
if (match_ids(id_table, id))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size)
|
||||
{
|
||||
int id[] = {0, 0, 0, 0};
|
||||
|
||||
get_modalias_ids(&fw_parent_device(unit)->config_rom[5], id);
|
||||
get_modalias_ids(unit->directory, id);
|
||||
get_modalias_ids(unit, id);
|
||||
|
||||
return snprintf(buffer, buffer_size,
|
||||
"ieee1394:ven%08Xmo%08Xsp%08Xver%08X",
|
||||
|
Loading…
x
Reference in New Issue
Block a user