Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'firewire-updates-6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394

Pull firewire updates from Takashi Sakamoto:
"This includes the series of changes related to device attributes, as
well as slight code refactoring.

Some old devices are recognized to have legacy layout of configuration
ROM. They have an inconvenience that FireWire subsystem adds no
attributes for vendor information to corresponding devices. The main
purpose of this update is to rectify the inconvenience.

We have a slight concern about regression. The update changes the
value of modalias for the unit devices by populating its model field,
which was previously left as zero in the case. I've assessed the
potential impact of this change and anticipate it to have minimal
concern for both the kernel and user lands. The change is enough
acceptable"

* tag 'firewire-updates-6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394:
firewire: core: fill model field in modalias of unit device for legacy layout of configuration ROM
firewire: core: detect model name for legacy layout of configuration ROM
firewire: core: detect numeric model identifier for legacy layout of configuration ROM
firewire: test: add test of device attributes for legacy AV/C device
firewire: test: add test of device attributes for simple AV/C device
firewire: test: add KUnit test for device attributes
firewire: core: replace magic number with macro
firewire: core: adds constant qualifier for local helper functions
firewire: make fw_bus_type const

+370 -29
+1
drivers/firewire/.kunitconfig
··· 2 2 CONFIG_PCI=y 3 3 CONFIG_FIREWIRE=y 4 4 CONFIG_FIREWIRE_KUNIT_UAPI_TEST=y 5 + CONFIG_FIREWIRE_KUNIT_DEVICE_ATTRIBUTE_TEST=y
+16
drivers/firewire/Kconfig
··· 34 34 For more information on KUnit and unit tests in general, refer 35 35 to the KUnit documentation in Documentation/dev-tools/kunit/. 36 36 37 + config FIREWIRE_KUNIT_DEVICE_ATTRIBUTE_TEST 38 + tristate "KUnit tests for device attributes" if !KUNIT_ALL_TESTS 39 + depends on FIREWIRE && KUNIT 40 + default KUNIT_ALL_TESTS 41 + help 42 + This builds the KUnit tests for device attribute for node and 43 + unit. 44 + 45 + KUnit tests run during boot and output the results to the debug 46 + log in TAP format (https://testanything.org/). Only useful for 47 + kernel devs running KUnit test harness and are not for inclusion 48 + into a production build. 49 + 50 + For more information on KUnit and unit tests in general, refer 51 + to the KUnit documentation in Documentation/dev-tools/kunit/. 52 + 37 53 config FIREWIRE_OHCI 38 54 tristate "OHCI-1394 controllers" 39 55 depends on PCI && FIREWIRE && MMU
+101 -28
drivers/firewire/core-device.c
··· 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; ··· 48 46 return ci->p++ < ci->end; 49 47 } 50 48 EXPORT_SYMBOL(fw_csr_iterator_next); 49 + 50 + static const u32 *search_directory(const u32 *directory, int search_key) 51 + { 52 + struct fw_csr_iterator ci; 53 + int key, value; 54 + 55 + search_key |= CSR_DIRECTORY; 56 + 57 + fw_csr_iterator_init(&ci, directory); 58 + while (fw_csr_iterator_next(&ci, &key, &value)) { 59 + if (key == search_key) 60 + return ci.p - 1 + value; 61 + } 62 + 63 + return NULL; 64 + } 51 65 52 66 static const u32 *search_leaf(const u32 *directory, int search_key) 53 67 { ··· 153 135 154 136 static void get_modalias_ids(const struct fw_unit *unit, int *id) 155 137 { 156 - get_ids(&fw_parent_device(unit)->config_rom[5], id); 157 - get_ids(unit->directory, id); 138 + const u32 *root_directory = &fw_parent_device(unit)->config_rom[ROOT_DIR_OFFSET]; 139 + const u32 *directories[] = {NULL, NULL, NULL}; 140 + const u32 *vendor_directory; 141 + int i; 142 + 143 + directories[0] = root_directory; 144 + 145 + // Legacy layout of configuration ROM described in Annex 1 of 'Configuration ROM for AV/C 146 + // Devices 1.0 (December 12, 2000, 1394 Trading Association, TA Document 1999027)'. 147 + vendor_directory = search_directory(root_directory, CSR_VENDOR); 148 + if (!vendor_directory) { 149 + directories[1] = unit->directory; 150 + } else { 151 + directories[1] = vendor_directory; 152 + directories[2] = unit->directory; 153 + } 154 + 155 + for (i = 0; i < ARRAY_SIZE(directories) && !!directories[i]; ++i) 156 + get_ids(directories[i], id); 158 157 } 159 158 160 159 static bool match_ids(const struct ieee1394_device_id *id_table, int *id) ··· 206 171 return NULL; 207 172 } 208 173 209 - static bool is_fw_unit(struct device *dev); 174 + static bool is_fw_unit(const struct device *dev); 210 175 211 176 static int fw_unit_match(struct device *dev, struct device_driver *drv) 212 177 { ··· 254 219 return 0; 255 220 } 256 221 257 - struct bus_type fw_bus_type = { 222 + const struct bus_type fw_bus_type = { 258 223 .name = "firewire", 259 224 .match = fw_unit_match, 260 225 .probe = fw_unit_probe, ··· 286 251 struct config_rom_attribute *attr = 287 252 container_of(dattr, struct config_rom_attribute, attr); 288 253 struct fw_csr_iterator ci; 289 - const u32 *dir; 290 - int key, value, ret = -ENOENT; 254 + const u32 *directories[] = {NULL, NULL}; 255 + int i, value = -1; 291 256 292 257 down_read(&fw_device_rwsem); 293 258 294 - if (is_fw_unit(dev)) 295 - dir = fw_unit(dev)->directory; 296 - else 297 - dir = fw_device(dev)->config_rom + 5; 259 + if (is_fw_unit(dev)) { 260 + directories[0] = fw_unit(dev)->directory; 261 + } else { 262 + const u32 *root_directory = fw_device(dev)->config_rom + ROOT_DIR_OFFSET; 263 + const u32 *vendor_directory = search_directory(root_directory, CSR_VENDOR); 298 264 299 - fw_csr_iterator_init(&ci, dir); 300 - while (fw_csr_iterator_next(&ci, &key, &value)) 301 - if (attr->key == key) { 302 - ret = snprintf(buf, buf ? PAGE_SIZE : 0, 303 - "0x%06x\n", value); 304 - break; 265 + if (!vendor_directory) { 266 + directories[0] = root_directory; 267 + } else { 268 + // Legacy layout of configuration ROM described in Annex 1 of 269 + // 'Configuration ROM for AV/C Devices 1.0 (December 12, 2000, 1394 Trading 270 + // Association, TA Document 1999027)'. 271 + directories[0] = vendor_directory; 272 + directories[1] = root_directory; 305 273 } 274 + } 275 + 276 + for (i = 0; i < ARRAY_SIZE(directories) && !!directories[i]; ++i) { 277 + int key, val; 278 + 279 + fw_csr_iterator_init(&ci, directories[i]); 280 + while (fw_csr_iterator_next(&ci, &key, &val)) { 281 + if (attr->key == key) 282 + value = val; 283 + } 284 + } 306 285 307 286 up_read(&fw_device_rwsem); 308 287 309 - return ret; 288 + if (value < 0) 289 + return -ENOENT; 290 + 291 + return snprintf(buf, buf ? PAGE_SIZE : 0, "0x%06x\n", value); 310 292 } 311 293 312 294 #define IMMEDIATE_ATTR(name, key) \ ··· 334 282 { 335 283 struct config_rom_attribute *attr = 336 284 container_of(dattr, struct config_rom_attribute, attr); 337 - const u32 *dir; 285 + const u32 *directories[] = {NULL, NULL}; 338 286 size_t bufsize; 339 287 char dummy_buf[2]; 340 - int ret; 288 + int i, ret = -ENOENT; 341 289 342 290 down_read(&fw_device_rwsem); 343 291 344 - if (is_fw_unit(dev)) 345 - dir = fw_unit(dev)->directory; 346 - else 347 - dir = fw_device(dev)->config_rom + 5; 292 + if (is_fw_unit(dev)) { 293 + directories[0] = fw_unit(dev)->directory; 294 + } else { 295 + const u32 *root_directory = fw_device(dev)->config_rom + ROOT_DIR_OFFSET; 296 + const u32 *vendor_directory = search_directory(root_directory, CSR_VENDOR); 297 + 298 + if (!vendor_directory) { 299 + directories[0] = root_directory; 300 + } else { 301 + // Legacy layout of configuration ROM described in Annex 1 of 302 + // 'Configuration ROM for AV/C Devices 1.0 (December 12, 2000, 1394 303 + // Trading Association, TA Document 1999027)'. 304 + directories[0] = root_directory; 305 + directories[1] = vendor_directory; 306 + } 307 + } 348 308 349 309 if (buf) { 350 310 bufsize = PAGE_SIZE - 1; ··· 365 301 bufsize = 1; 366 302 } 367 303 368 - ret = fw_csr_string(dir, attr->key, buf, bufsize); 304 + for (i = 0; i < ARRAY_SIZE(directories) && !!directories[i]; ++i) { 305 + int result = fw_csr_string(directories[i], attr->key, buf, bufsize); 306 + // Detected. 307 + if (result >= 0) 308 + ret = result; 309 + } 369 310 370 311 if (ret >= 0) { 371 312 /* Strip trailing whitespace and add newline. */ ··· 515 446 int key, value, i = 0; 516 447 517 448 down_read(&fw_device_rwsem); 518 - fw_csr_iterator_init(&ci, &device->config_rom[5]); 449 + fw_csr_iterator_init(&ci, &device->config_rom[ROOT_DIR_OFFSET]); 519 450 while (fw_csr_iterator_next(&ci, &key, &value)) { 520 451 if (key != (CSR_UNIT | CSR_DIRECTORY)) 521 452 continue; ··· 748 679 .release = fw_unit_release, 749 680 }; 750 681 751 - static bool is_fw_unit(struct device *dev) 682 + static bool is_fw_unit(const struct device *dev) 752 683 { 753 684 return dev->type == &fw_unit_type; 754 685 } ··· 760 691 int key, value, i; 761 692 762 693 i = 0; 763 - fw_csr_iterator_init(&ci, &device->config_rom[5]); 694 + fw_csr_iterator_init(&ci, &device->config_rom[ROOT_DIR_OFFSET]); 764 695 while (fw_csr_iterator_next(&ci, &key, &value)) { 765 696 if (key != (CSR_UNIT | CSR_DIRECTORY)) 766 697 continue; ··· 904 835 .release = fw_device_release, 905 836 }; 906 837 907 - static bool is_fw_device(struct device *dev) 838 + static bool is_fw_device(const struct device *dev) 908 839 { 909 840 return dev->type == &fw_device_type; 910 841 } ··· 1377 1308 break; 1378 1309 } 1379 1310 } 1311 + 1312 + #ifdef CONFIG_FIREWIRE_KUNIT_DEVICE_ATTRIBUTE_TEST 1313 + #include "device-attribute-test.c" 1314 + #endif
+251
drivers/firewire/device-attribute-test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // 3 + // device-attribute-test.c - An application of Kunit to test implementation for device attributes. 4 + // 5 + // Copyright (c) 2023 Takashi Sakamoto 6 + // 7 + // This file can not be built independently since it is intentionally included in core-device.c. 8 + 9 + #include <kunit/test.h> 10 + 11 + // Configuration ROM for AV/C Devices 1.0 (Dec. 12, 2000, 1394 Trading Association) 12 + // Annex C:Configuration ROM example(informative) 13 + // C.1 Simple AV/C device 14 + // 15 + // Copied from the documentation. 16 + static const u32 simple_avc_config_rom[] = { 17 + 0x0404eabf, 18 + 0x31333934, 19 + 0xe0646102, 20 + 0xffffffff, 21 + 0xffffffff, 22 + 0x00063287, // root directory. 23 + 0x03ffffff, 24 + 0x8100000a, 25 + 0x17ffffff, 26 + 0x8100000e, 27 + 0x0c0083c0, 28 + 0xd1000001, 29 + 0x0004442d, // unit 0 directory. 30 + 0x1200a02d, 31 + 0x13010001, 32 + 0x17ffffff, 33 + 0x81000007, 34 + 0x0005c915, // leaf for textual descriptor. 35 + 0x00000000, 36 + 0x00000000, 37 + 0x56656e64, 38 + 0x6f72204e, 39 + 0x616d6500, 40 + 0x00057f16, // leaf for textual descriptor. 41 + 0x00000000, 42 + 0x00000000, 43 + 0x4d6f6465, 44 + 0x6c204e61, 45 + 0x6d650000, 46 + }; 47 + 48 + // Ibid. 49 + // Annex A:Consideration for configuration ROM reader design (informative) 50 + // A.1 Vendor directory 51 + // 52 + // Written by hand. 53 + static const u32 legacy_avc_config_rom[] = { 54 + 0x04199fe7, 55 + 0x31333934, 56 + 0xe0644000, 57 + 0x00112233, 58 + 0x44556677, 59 + 0x0005dace, // root directory. 60 + 0x03012345, 61 + 0x0c0083c0, 62 + 0x8d000009, 63 + 0xd1000002, 64 + 0xc3000004, 65 + 0x0002e107, // unit 0 directory. 66 + 0x12abcdef, 67 + 0x13543210, 68 + 0x0002cb73, // vendor directory. 69 + 0x17fedcba, 70 + 0x81000004, 71 + 0x00026dc1, // leaf for EUI-64. 72 + 0x00112233, 73 + 0x44556677, 74 + 0x00050e84, // leaf for textual descriptor. 75 + 0x00000000, 76 + 0x00000000, 77 + 0x41424344, 78 + 0x45464748, 79 + 0x494a0000, 80 + }; 81 + 82 + static void device_attr_simple_avc(struct kunit *test) 83 + { 84 + static const struct fw_device node = { 85 + .device = { 86 + .type = &fw_device_type, 87 + }, 88 + .config_rom = simple_avc_config_rom, 89 + .config_rom_length = sizeof(simple_avc_config_rom), 90 + }; 91 + static const struct fw_unit unit0 = { 92 + .device = { 93 + .type = &fw_unit_type, 94 + .parent = (struct device *)&node.device, 95 + }, 96 + .directory = &simple_avc_config_rom[12], 97 + }; 98 + struct device *node_dev = (struct device *)&node.device; 99 + struct device *unit0_dev = (struct device *)&unit0.device; 100 + static const int unit0_expected_ids[] = {0x00ffffff, 0x00ffffff, 0x0000a02d, 0x00010001}; 101 + char *buf = kunit_kzalloc(test, PAGE_SIZE, GFP_KERNEL); 102 + int ids[4] = {0, 0, 0, 0}; 103 + 104 + // Ensure associations for node and unit devices. 105 + 106 + KUNIT_ASSERT_TRUE(test, is_fw_device(node_dev)); 107 + KUNIT_ASSERT_FALSE(test, is_fw_unit(node_dev)); 108 + KUNIT_ASSERT_PTR_EQ(test, fw_device(node_dev), &node); 109 + 110 + KUNIT_ASSERT_FALSE(test, is_fw_device(unit0_dev)); 111 + KUNIT_ASSERT_TRUE(test, is_fw_unit(unit0_dev)); 112 + KUNIT_ASSERT_PTR_EQ(test, fw_parent_device((&unit0)), &node); 113 + KUNIT_ASSERT_PTR_EQ(test, fw_unit(unit0_dev), &unit0); 114 + 115 + // For entries in root directory. 116 + 117 + // Vendor immediate entry is found. 118 + KUNIT_EXPECT_GT(test, show_immediate(node_dev, &config_rom_attributes[0].attr, buf), 0); 119 + KUNIT_EXPECT_STREQ(test, buf, "0xffffff\n"); 120 + 121 + // Model immediate entry is found. 122 + KUNIT_EXPECT_GT(test, show_immediate(node_dev, &config_rom_attributes[4].attr, buf), 0); 123 + KUNIT_EXPECT_STREQ(test, buf, "0xffffff\n"); 124 + 125 + // Descriptor leaf entry for vendor is found. 126 + KUNIT_EXPECT_GT(test, show_text_leaf(node_dev, &config_rom_attributes[5].attr, buf), 0); 127 + KUNIT_EXPECT_STREQ(test, buf, "Vendor Name\n"); 128 + 129 + // Descriptor leaf entry for model is found. 130 + KUNIT_EXPECT_GT(test, show_text_leaf(node_dev, &config_rom_attributes[6].attr, buf), 0); 131 + KUNIT_EXPECT_STREQ(test, buf, "Model Name\n"); 132 + 133 + // For entries in unit 0 directory. 134 + 135 + // Vendor immediate entry is not found. 136 + KUNIT_EXPECT_LT(test, show_immediate(unit0_dev, &config_rom_attributes[0].attr, buf), 0); 137 + 138 + // Model immediate entry is found. 139 + KUNIT_EXPECT_GT(test, show_immediate(unit0_dev, &config_rom_attributes[4].attr, buf), 0); 140 + KUNIT_EXPECT_STREQ(test, buf, "0xffffff\n"); 141 + 142 + // Descriptor leaf entry for vendor is not found. 143 + KUNIT_EXPECT_LT(test, show_text_leaf(unit0_dev, &config_rom_attributes[5].attr, buf), 0); 144 + 145 + // Descriptor leaf entry for model is found. 146 + KUNIT_EXPECT_GT(test, show_text_leaf(unit0_dev, &config_rom_attributes[6].attr, buf), 0); 147 + KUNIT_EXPECT_STREQ(test, buf, "Model Name\n"); 148 + 149 + // Specifier_ID immediate entry is found. 150 + KUNIT_EXPECT_GT(test, show_immediate(unit0_dev, &config_rom_attributes[2].attr, buf), 0); 151 + KUNIT_EXPECT_STREQ(test, buf, "0x00a02d\n"); 152 + 153 + // Version immediate entry is found. 154 + KUNIT_EXPECT_GT(test, show_immediate(unit0_dev, &config_rom_attributes[3].attr, buf), 0); 155 + KUNIT_EXPECT_STREQ(test, buf, "0x010001\n"); 156 + 157 + kunit_kfree(test, buf); 158 + 159 + get_modalias_ids(&unit0, ids); 160 + KUNIT_EXPECT_MEMEQ(test, ids, unit0_expected_ids, sizeof(ids)); 161 + } 162 + 163 + static void device_attr_legacy_avc(struct kunit *test) 164 + { 165 + static const struct fw_device node = { 166 + .device = { 167 + .type = &fw_device_type, 168 + }, 169 + .config_rom = legacy_avc_config_rom, 170 + .config_rom_length = sizeof(legacy_avc_config_rom), 171 + }; 172 + static const struct fw_unit unit0 = { 173 + .device = { 174 + .type = &fw_unit_type, 175 + .parent = (struct device *)&node.device, 176 + }, 177 + .directory = &legacy_avc_config_rom[11], 178 + }; 179 + struct device *node_dev = (struct device *)&node.device; 180 + struct device *unit0_dev = (struct device *)&unit0.device; 181 + static const int unit0_expected_ids[] = {0x00012345, 0x00fedcba, 0x00abcdef, 0x00543210}; 182 + char *buf = kunit_kzalloc(test, PAGE_SIZE, GFP_KERNEL); 183 + int ids[4] = {0, 0, 0, 0}; 184 + 185 + // Ensure associations for node and unit devices. 186 + 187 + KUNIT_ASSERT_TRUE(test, is_fw_device(node_dev)); 188 + KUNIT_ASSERT_FALSE(test, is_fw_unit(node_dev)); 189 + KUNIT_ASSERT_PTR_EQ(test, fw_device((node_dev)), &node); 190 + 191 + KUNIT_ASSERT_FALSE(test, is_fw_device(unit0_dev)); 192 + KUNIT_ASSERT_TRUE(test, is_fw_unit(unit0_dev)); 193 + KUNIT_ASSERT_PTR_EQ(test, fw_parent_device((&unit0)), &node); 194 + KUNIT_ASSERT_PTR_EQ(test, fw_unit(unit0_dev), &unit0); 195 + 196 + // For entries in root directory. 197 + 198 + // Vendor immediate entry is found. 199 + KUNIT_EXPECT_GT(test, show_immediate(node_dev, &config_rom_attributes[0].attr, buf), 0); 200 + KUNIT_EXPECT_STREQ(test, buf, "0x012345\n"); 201 + 202 + // Model immediate entry is found. 203 + KUNIT_EXPECT_GT(test, show_immediate(node_dev, &config_rom_attributes[4].attr, buf), 0); 204 + KUNIT_EXPECT_STREQ(test, buf, "0xfedcba\n"); 205 + 206 + // Descriptor leaf entry for vendor is not found. 207 + KUNIT_EXPECT_LT(test, show_text_leaf(node_dev, &config_rom_attributes[5].attr, buf), 0); 208 + 209 + // Descriptor leaf entry for model is found. 210 + KUNIT_EXPECT_GT(test, show_text_leaf(node_dev, &config_rom_attributes[6].attr, buf), 0); 211 + KUNIT_EXPECT_STREQ(test, buf, "ABCDEFGHIJ\n"); 212 + 213 + // For entries in unit 0 directory. 214 + 215 + // Vendor immediate entry is not found. 216 + KUNIT_EXPECT_LT(test, show_immediate(unit0_dev, &config_rom_attributes[0].attr, buf), 0); 217 + 218 + // Model immediate entry is not found. 219 + KUNIT_EXPECT_LT(test, show_immediate(unit0_dev, &config_rom_attributes[4].attr, buf), 0); 220 + 221 + // Descriptor leaf entry for vendor is not found. 222 + KUNIT_EXPECT_LT(test, show_text_leaf(unit0_dev, &config_rom_attributes[5].attr, buf), 0); 223 + 224 + // Descriptor leaf entry for model is not found. 225 + KUNIT_EXPECT_LT(test, show_text_leaf(unit0_dev, &config_rom_attributes[6].attr, buf), 0); 226 + 227 + // Specifier_ID immediate entry is found. 228 + KUNIT_EXPECT_GT(test, show_immediate(unit0_dev, &config_rom_attributes[2].attr, buf), 0); 229 + KUNIT_EXPECT_STREQ(test, buf, "0xabcdef\n"); 230 + 231 + // Version immediate entry is found. 232 + KUNIT_EXPECT_GT(test, show_immediate(unit0_dev, &config_rom_attributes[3].attr, buf), 0); 233 + KUNIT_EXPECT_STREQ(test, buf, "0x543210\n"); 234 + 235 + kunit_kfree(test, buf); 236 + 237 + get_modalias_ids(&unit0, ids); 238 + KUNIT_EXPECT_MEMEQ(test, ids, unit0_expected_ids, sizeof(ids)); 239 + } 240 + 241 + static struct kunit_case device_attr_test_cases[] = { 242 + KUNIT_CASE(device_attr_simple_avc), 243 + KUNIT_CASE(device_attr_legacy_avc), 244 + {} 245 + }; 246 + 247 + static struct kunit_suite device_attr_test_suite = { 248 + .name = "firewire-device-attribute", 249 + .test_cases = device_attr_test_cases, 250 + }; 251 + kunit_test_suite(device_attr_test_suite);
+1 -1
include/linux/firewire.h
··· 75 75 int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value); 76 76 int fw_csr_string(const u32 *directory, int key, char *buf, size_t size); 77 77 78 - extern struct bus_type fw_bus_type; 78 + extern const struct bus_type fw_bus_type; 79 79 80 80 struct fw_card_driver; 81 81 struct fw_node;