diff options
| author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2026-09-01 22:45:23 +0900 |
|---|---|---|
| committer | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2026-09-01 22:45:23 +0900 |
| commit | bae885b9bee546cd260736cd9e4e282c74e9baf7 (patch) | |
| tree | 862abd83d4733b498b9b28deb84522f5bb0fba7e /drivers/firewire | |
| parent | 428ef9ca38545ccab8dc5c38b0fa62b02090e66d (diff) | |
| download | linux-bae885b9bee546cd260736cd9e4e282c74e9baf7.tar.gz linux-bae885b9bee546cd260736cd9e4e282c74e9baf7.zip | |
firewire: core: add test to detect irm-is-1394-1995-only quirk in config ROM parser
Some Sony DV cameras have a quirk where their IRM functionality does not
comply with IEEE 1394a:2000. This quirk was supported by commit
10389536742c ("firewire: core: check for 1394a compliant IRM, fix
inaccessibility of Sony camcorder") and refactored by commit 5a43dc9f4ee0
("firewire: core: detect device quirk when reading configuration ROM").
Add a KUnit test to check detection of the quirk. The configuration ROM
content is retrieved from the following discussion:
https://github.com/systemd/systemd/issues/25029.
Link: https://lore.kernel.org/r/20260901134534.2386577-3-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Diffstat (limited to 'drivers/firewire')
| -rw-r--r-- | drivers/firewire/config-rom-parser-test.c | 151 | ||||
| -rw-r--r-- | drivers/firewire/core-transaction.c | 4 |
2 files changed, 155 insertions, 0 deletions
diff --git a/drivers/firewire/config-rom-parser-test.c b/drivers/firewire/config-rom-parser-test.c index 632f24e68692..131c7aa3b224 100644 --- a/drivers/firewire/config-rom-parser-test.c +++ b/drivers/firewire/config-rom-parser-test.c @@ -7,13 +7,164 @@ // This file can not be built independently since it is intentionally included in core-device.c. #include <kunit/test.h> +#include <kunit/static_stub.h> +#include <kunit/device.h> + +static const u32 sony_dcr_trv310k_config_rom[] = { + 0x0404e552, + 0x31333934, + 0xe0648100, + 0x00008500, + 0x005eb597, + 0x0007cdd0, + 0x03000085, + 0x8100000d, + 0x17000002, + 0x81000010, + 0x0c0083c0, + 0xd8000002, + 0xd1000003, + 0x0001ce96, + 0xd1000001, + 0x0004bbee, + 0x1200a02d, + 0x13010001, + 0x17000002, + 0x81000006, + 0x00046dc8, + 0x00000000, + 0x00000000, + 0x43616e6f, + 0x6e000000, + 0x000621ee, + 0x00000000, + 0x00000000, + 0x4d563569, + 0x204d4300, + 0x00000000, + 0x00000000, +}; + +static const struct parser_test_case { + const char *name; + const u32 *quadlets; + size_t quadlet_length; + int phy_speed_in_self_id; + int expected_speed; + int expected_quirk; + unsigned int expected_max_rec; + bool expected_cmc; + bool expected_irmc; +} parser_test_cases[] = { + { + .name = "detect_irm_is_1394_1995_only_quirk", + .quadlets = sony_dcr_trv310k_config_rom, + .quadlet_length = ARRAY_SIZE(sony_dcr_trv310k_config_rom), + .phy_speed_in_self_id = SCODE_100, + .expected_speed = SCODE_100, + .expected_quirk = FW_DEVICE_QUIRK_IRM_IS_1394_1995_ONLY, + .expected_max_rec = 8, + .expected_cmc = true, + .expected_irmc = true, + }, +}; + +// Define parser_test_gen_params. +KUNIT_ARRAY_PARAM_DESC(parser_test, parser_test_cases, name); + +static int stub_run_regular_transaction(struct fw_card *card, int tcode, int destination_id, + int generation, int speed, unsigned long long offset, + void *payload, size_t length) +{ + struct kunit *test = kunit_get_current_test(); + const struct parser_test_case *param = test->param_value; + + KUNIT_ASSERT_GE(test, offset, CSR_REGISTER_BASE | CSR_CONFIG_ROM); + KUNIT_ASSERT_LT(test, offset, CSR_REGISTER_BASE | CSR_CONFIG_ROM_END); + KUNIT_ASSERT_NOT_NULL(test, payload); + KUNIT_ASSERT_EQ(test, length, 4); + + unsigned int index = (offset - (CSR_REGISTER_BASE | CSR_CONFIG_ROM)) / sizeof(u32); + u32 *quadlet = payload; + + KUNIT_EXPECT_LE(test, speed, param->expected_speed); + KUNIT_EXPECT_LT(test, index, param->quadlet_length); + + *quadlet = cpu_to_be32(param->quadlets[index]); + + return RCODE_COMPLETE; +} + +static void test_parser_with_regular_cases(struct kunit *test) +{ + struct fw_device *device = test->priv; + const struct parser_test_case *param = test->param_value; + + kunit_activate_static_stub(test, fw_run_transaction, stub_run_regular_transaction); + + device->card->link_speed = SCODE_BETA; + device->node->max_speed = param->phy_speed_in_self_id; + + KUNIT_EXPECT_EQ(test, read_config_rom(device, 0), RCODE_COMPLETE); + + KUNIT_EXPECT_EQ(test, device->config_rom_length, param->quadlet_length); + KUNIT_EXPECT_MEMEQ(test, device->config_rom, param->quadlets, param->quadlet_length); + + KUNIT_EXPECT_TRUE(test, device->quirks & param->expected_quirk); + KUNIT_EXPECT_EQ(test, device->max_speed, param->expected_speed); + KUNIT_EXPECT_EQ(test, (unsigned int)device->max_rec, param->expected_max_rec); + KUNIT_EXPECT_EQ(test, (bool)device->cmc, param->expected_cmc); + KUNIT_EXPECT_EQ(test, (bool)device->irmc, param->expected_irmc); + + kunit_deactivate_static_stub(test, fw_run_transaction); +} + +static const struct fw_card_driver dummy_card_driver; + +static int config_rom_parser_test_init(struct kunit *test) +{ + struct fw_device *device; + struct device *dev; + + device = kunit_kzalloc(test, sizeof(*device), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, device); + + device->node = kunit_kzalloc(test, sizeof(*device->node), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, device->node); + kref_init(&device->node->kref); + + device->card = kunit_kzalloc(test, sizeof(*device->card), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, device->card); + + dev = kunit_device_register(test, "dummy-device"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + + fw_card_initialize(device->card, &dummy_card_driver, dev); + + test->priv = device; + + return 0; +} + +static void config_rom_parser_test_exit(struct kunit *test) +{ + struct fw_device *device = test->priv; + + kunit_device_unregister(test, device->card->device); + kunit_kfree(test, device->card); + kunit_kfree(test, device->node); + kunit_kfree(test, device); +} static struct kunit_case config_rom_parser_test_cases[] = { + KUNIT_CASE_PARAM(test_parser_with_regular_cases, parser_test_gen_params), {} }; static struct kunit_suite config_rom_parser_test_suite = { .name = "firewire-config-rom-parser", + .init = config_rom_parser_test_init, + .exit = config_rom_parser_test_exit, .test_cases = config_rom_parser_test_cases, }; kunit_test_suite(config_rom_parser_test_suite); diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 016070560c74..2d64ab5b0ab0 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -24,6 +24,7 @@ #include <linux/timer.h> #include <linux/types.h> #include <linux/workqueue.h> +#include <kunit/static_stub.h> #include <asm/byteorder.h> @@ -485,6 +486,9 @@ int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, int generation, int speed, unsigned long long offset, void *payload, size_t length) { + KUNIT_STATIC_STUB_REDIRECT(fw_run_transaction, card, tcode, destination_id, generation, + speed, offset, payload, length); + struct transaction_callback_data d; struct fw_transaction t; |
