31
31
32
32
#include "core.h"
33
33
34
+ #define ROOT_DIR_OFFSET 5
35
+
34
36
void fw_csr_iterator_init (struct fw_csr_iterator * ci , const u32 * p )
35
37
{
36
38
ci -> p = p + 1 ;
@@ -47,6 +49,22 @@ int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value)
47
49
}
48
50
EXPORT_SYMBOL (fw_csr_iterator_next );
49
51
52
+ static const u32 * search_directory (const u32 * directory , int search_key )
53
+ {
54
+ struct fw_csr_iterator ci ;
55
+ int key , value ;
56
+
57
+ search_key |= CSR_DIRECTORY ;
58
+
59
+ fw_csr_iterator_init (& ci , directory );
60
+ while (fw_csr_iterator_next (& ci , & key , & value )) {
61
+ if (key == search_key )
62
+ return ci .p - 1 + value ;
63
+ }
64
+
65
+ return NULL ;
66
+ }
67
+
50
68
static const u32 * search_leaf (const u32 * directory , int search_key )
51
69
{
52
70
struct fw_csr_iterator ci ;
@@ -135,8 +153,25 @@ static void get_ids(const u32 *directory, int *id)
135
153
136
154
static void get_modalias_ids (const struct fw_unit * unit , int * id )
137
155
{
138
- get_ids (& fw_parent_device (unit )-> config_rom [5 ], id );
139
- get_ids (unit -> directory , id );
156
+ const u32 * root_directory = & fw_parent_device (unit )-> config_rom [ROOT_DIR_OFFSET ];
157
+ const u32 * directories [] = {NULL , NULL , NULL };
158
+ const u32 * vendor_directory ;
159
+ int i ;
160
+
161
+ directories [0 ] = root_directory ;
162
+
163
+ // Legacy layout of configuration ROM described in Annex 1 of 'Configuration ROM for AV/C
164
+ // Devices 1.0 (December 12, 2000, 1394 Trading Association, TA Document 1999027)'.
165
+ vendor_directory = search_directory (root_directory , CSR_VENDOR );
166
+ if (!vendor_directory ) {
167
+ directories [1 ] = unit -> directory ;
168
+ } else {
169
+ directories [1 ] = vendor_directory ;
170
+ directories [2 ] = unit -> directory ;
171
+ }
172
+
173
+ for (i = 0 ; i < ARRAY_SIZE (directories ) && !!directories [i ]; ++ i )
174
+ get_ids (directories [i ], id );
140
175
}
141
176
142
177
static bool match_ids (const struct ieee1394_device_id * id_table , int * id )
@@ -171,7 +206,7 @@ static const struct ieee1394_device_id *unit_match(struct device *dev,
171
206
return NULL ;
172
207
}
173
208
174
- static bool is_fw_unit (struct device * dev );
209
+ static bool is_fw_unit (const struct device * dev );
175
210
176
211
static int fw_unit_match (struct device * dev , struct device_driver * drv )
177
212
{
@@ -219,7 +254,7 @@ static int fw_unit_uevent(const struct device *dev, struct kobj_uevent_env *env)
219
254
return 0 ;
220
255
}
221
256
222
- struct bus_type fw_bus_type = {
257
+ const struct bus_type fw_bus_type = {
223
258
.name = "firewire" ,
224
259
.match = fw_unit_match ,
225
260
.probe = fw_unit_probe ,
@@ -251,27 +286,44 @@ static ssize_t show_immediate(struct device *dev,
251
286
struct config_rom_attribute * attr =
252
287
container_of (dattr , struct config_rom_attribute , attr );
253
288
struct fw_csr_iterator ci ;
254
- const u32 * dir ;
255
- int key , value , ret = - ENOENT ;
289
+ const u32 * directories [] = { NULL , NULL } ;
290
+ int i , value = -1 ;
256
291
257
292
down_read (& fw_device_rwsem );
258
293
259
- if (is_fw_unit (dev ))
260
- dir = fw_unit (dev )-> directory ;
261
- else
262
- dir = fw_device (dev )-> config_rom + 5 ;
294
+ if (is_fw_unit (dev )) {
295
+ directories [0 ] = fw_unit (dev )-> directory ;
296
+ } else {
297
+ const u32 * root_directory = fw_device (dev )-> config_rom + ROOT_DIR_OFFSET ;
298
+ const u32 * vendor_directory = search_directory (root_directory , CSR_VENDOR );
299
+
300
+ if (!vendor_directory ) {
301
+ directories [0 ] = root_directory ;
302
+ } else {
303
+ // Legacy layout of configuration ROM described in Annex 1 of
304
+ // 'Configuration ROM for AV/C Devices 1.0 (December 12, 2000, 1394 Trading
305
+ // Association, TA Document 1999027)'.
306
+ directories [0 ] = vendor_directory ;
307
+ directories [1 ] = root_directory ;
308
+ }
309
+ }
263
310
264
- fw_csr_iterator_init (& ci , dir );
265
- while (fw_csr_iterator_next (& ci , & key , & value ))
266
- if (attr -> key == key ) {
267
- ret = snprintf (buf , buf ? PAGE_SIZE : 0 ,
268
- "0x%06x\n" , value );
269
- break ;
311
+ for (i = 0 ; i < ARRAY_SIZE (directories ) && !!directories [i ]; ++ i ) {
312
+ int key , val ;
313
+
314
+ fw_csr_iterator_init (& ci , directories [i ]);
315
+ while (fw_csr_iterator_next (& ci , & key , & val )) {
316
+ if (attr -> key == key )
317
+ value = val ;
270
318
}
319
+ }
271
320
272
321
up_read (& fw_device_rwsem );
273
322
274
- return ret ;
323
+ if (value < 0 )
324
+ return - ENOENT ;
325
+
326
+ return snprintf (buf , buf ? PAGE_SIZE : 0 , "0x%06x\n" , value );
275
327
}
276
328
277
329
#define IMMEDIATE_ATTR (name , key ) \
@@ -282,17 +334,29 @@ static ssize_t show_text_leaf(struct device *dev,
282
334
{
283
335
struct config_rom_attribute * attr =
284
336
container_of (dattr , struct config_rom_attribute , attr );
285
- const u32 * dir ;
337
+ const u32 * directories [] = { NULL , NULL } ;
286
338
size_t bufsize ;
287
339
char dummy_buf [2 ];
288
- int ret ;
340
+ int i , ret = - ENOENT ;
289
341
290
342
down_read (& fw_device_rwsem );
291
343
292
- if (is_fw_unit (dev ))
293
- dir = fw_unit (dev )-> directory ;
294
- else
295
- dir = fw_device (dev )-> config_rom + 5 ;
344
+ if (is_fw_unit (dev )) {
345
+ directories [0 ] = fw_unit (dev )-> directory ;
346
+ } else {
347
+ const u32 * root_directory = fw_device (dev )-> config_rom + ROOT_DIR_OFFSET ;
348
+ const u32 * vendor_directory = search_directory (root_directory , CSR_VENDOR );
349
+
350
+ if (!vendor_directory ) {
351
+ directories [0 ] = root_directory ;
352
+ } else {
353
+ // Legacy layout of configuration ROM described in Annex 1 of
354
+ // 'Configuration ROM for AV/C Devices 1.0 (December 12, 2000, 1394
355
+ // Trading Association, TA Document 1999027)'.
356
+ directories [0 ] = root_directory ;
357
+ directories [1 ] = vendor_directory ;
358
+ }
359
+ }
296
360
297
361
if (buf ) {
298
362
bufsize = PAGE_SIZE - 1 ;
@@ -301,7 +365,12 @@ static ssize_t show_text_leaf(struct device *dev,
301
365
bufsize = 1 ;
302
366
}
303
367
304
- ret = fw_csr_string (dir , attr -> key , buf , bufsize );
368
+ for (i = 0 ; i < ARRAY_SIZE (directories ) && !!directories [i ]; ++ i ) {
369
+ int result = fw_csr_string (directories [i ], attr -> key , buf , bufsize );
370
+ // Detected.
371
+ if (result >= 0 )
372
+ ret = result ;
373
+ }
305
374
306
375
if (ret >= 0 ) {
307
376
/* Strip trailing whitespace and add newline. */
@@ -446,7 +515,7 @@ static ssize_t units_show(struct device *dev,
446
515
int key , value , i = 0 ;
447
516
448
517
down_read (& fw_device_rwsem );
449
- fw_csr_iterator_init (& ci , & device -> config_rom [5 ]);
518
+ fw_csr_iterator_init (& ci , & device -> config_rom [ROOT_DIR_OFFSET ]);
450
519
while (fw_csr_iterator_next (& ci , & key , & value )) {
451
520
if (key != (CSR_UNIT | CSR_DIRECTORY ))
452
521
continue ;
@@ -679,7 +748,7 @@ static struct device_type fw_unit_type = {
679
748
.release = fw_unit_release ,
680
749
};
681
750
682
- static bool is_fw_unit (struct device * dev )
751
+ static bool is_fw_unit (const struct device * dev )
683
752
{
684
753
return dev -> type == & fw_unit_type ;
685
754
}
@@ -691,7 +760,7 @@ static void create_units(struct fw_device *device)
691
760
int key , value , i ;
692
761
693
762
i = 0 ;
694
- fw_csr_iterator_init (& ci , & device -> config_rom [5 ]);
763
+ fw_csr_iterator_init (& ci , & device -> config_rom [ROOT_DIR_OFFSET ]);
695
764
while (fw_csr_iterator_next (& ci , & key , & value )) {
696
765
if (key != (CSR_UNIT | CSR_DIRECTORY ))
697
766
continue ;
@@ -835,7 +904,7 @@ static struct device_type fw_device_type = {
835
904
.release = fw_device_release ,
836
905
};
837
906
838
- static bool is_fw_device (struct device * dev )
907
+ static bool is_fw_device (const struct device * dev )
839
908
{
840
909
return dev -> type == & fw_device_type ;
841
910
}
@@ -1308,3 +1377,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
1308
1377
break ;
1309
1378
}
1310
1379
}
1380
+
1381
+ #ifdef CONFIG_FIREWIRE_KUNIT_DEVICE_ATTRIBUTE_TEST
1382
+ #include "device-attribute-test.c"
1383
+ #endif
0 commit comments