diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index ee239a913e0c..37895107e427 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -14,8 +14,6 @@ struct gb_firmware { struct gb_connection *connection; const struct firmware *fw; - u32 vendor_id; - u32 product_id; }; static void free_firmware(struct gb_firmware *firmware) @@ -31,7 +29,7 @@ static void free_firmware(struct gb_firmware *firmware) * This fetches VID/PID (over firmware protocol) for es2 chip only, when VID/PID * already sent during hotplug are 0. * - * Otherwise, we keep firmware->vendor_id/product_id same as what's passed + * Otherwise, we keep intf->vendor_id/product_id same as what's passed * during hotplug. */ static void firmware_es2_fixup_vid_pid(struct gb_firmware *firmware) @@ -59,11 +57,18 @@ static void firmware_es2_fixup_vid_pid(struct gb_firmware *firmware) return; } - firmware->vendor_id = le32_to_cpu(response.vendor_id); - firmware->product_id = le32_to_cpu(response.product_id); + /* + * NOTE: This is hacked, so that the same values of VID/PID can be used + * by next firmware level as well. The uevent for bootrom will still + * have VID/PID as 0, though after this point the sysfs files will start + * showing the updated values. But yeah, that's a bit racy as the same + * sysfs files would be showing 0 before this point. + */ + intf->vendor_id = le32_to_cpu(response.vendor_id); + intf->product_id = le32_to_cpu(response.product_id); dev_dbg(&connection->bundle->dev, "Firmware got vid (0x%x)/pid (0x%x)\n", - firmware->vendor_id, firmware->product_id); + intf->vendor_id, intf->product_id); } /* This returns path of the firmware blob on the disk */ @@ -86,7 +91,7 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) snprintf(firmware_name, sizeof(firmware_name), "ara_%08x_%08x_%08x_%08x_%02x.tftf", intf->ddbl1_manufacturer_id, intf->ddbl1_product_id, - firmware->vendor_id, firmware->product_id, stage); + intf->vendor_id, intf->product_id, stage); // FIXME: // Turn to dev_dbg later after everyone has valid bootloaders with good @@ -246,9 +251,6 @@ static int gb_firmware_connection_init(struct gb_connection *connection) firmware->connection = connection; connection->private = firmware; - firmware->vendor_id = connection->intf->vendor_id; - firmware->product_id = connection->intf->product_id; - firmware_es2_fixup_vid_pid(firmware); /* Tell bootrom we're ready. */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index feadb624cfd4..85eb7eaae737 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -464,6 +464,8 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) struct gb_host_device *hd = connection->hd; struct gb_interface *intf; u8 intf_id, device_id; + u32 vendor_id = 0; + u32 product_id = 0; int ret; /* The request message size has already been verified. */ @@ -474,6 +476,14 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) intf = gb_interface_find(hd, intf_id); if (intf) { + /* + * For ES2, we need to maintain the same vendor/product ids we + * got from bootrom, otherwise userspace can't distinguish + * between modules. + */ + vendor_id = intf->vendor_id; + product_id = intf->product_id; + /* * We have received a hotplug request for an interface that * already exists. @@ -506,6 +516,20 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) intf->product_id = le32_to_cpu(request->data.ara_prod_id); intf->serial_number = le64_to_cpu(request->data.serial_number); + /* + * Use VID/PID specified at hotplug if: + * - Bridge ASIC chip isn't ES2 + * - Received non-zero Vendor/Product ids + * + * Otherwise, use the ids we received from bootrom. + */ + if (intf->ddbl1_manufacturer_id == ES2_DDBL1_MFR_ID && + intf->ddbl1_product_id == ES2_DDBL1_PROD_ID && + intf->vendor_id == 0 && intf->product_id == 0) { + intf->vendor_id = vendor_id; + intf->product_id = product_id; + } + ret = gb_svc_read_and_clear_module_boot_status(intf); if (ret) { dev_err(&svc->dev, "failed to clear boot status of interface %u: %d\n",