All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Golle <daniel@makrotopia.org>
To: Beiyan Yun <root@infi.wang>
Cc: u-boot@lists.denx.de, Yao Zi <ziyao@disroot.org>,
	Marek Vasut <marek.vasut+renesas@mailbox.org>,
	Tom Rini <trini@konsulko.com>,
	Jerome Forissier <jerome.forissier@linaro.org>,
	Joe Hershberger <joe.hershberger@ni.com>,
	"Lucien.Jheng" <lucienzx159@gmail.com>,
	Ramon Fried <rfried.dev@gmail.com>,
	Romain Gantois <romain.gantois@bootlin.com>,
	Siddharth Vadapalli <s-vadapalli@ti.com>,
	Weijie Gao <weijie.gao@mediatek.com>
Subject: Re: [PATCH v4 5/5] net: phy: aquantia: use generic firmware loader
Date: Fri, 31 Oct 2025 15:41:19 +0000	[thread overview]
Message-ID: <aQTYn1wbwXXXnlT6@makrotopia.org> (raw)
In-Reply-To: <20251031152348.60571-6-root@infi.wang>

On Fri, Oct 31, 2025 at 11:21:07PM +0800, Beiyan Yun wrote:
> Aquantia PHYs are being used w/o SPI flash in some routers recently.
> Current firmware loader only attempts to load from FS on top of MMC,
> limiting the use on many devices.
> 
> Removed the old firmware loader, migrate to generic firmware loader to
> allow a wider range and runtime override of firmware source. (e.g., USB).
> 
> Tested on Buffalo WXR18000BE10P with UBIFS.

Does the Buffalo WXR18000BE10P use UBIFS as rootfs out-of-the-box, and
include the Aquatia firmware there?

I'm asking because most of the devices supported in OpenWrt don't use
UBIFS on UBI but typically use a squashfs volume, or even a squashfs
filesystem or cpio.gz embedded into the uImage.FIT which is stored
directly on a UBI volume (and not as a file within UBIFS).

Hence it would be crucial to make sure that using
request_firmware_into_buf_via_script()
works for those devices which do not store the firmware on a filesystem
which is directly accessible within U-Boot.
Imho that's also better than using a __weak symbol as it would allow
implementing the board-specific method for acquiring the firmware as a
script rather than having to write C code for each board.

> 
> Signed-off-by: Beiyan Yun <root@infi.wang>
> ---
> 
> Changes in v4:
> - Split firmware upload helpers change
> - Reorder `aquantia_read_fw`
> - Make `aquantia_read_fw` weak to allow overide
> - Rename exit label in `aquantia_read_fw`
> - Kconfig polish
> 
> Changes in v3:
> - Select FW_LOADER with PHY_AQUANTIA_UPLOAD_FW
> 
> Changes in v2:
> - Add support for script based loader
> 
>  drivers/net/phy/Kconfig    |  28 +++++----
>  drivers/net/phy/aquantia.c | 122 ++++++++++++++++++++++---------------
>  2 files changed, 91 insertions(+), 59 deletions(-)
> 
> diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> index 018be98705a..4a74a0d4e8c 100644
> --- a/drivers/net/phy/Kconfig
> +++ b/drivers/net/phy/Kconfig
> @@ -1,4 +1,3 @@
> -
>  config BITBANGMII
>  	bool "Bit-banged ethernet MII management channel support"
>  
> @@ -91,23 +90,30 @@ menuconfig PHY_AQUANTIA
>  config PHY_AQUANTIA_UPLOAD_FW
>  	bool "Aquantia firmware loading support"
>  	depends on PHY_AQUANTIA
> +	select FS_LOADER
> +	select FW_LOADER
>  	help
> -		Aquantia PHYs use firmware which can be either loaded automatically
> -		from storage directly attached to the phy or loaded by the boot loader
> -		via MDIO commands.  The firmware is loaded from a file, specified by
> -		the PHY_AQUANTIA_FW_PART and PHY_AQUANTIA_FW_NAME options.
> +	  Aquantia PHYs use firmware which can be either loaded automatically
> +	  from storage directly attached to the phy or loaded by the boot loader
> +	  via MDIO commands.
> +
> +	  This option enables loading the firmware using the generic
> +	  firmware loader framework.
>  
> -config PHY_AQUANTIA_FW_PART
> -	string "Aquantia firmware partition"
> +config PHY_AQUANTIA_FW_MAX_SIZE
> +	hex "Max firmware size"
>  	depends on PHY_AQUANTIA_UPLOAD_FW
> +	default 0x80000
>  	help
> -		Partition containing the firmware file.
> +	  The maximum size of the Aquantia PHY firmware. This is used to
> +	  allocate a buffer to load the firmware into.
>  
> -config PHY_AQUANTIA_FW_NAME
> -	string "Aquantia firmware filename"
> +config PHY_AQUANTIA_FW_LOADER_SCRIPT
> +	string "Aquantia firmware loader script"
>  	depends on PHY_AQUANTIA_UPLOAD_FW
> +	default "aqr_phy_load_firmware"
>  	help
> -		Firmware filename.
> +	  The firmware loading script variable name.
>  
>  config PHY_ATHEROS
>  	bool "Atheros Ethernet PHYs support"
> diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c
> index 461d4b07a40..934bd17eadd 100644
> --- a/drivers/net/phy/aquantia.c
> +++ b/drivers/net/phy/aquantia.c
> @@ -17,6 +17,10 @@
>  #include <malloc.h>
>  #include <asm/byteorder.h>
>  #include <fs.h>
> +#if (IS_ENABLED(CONFIG_PHY_AQUANTIA_UPLOAD_FW))
> +#include <fs_loader.h>
> +#include <fw_loader.h>
> +#endif
>  
>  #define AQUNTIA_10G_CTL 0x20
>  #define AQUNTIA_VENDOR_P1 0xc400
> @@ -127,51 +131,67 @@ struct fw_header {
>  
>  #pragma pack()
>  
> -#if defined(CONFIG_PHY_AQUANTIA_UPLOAD_FW)
> -static int aquantia_read_fw(u8 **fw_addr, size_t *fw_length)
> +#if (IS_ENABLED(CONFIG_PHY_AQUANTIA_UPLOAD_FW))
> +int __weak aquantia_read_fw(struct phy_device *phydev, u8 **fw_addr,
> +			    size_t *fw_length)
>  {
> -	loff_t length, read;
>  	int ret;
> -	void *addr = NULL;
> -
> -	*fw_addr = NULL;
> -	*fw_length = 0;
> -	debug("Loading Aquantia microcode from %s %s\n",
> -	      CONFIG_PHY_AQUANTIA_FW_PART, CONFIG_PHY_AQUANTIA_FW_NAME);
> -	ret = fs_set_blk_dev("mmc", CONFIG_PHY_AQUANTIA_FW_PART, FS_TYPE_ANY);
> -	if (ret < 0)
> -		goto cleanup;
> -
> -	ret = fs_size(CONFIG_PHY_AQUANTIA_FW_NAME, &length);
> -	if (ret < 0)
> -		goto cleanup;
> -
> -	addr = malloc(length);
> -	if (!addr) {
> -		ret = -ENOMEM;
> -		goto cleanup;
> +	ofnode node;
> +	struct udevice *loader_dev;
> +	const char *fw_name;
> +	u8 *tmp_fw_addr;
> +	size_t tmp_fw_length;
> +
> +	tmp_fw_addr = malloc(CONFIG_PHY_AQUANTIA_FW_MAX_SIZE);
> +	if (!tmp_fw_addr) {
> +		printf("Failed to allocate memory for firmware\n");
> +		return -ENOMEM;
>  	}
>  
> -	ret = fs_set_blk_dev("mmc", CONFIG_PHY_AQUANTIA_FW_PART, FS_TYPE_ANY);
> -	if (ret < 0)
> -		goto cleanup;
> -
> -	ret = fs_read(CONFIG_PHY_AQUANTIA_FW_NAME, (ulong)addr, 0, length,
> -		      &read);
> -	if (ret < 0)
> -		goto cleanup;
> -
> -	*fw_addr = addr;
> -	*fw_length = length;
> -	debug("Found Aquantia microcode.\n");
> -
> -cleanup:
> -	if (ret < 0) {
> -		printf("loading firmware file %s %s failed with error %d\n",
> -		       CONFIG_PHY_AQUANTIA_FW_PART, CONFIG_PHY_AQUANTIA_FW_NAME,
> -		       ret);
> -		free(addr);
> +	/* First, try to load firmware via script */
> +	ret = request_firmware_into_buf_via_script(
> +		tmp_fw_addr, CONFIG_PHY_AQUANTIA_FW_MAX_SIZE,
> +		CONFIG_PHY_AQUANTIA_FW_LOADER_SCRIPT, &tmp_fw_length);
> +	if (ret) {
> +		/* Fallback to DT specified firmware */
> +		node = phy_get_ofnode(phydev);
> +		if (!ofnode_valid(node)) {
> +			printf("Failed to get PHY node\n");
> +			ret = -EINVAL;
> +			goto fail_free;
> +		}
> +
> +		fw_name = ofnode_read_string(node, "firmware-name");
> +		if (!fw_name) {
> +			printf("Failed to get firmware name\n");
> +			ret = -ENOENT;
> +			goto fail_free;
> +		}
> +
> +		ret = get_fs_loader(&loader_dev);
> +		if (ret) {
> +			printf("Failed to get fs_loader instance: %d\n", ret);
> +			goto fail_free;
> +		}
> +
> +		ret = request_firmware_into_buf(loader_dev, fw_name,
> +						tmp_fw_addr,
> +						CONFIG_PHY_AQUANTIA_FW_MAX_SIZE,
> +						0);
> +		if (ret < 0) {
> +			printf("Failed to load firmware %s: %d\n", fw_name,
> +			       ret);
> +			goto fail_free;
> +		}
> +		tmp_fw_length = ret;
>  	}
> +
> +	*fw_addr = tmp_fw_addr;
> +	*fw_length = tmp_fw_length;
> +	return 1;
> +
> +fail_free:
> +	free(tmp_fw_addr);
>  	return ret;
>  }
>  
> @@ -227,6 +247,11 @@ static int aquantia_do_upload_firmware(struct phy_device *phydev,
>  	u32 primary_offset, iram_offset, iram_size, dram_offset, dram_size;
>  	const struct fw_header *header;
>  
> +	if (!addr || !fw_length) {
> +		printf("%s: Invalid firmware data\n", phydev->dev->name);
> +		return -EINVAL;
> +	}
> +
>  	read_crc = (addr[fw_length - 2] << 8) | addr[fw_length - 1];
>  	calculated_crc = crc16_ccitt(0, addr, fw_length - 2);
>  	if (read_crc != calculated_crc) {
> @@ -290,17 +315,18 @@ static int aquantia_do_upload_firmware(struct phy_device *phydev,
>  
>  static int aquantia_upload_firmware(struct phy_device *phydev)
>  {
> -	int ret;
> -	u8 *addr = NULL;
> -	size_t fw_length = 0;
> +	int ret, fwrc;
> +	u8 *fw_addr = NULL;
> +	size_t fw_length;
>  
> -	ret = aquantia_read_fw(&addr, &fw_length);
> -	if (ret != 0)
> -		return ret;
> +	fwrc = aquantia_read_fw(phydev, &fw_addr, &fw_length);
> +	if (fwrc < 0)
> +		return fwrc;
>  
> -	ret = aquantia_do_upload_firmware(phydev, addr, fw_length);
> +	ret = aquantia_do_upload_firmware(phydev, fw_addr, fw_length);
>  
> -	free(addr);
> +	if (fwrc > 0)
> +		free(fw_addr);
>  
>  	return ret;
>  }
> -- 
> 2.47.3
> 

  reply	other threads:[~2025-10-31 15:41 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-31 15:21 [PATCH v4 0/5] net: phy: aquantia: Switch to generic firmware loader Beiyan Yun
2025-10-31 15:21 ` [PATCH v4 1/5] net: phy: aquantia: refresh format Beiyan Yun
2025-10-31 15:51   ` Marek Vasut
2025-10-31 17:21     ` Beiyan Yun
2025-10-31 18:33       ` Marek Vasut
2025-10-31 19:00         ` Tom Rini
2025-10-31 15:21 ` [PATCH v4 2/5] doc: bindings: use upstream bindings for aquantia phy Beiyan Yun
2025-10-31 15:53   ` Marek Vasut
2025-10-31 17:02     ` Beiyan Yun
2025-10-31 17:12       ` Marek Vasut
2025-10-31 15:21 ` [PATCH v4 3/5] net: phy: aquantia: replace the "mdi-reversal" node with "marvell, mdi-cfg-order" Beiyan Yun
2025-10-31 15:21 ` [PATCH v4 4/5] net: phy: aquantia: refactor firmware upload helpers Beiyan Yun
2025-10-31 15:21 ` [PATCH v4 5/5] net: phy: aquantia: use generic firmware loader Beiyan Yun
2025-10-31 15:41   ` Daniel Golle [this message]
2025-10-31 16:09     ` Beiyan Yun
2025-10-31 15:57   ` Marek Vasut
2025-10-31 16:34     ` Beiyan Yun
2025-10-31 16:51       ` Marek Vasut
2025-11-01  7:45         ` Beiyan Yun
2025-11-01 11:54           ` Marek Vasut
2025-11-02  4:57             ` Beiyan Yun
2025-11-02 14:25               ` Marek Vasut

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aQTYn1wbwXXXnlT6@makrotopia.org \
    --to=daniel@makrotopia.org \
    --cc=jerome.forissier@linaro.org \
    --cc=joe.hershberger@ni.com \
    --cc=lucienzx159@gmail.com \
    --cc=marek.vasut+renesas@mailbox.org \
    --cc=rfried.dev@gmail.com \
    --cc=romain.gantois@bootlin.com \
    --cc=root@infi.wang \
    --cc=s-vadapalli@ti.com \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.denx.de \
    --cc=weijie.gao@mediatek.com \
    --cc=ziyao@disroot.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.