Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ebc65c36 authored by Vinod Koul's avatar Vinod Koul Committed by John Stultz
Browse files

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: default avatarVinod Koul <vkoul@kernel.org>
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Cc: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
Bug: 146449535
Change-Id: If3a1e3b0dd467bb0ce4c7728828b34a05edae05c
Link: https://lore.kernel.org/linux-arm-msm/20200113084005.849071-5-vkoul@kernel.org/
parent d3e9cfdb
Loading
Loading
Loading
Loading
+43 −2
Original line number Diff line number Diff line
@@ -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,14 +725,30 @@ 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");

		/*
		 * 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);
	if (err)