| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Vinod Koul <vkoul@kernel.org> |
| Date: Mon, 13 Jan 2020 14:10:04 +0530 |
| Subject: FROMLIST: usb: renesas-xhci: allow multiple firmware versions |
| |
| Allow multiple firmware file versions in table and load them in |
| increasing order as we find them in the file system. |
| |
| Signed-off-by: Vinod Koul <vkoul@kernel.org> |
| Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> |
| Cc: Christian Lamparter <chunkeey@googlemail.com> |
| Signed-off-by: John Stultz <john.stultz@linaro.org> |
| Bug: 146449535 |
| Change-Id: If3a1e3b0dd467bb0ce4c7728828b34a05edae05c |
| Link: https://lore.kernel.org/linux-arm-msm/20200113084005.849071-5-vkoul@kernel.org/ |
| --- |
| drivers/usb/host/xhci-pci-renesas.c | 45 +++++++++++++++++++++++++++-- |
| 1 file changed, 43 insertions(+), 2 deletions(-) |
| |
| diff --git a/drivers/usb/host/xhci-pci-renesas.c b/drivers/usb/host/xhci-pci-renesas.c |
| index 1d073c5637c4..fe95487ca888 100644 |
| --- a/drivers/usb/host/xhci-pci-renesas.c |
| +++ b/drivers/usb/host/xhci-pci-renesas.c |
| @@ -73,13 +73,20 @@ static const struct renesas_fw_entry { |
| * - uPD720201 ES 2.0 sample whose revision ID is 2. |
| * - uPD720201 ES 2.1 sample & CS sample & Mass product, ID is 3. |
| * - uPD720202 ES 2.0 sample & CS sample & Mass product, ID is 2. |
| + * |
| + * Entry expected_version should be kept in decreasing order for a |
| + * chip, so that driver will pick latest version and if that fails |
| + * then next one will be picked |
| */ |
| { "K2013080.mem", 0x0014, 0x02, 0x2013 }, |
| + { "K2026090.mem", 0x0014, 0x03, 0x2026 }, |
| { "K2013080.mem", 0x0014, 0x03, 0x2013 }, |
| + { "K2026090.mem", 0x0015, 0x02, 0x2026 }, |
| { "K2013080.mem", 0x0015, 0x02, 0x2013 }, |
| }; |
| |
| MODULE_FIRMWARE("K2013080.mem"); |
| +MODULE_FIRMWARE("K2026090.mem"); |
| |
| static const struct renesas_fw_entry *renesas_needs_fw_dl(struct pci_dev *dev) |
| { |
| @@ -100,6 +107,24 @@ static const struct renesas_fw_entry *renesas_needs_fw_dl(struct pci_dev *dev) |
| return NULL; |
| } |
| |
| +static const struct |
| +renesas_fw_entry *renesas_get_next_entry(struct pci_dev *dev, |
| + const struct renesas_fw_entry *entry) |
| +{ |
| + const struct renesas_fw_entry *next_entry; |
| + size_t i; |
| + |
| + for (i = 0; i < ARRAY_SIZE(renesas_fw_table); i++) { |
| + next_entry = &renesas_fw_table[i]; |
| + if (next_entry->device == dev->device && |
| + next_entry->revision == dev->revision && |
| + next_entry->expected_version < entry->expected_version) |
| + return next_entry; |
| + } |
| + |
| + return NULL; |
| +} |
| + |
| static int renesas_fw_download_image(struct pci_dev *dev, |
| const u32 *fw, |
| size_t step) |
| @@ -700,13 +725,29 @@ static void renesas_fw_callback(const struct firmware *fw, |
| struct renesas_fw_ctx *ctx = context; |
| struct pci_dev *pdev = ctx->pdev; |
| struct device *parent = pdev->dev.parent; |
| + const struct renesas_fw_entry *next_entry; |
| bool rom; |
| int err; |
| |
| if (!fw) { |
| dev_err(&pdev->dev, "firmware failed to load\n"); |
| - |
| - goto cleanup; |
| + /* |
| + * we didn't find firmware, check if we have another |
| + * entry for this device |
| + */ |
| + next_entry = renesas_get_next_entry(ctx->pdev, ctx->entry); |
| + if (next_entry) { |
| + ctx->entry = next_entry; |
| + dev_dbg(&pdev->dev, "Found next entry, requesting: %s\n", |
| + next_entry->firmware_name); |
| + request_firmware_nowait(THIS_MODULE, 1, |
| + next_entry->firmware_name, |
| + &pdev->dev, GFP_KERNEL, |
| + ctx, renesas_fw_callback); |
| + return; |
| + } else { |
| + goto cleanup; |
| + } |
| } |
| |
| err = renesas_fw_verify(pdev, fw->data, fw->size); |