firewire: also use vendor ID in root directory for driver matches

Due to AV/C protocol extensions, FireDTV devices need a vendor-specific
driver. But their configuration ROM features a vendor ID only in the
root directory, not in the unit directory.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

+16 -6
+16 -6
drivers/firewire/fw-device.c
··· 58 59 static int is_fw_unit(struct device *dev); 60 61 - static int match_unit_directory(u32 *directory, 62 const struct ieee1394_device_id *id) 63 { 64 struct fw_csr_iterator ci; ··· 77 match |= IEEE1394_MATCH_VERSION; 78 } 79 80 - return (match & id->match_flags) == id->match_flags; 81 } 82 83 static int fw_unit_match(struct device *dev, struct device_driver *drv) 84 { 85 struct fw_unit *unit = fw_unit(dev); 86 - struct fw_driver *driver = fw_driver(drv); 87 - int i; 88 89 /* We only allow binding to fw_units. */ 90 if (!is_fw_unit(dev)) 91 return 0; 92 93 - for (i = 0; driver->id_table[i].match_flags != 0; i++) { 94 - if (match_unit_directory(unit->directory, &driver->id_table[i])) 95 return 1; 96 } 97
··· 58 59 static int is_fw_unit(struct device *dev); 60 61 + static int match_unit_directory(u32 *directory, u32 match_flags, 62 const struct ieee1394_device_id *id) 63 { 64 struct fw_csr_iterator ci; ··· 77 match |= IEEE1394_MATCH_VERSION; 78 } 79 80 + return (match & match_flags) == match_flags; 81 } 82 83 static int fw_unit_match(struct device *dev, struct device_driver *drv) 84 { 85 struct fw_unit *unit = fw_unit(dev); 86 + struct fw_device *device; 87 + const struct ieee1394_device_id *id; 88 89 /* We only allow binding to fw_units. */ 90 if (!is_fw_unit(dev)) 91 return 0; 92 93 + device = fw_device(unit->device.parent); 94 + 95 + for (id = fw_driver(drv)->id_table; id->match_flags != 0; id++) { 96 + if (match_unit_directory(unit->directory, id->match_flags, id)) 97 + return 1; 98 + 99 + /* Also check vendor ID in the root directory. */ 100 + if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) && 101 + match_unit_directory(&device->config_rom[5], 102 + IEEE1394_MATCH_VENDOR_ID, id) && 103 + match_unit_directory(unit->directory, id->match_flags 104 + & ~IEEE1394_MATCH_VENDOR_ID, id)) 105 return 1; 106 } 107