diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-03-18 19:39:07 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-03-24 17:01:47 -0400 |
commit | fe43d6d9cf59d8f8cbfdcde2018de13ffd1285c7 (patch) | |
tree | 4eb14adaa43b7746cd8e0bc5416281b5d3839f9c /drivers/firewire/core-device.c | |
parent | 5ae73518cb39dd81e641dfa7ce20751c853579e0 (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.c | 87 |
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 | } |
128 | EXPORT_SYMBOL(fw_csr_string); | 128 | EXPORT_SYMBOL(fw_csr_string); |
129 | 129 | ||
130 | static bool is_fw_unit(struct device *dev); | 130 | static void get_ids(const u32 *directory, int *id) |
131 | |||
132 | static 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; | 146 | static 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 | |||
152 | static 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 | ||
168 | static bool is_fw_unit(struct device *dev); | ||
169 | |||
154 | static int fw_unit_match(struct device *dev, struct device_driver *drv) | 170 | static 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 | ||
183 | static 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 | |||
199 | static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size) | 189 | static 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", |