lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <c5ed6991-5b68-f514-2b12-d47d907cdff1@gmail.com>
Date:   Wed, 23 Jan 2019 14:43:52 -0800
From:   Florian Fainelli <f.fainelli@...il.com>
To:     René van Dorst <opensource@...rst.com>,
        Andrew Lunn <andrew@...n.ch>,
        Heiner Kallweit <hkallweit1@...il.com>,
        "David S. Miller" <davem@...emloft.net>, netdev@...r.kernel.org
Subject: Re: [PATCH] sfp: sfp_read: split-up request when hw rx buffer is too
 small.

On 1/23/19 1:20 PM, René van Dorst wrote:
> Without this patch sfp code retries to read the full struct sfp_eeprom_id
> id out of the SFP eeprom. Sizeof(id) is 96 bytes.
> My i2c hardware, Mediatek mt7621, has a rx buffer of 64 bytes.
> So sfp_read gets -NOSUPPORTED back on his turn return -EAGAIN.
> Same issue is with the SFP_EXT_STATUS data which is 92 bytes.
> 
> By split-up the request in multiple smaller requests with a max size of i2c
> max_read_len, we can readout the SFP module successfully.
> 
> Tested with MT7621 and two Fiberstore modules SFP-GB-GE-T and SFP-GE-BX.
> 
> Signed-off-by: René van Dorst <opensource@...rst.com>
> ---
>  drivers/net/phy/sfp.c | 23 ++++++++++++++++++++++-
>  1 file changed, 22 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
> index fd8bb998ae52..1352a19571cd 100644
> --- a/drivers/net/phy/sfp.c
> +++ b/drivers/net/phy/sfp.c
> @@ -367,7 +367,28 @@ static void sfp_set_state(struct sfp *sfp, unsigned int state)
>  
>  static int sfp_read(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len)
>  {
> -	return sfp->read(sfp, a2, addr, buf, len);
> +	const struct i2c_adapter_quirks *q = sfp->i2c->quirks;
> +	int ret;
> +	size_t rx_bytes = 0;
> +
> +	/* Many i2c hw have limited rx buffers, split-up request when needed. */
> +	while ((q->max_read_len) && (len > q->max_read_len)) {
> +		ret = sfp->read(sfp, a2, addr, buf, q->max_read_len);
> +		if (ret < 0)
> +			return ret;
> +		rx_bytes += ret;
> +		addr += q->max_read_len;
> +		buf += q->max_read_len;
> +		len -= q->max_read_len;
> +	}

sfp->read defaults to sfp_i2c_read() but it is possible to override that
by registering a custom sfp_bus instance (nothing does it today, but
that could obviously change), so there is no guarantee that
sfp->i2c->quirks is applicable unless sfp_i2c_read() is used.

sfp_i2c_read() is presumably where the max_read_len splitting should
occur, or better yet, should not i2c_transfer() take care of that on its
own? That way there would be no layering violation of having to fetch
the quirk bitmask for the i2c adapter being used, that is something that
should belong in the core i2c framework.

> +
> +	ret = sfp->read(sfp, a2, addr, buf, len);
> +	if (ret < 0)
> +		return ret;
> +
> +	rx_bytes += ret;
> +
> +	return rx_bytes;
>  }
>  
>  static int sfp_write(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len)
> 


-- 
Florian

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ