3131
3232#include "core.h"
3333
34+ #define ROOT_DIR_OFFSET 5
35+
3436void fw_csr_iterator_init (struct fw_csr_iterator * ci , const u32 * p )
3537{
3638 ci -> p = p + 1 ;
@@ -47,6 +49,22 @@ int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value)
4749}
4850EXPORT_SYMBOL (fw_csr_iterator_next );
4951
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+
5068static const u32 * search_leaf (const u32 * directory , int search_key )
5169{
5270 struct fw_csr_iterator ci ;
@@ -135,8 +153,25 @@ static void get_ids(const u32 *directory, int *id)
135153
136154static void get_modalias_ids (const struct fw_unit * unit , int * id )
137155{
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 );
140175}
141176
142177static 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,
171206 return NULL ;
172207}
173208
174- static bool is_fw_unit (struct device * dev );
209+ static bool is_fw_unit (const struct device * dev );
175210
176211static int fw_unit_match (struct device * dev , struct device_driver * drv )
177212{
@@ -219,7 +254,7 @@ static int fw_unit_uevent(const struct device *dev, struct kobj_uevent_env *env)
219254 return 0 ;
220255}
221256
222- struct bus_type fw_bus_type = {
257+ const struct bus_type fw_bus_type = {
223258 .name = "firewire" ,
224259 .match = fw_unit_match ,
225260 .probe = fw_unit_probe ,
@@ -251,27 +286,44 @@ static ssize_t show_immediate(struct device *dev,
251286 struct config_rom_attribute * attr =
252287 container_of (dattr , struct config_rom_attribute , attr );
253288 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 ;
256291
257292 down_read (& fw_device_rwsem );
258293
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+ }
263310
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 ;
270318 }
319+ }
271320
272321 up_read (& fw_device_rwsem );
273322
274- return ret ;
323+ if (value < 0 )
324+ return - ENOENT ;
325+
326+ return snprintf (buf , buf ? PAGE_SIZE : 0 , "0x%06x\n" , value );
275327}
276328
277329#define IMMEDIATE_ATTR (name , key ) \
@@ -282,17 +334,29 @@ static ssize_t show_text_leaf(struct device *dev,
282334{
283335 struct config_rom_attribute * attr =
284336 container_of (dattr , struct config_rom_attribute , attr );
285- const u32 * dir ;
337+ const u32 * directories [] = { NULL , NULL } ;
286338 size_t bufsize ;
287339 char dummy_buf [2 ];
288- int ret ;
340+ int i , ret = - ENOENT ;
289341
290342 down_read (& fw_device_rwsem );
291343
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+ }
296360
297361 if (buf ) {
298362 bufsize = PAGE_SIZE - 1 ;
@@ -301,7 +365,12 @@ static ssize_t show_text_leaf(struct device *dev,
301365 bufsize = 1 ;
302366 }
303367
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+ }
305374
306375 if (ret >= 0 ) {
307376 /* Strip trailing whitespace and add newline. */
@@ -446,7 +515,7 @@ static ssize_t units_show(struct device *dev,
446515 int key , value , i = 0 ;
447516
448517 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 ]);
450519 while (fw_csr_iterator_next (& ci , & key , & value )) {
451520 if (key != (CSR_UNIT | CSR_DIRECTORY ))
452521 continue ;
@@ -679,7 +748,7 @@ static struct device_type fw_unit_type = {
679748 .release = fw_unit_release ,
680749};
681750
682- static bool is_fw_unit (struct device * dev )
751+ static bool is_fw_unit (const struct device * dev )
683752{
684753 return dev -> type == & fw_unit_type ;
685754}
@@ -691,7 +760,7 @@ static void create_units(struct fw_device *device)
691760 int key , value , i ;
692761
693762 i = 0 ;
694- fw_csr_iterator_init (& ci , & device -> config_rom [5 ]);
763+ fw_csr_iterator_init (& ci , & device -> config_rom [ROOT_DIR_OFFSET ]);
695764 while (fw_csr_iterator_next (& ci , & key , & value )) {
696765 if (key != (CSR_UNIT | CSR_DIRECTORY ))
697766 continue ;
@@ -835,7 +904,7 @@ static struct device_type fw_device_type = {
835904 .release = fw_device_release ,
836905};
837906
838- static bool is_fw_device (struct device * dev )
907+ static bool is_fw_device (const struct device * dev )
839908{
840909 return dev -> type == & fw_device_type ;
841910}
@@ -1308,3 +1377,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
13081377 break ;
13091378 }
13101379}
1380+
1381+ #ifdef CONFIG_FIREWIRE_KUNIT_DEVICE_ATTRIBUTE_TEST
1382+ #include "device-attribute-test.c"
1383+ #endif
0 commit comments