Commit fe43d6d9 authored by Stefan Richter's avatar Stefan Richter

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: default avatarStefan Richter <stefanr@s5r6.in-berlin.de>
parent 5ae73518
...@@ -127,81 +127,70 @@ int fw_csr_string(const u32 *directory, int key, char *buf, size_t size) ...@@ -127,81 +127,70 @@ int fw_csr_string(const u32 *directory, int key, char *buf, size_t size)
} }
EXPORT_SYMBOL(fw_csr_string); EXPORT_SYMBOL(fw_csr_string);
static bool is_fw_unit(struct device *dev); static void get_ids(const u32 *directory, int *id)
static int match_unit_directory(const u32 *directory, u32 match_flags,
const struct ieee1394_device_id *id)
{ {
struct fw_csr_iterator ci; struct fw_csr_iterator ci;
int key, value, match; int key, value;
match = 0;
fw_csr_iterator_init(&ci, directory); fw_csr_iterator_init(&ci, directory);
while (fw_csr_iterator_next(&ci, &key, &value)) { while (fw_csr_iterator_next(&ci, &key, &value)) {
if (key == CSR_VENDOR && value == id->vendor_id) switch (key) {
match |= IEEE1394_MATCH_VENDOR_ID; case CSR_VENDOR: id[0] = value; break;
if (key == CSR_MODEL && value == id->model_id) case CSR_MODEL: id[1] = value; break;
match |= IEEE1394_MATCH_MODEL_ID; case CSR_SPECIFIER_ID: id[2] = value; break;
if (key == CSR_SPECIFIER_ID && value == id->specifier_id) case CSR_VERSION: id[3] = value; break;
match |= IEEE1394_MATCH_SPECIFIER_ID; }
if (key == CSR_VERSION && value == id->version)
match |= IEEE1394_MATCH_VERSION;
} }
}
return (match & match_flags) == match_flags; 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) static int fw_unit_match(struct device *dev, struct device_driver *drv)
{ {
struct fw_unit *unit = fw_unit(dev); const struct ieee1394_device_id *id_table =
struct fw_device *device; container_of(drv, struct fw_driver, driver)->id_table;
const struct ieee1394_device_id *id; int id[] = {0, 0, 0, 0};
/* We only allow binding to fw_units. */ /* We only allow binding to fw_units. */
if (!is_fw_unit(dev)) if (!is_fw_unit(dev))
return 0; return 0;
device = fw_parent_device(unit); get_modalias_ids(fw_unit(dev), id);
id = container_of(drv, struct fw_driver, driver)->id_table;
for (; id->match_flags != 0; id++) { for (; id_table->match_flags != 0; id_table++)
if (match_unit_directory(unit->directory, id->match_flags, id)) if (match_ids(id_table, id))
return 1; 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; return 0;
} }
static void get_modalias_ids(const u32 *directory, int *id)
{
struct fw_csr_iterator ci;
int key, value;
fw_csr_iterator_init(&ci, directory);
while (fw_csr_iterator_next(&ci, &key, &value)) {
switch (key) {
case CSR_VENDOR: id[0] = value; break;
case CSR_MODEL: id[1] = value; break;
case CSR_SPECIFIER_ID: id[2] = value; break;
case CSR_VERSION: id[3] = value; break;
}
}
}
static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size) static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size)
{ {
int id[] = {0, 0, 0, 0}; int id[] = {0, 0, 0, 0};
get_modalias_ids(&fw_parent_device(unit)->config_rom[5], id); get_modalias_ids(unit, id);
get_modalias_ids(unit->directory, id);
return snprintf(buffer, buffer_size, return snprintf(buffer, buffer_size,
"ieee1394:ven%08Xmo%08Xsp%08Xver%08X", "ieee1394:ven%08Xmo%08Xsp%08Xver%08X",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment