aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/core-device.c
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2010-03-18 19:39:07 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2010-03-24 17:01:47 -0400
commitfe43d6d9cf59d8f8cbfdcde2018de13ffd1285c7 (patch)
tree4eb14adaa43b7746cd8e0bc5416281b5d3839f9c /drivers/firewire/core-device.c
parent5ae73518cb39dd81e641dfa7ce20751c853579e0 (diff)
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>
Diffstat (limited to 'drivers/firewire/core-device.c')
-rw-r--r--drivers/firewire/core-device.c87
1 files changed, 38 insertions, 49 deletions
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index c91d7179eb96..92b633d643f2 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -127,81 +127,70 @@ int fw_csr_string(const u32 *directory, int key, char *buf, size_t size)
127} 127}
128EXPORT_SYMBOL(fw_csr_string); 128EXPORT_SYMBOL(fw_csr_string);
129 129
130static bool is_fw_unit(struct device *dev); 130static void get_ids(const u32 *directory, int *id)
131
132static int match_unit_directory(const u32 *directory, u32 match_flags,
133 const struct ieee1394_device_id *id)
134{ 131{
135 struct fw_csr_iterator ci; 132 struct fw_csr_iterator ci;
136 int key, value, match; 133 int key, value;
137 134
138 match = 0;
139 fw_csr_iterator_init(&ci, directory); 135 fw_csr_iterator_init(&ci, directory);
140 while (fw_csr_iterator_next(&ci, &key, &value)) { 136 while (fw_csr_iterator_next(&ci, &key, &value)) {
141 if (key == CSR_VENDOR && value == id->vendor_id) 137 switch (key) {
142 match |= IEEE1394_MATCH_VENDOR_ID; 138 case CSR_VENDOR: id[0] = value; break;
143 if (key == CSR_MODEL && value == id->model_id) 139 case CSR_MODEL: id[1] = value; break;
144 match |= IEEE1394_MATCH_MODEL_ID; 140 case CSR_SPECIFIER_ID: id[2] = value; break;
145 if (key == CSR_SPECIFIER_ID && value == id->specifier_id) 141 case CSR_VERSION: id[3] = value; break;
146 match |= IEEE1394_MATCH_SPECIFIER_ID; 142 }
147 if (key == CSR_VERSION && value == id->version)
148 match |= IEEE1394_MATCH_VERSION;
149 } 143 }
144}
150 145
151 return (match & match_flags) == match_flags; 146static void get_modalias_ids(struct fw_unit *unit, int *id)
147{
148 get_ids(&fw_parent_device(unit)->config_rom[5], id);
149 get_ids(unit->directory, id);
150}
151
152static bool match_ids(const struct ieee1394_device_id *id_table, int *id)
153{
154 int match = 0;
155
156 if (id[0] == id_table->vendor_id)
157 match |= IEEE1394_MATCH_VENDOR_ID;
158 if (id[1] == id_table->model_id)
159 match |= IEEE1394_MATCH_MODEL_ID;
160 if (id[2] == id_table->specifier_id)
161 match |= IEEE1394_MATCH_SPECIFIER_ID;
162 if (id[3] == id_table->version)
163 match |= IEEE1394_MATCH_VERSION;
164
165 return (match & id_table->match_flags) == id_table->match_flags;
152} 166}
153 167
168static bool is_fw_unit(struct device *dev);
169
154static int fw_unit_match(struct device *dev, struct device_driver *drv) 170static int fw_unit_match(struct device *dev, struct device_driver *drv)
155{ 171{
156 struct fw_unit *unit = fw_unit(dev); 172 const struct ieee1394_device_id *id_table =
157 struct fw_device *device; 173 container_of(drv, struct fw_driver, driver)->id_table;
158 const struct ieee1394_device_id *id; 174 int id[] = {0, 0, 0, 0};
159 175
160 /* We only allow binding to fw_units. */ 176 /* We only allow binding to fw_units. */
161 if (!is_fw_unit(dev)) 177 if (!is_fw_unit(dev))
162 return 0; 178 return 0;
163 179
164 device = fw_parent_device(unit); 180 get_modalias_ids(fw_unit(dev), id);
165 id = container_of(drv, struct fw_driver, driver)->id_table;
166 181
167 for (; id->match_flags != 0; id++) { 182 for (; id_table->match_flags != 0; id_table++)
168 if (match_unit_directory(unit->directory, id->match_flags, id)) 183 if (match_ids(id_table, id))
169 return 1; 184 return 1;
170 185
171 /* Also check vendor ID in the root directory. */
172 if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
173 match_unit_directory(&device->config_rom[5],
174 IEEE1394_MATCH_VENDOR_ID, id) &&
175 match_unit_directory(unit->directory, id->match_flags
176 & ~IEEE1394_MATCH_VENDOR_ID, id))
177 return 1;
178 }
179
180 return 0; 186 return 0;
181} 187}
182 188
183static void get_modalias_ids(const u32 *directory, int *id)
184{
185 struct fw_csr_iterator ci;
186 int key, value;
187
188 fw_csr_iterator_init(&ci, directory);
189 while (fw_csr_iterator_next(&ci, &key, &value)) {
190 switch (key) {
191 case CSR_VENDOR: id[0] = value; break;
192 case CSR_MODEL: id[1] = value; break;
193 case CSR_SPECIFIER_ID: id[2] = value; break;
194 case CSR_VERSION: id[3] = value; break;
195 }
196 }
197}
198
199static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size) 189static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size)
200{ 190{
201 int id[] = {0, 0, 0, 0}; 191 int id[] = {0, 0, 0, 0};
202 192
203 get_modalias_ids(&fw_parent_device(unit)->config_rom[5], id); 193 get_modalias_ids(unit, id);
204 get_modalias_ids(unit->directory, id);
205 194
206 return snprintf(buffer, buffer_size, 195 return snprintf(buffer, buffer_size,
207 "ieee1394:ven%08Xmo%08Xsp%08Xver%08X", 196 "ieee1394:ven%08Xmo%08Xsp%08Xver%08X",