diff mbox series

[v2] net: dsa: realtek-smi: fix indirect reg access for ports>3

Message ID 20211126081252.32254-1-luizluca@gmail.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [v2] net: dsa: realtek-smi: fix indirect reg access for ports>3 | expand

Checks

Context Check Description
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix warning Target tree name not specified in the subject
netdev/cover_letter success Single patches do not need cover letters
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers fail 4 blamed authors not CCed: mir@bang-olufsen.dk f.fainelli@gmail.com linus.walleij@linaro.org davem@davemloft.net; 8 maintainers not CCed: mir@bang-olufsen.dk vivien.didelot@gmail.com linus.walleij@linaro.org andrew@lunn.ch f.fainelli@gmail.com olteanv@gmail.com kuba@kernel.org davem@davemloft.net
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 31 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/tree_selection success Guessing tree name failed - patch did not apply

Commit Message

Luiz Angelo Daros de Luca Nov. 26, 2021, 8:12 a.m. UTC
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>

This switch family can have up to 8 ports {0..7}. However,
INDIRECT_ACCESS_ADDRESS_PHYNUM_MASK was using 2 bits instead of 3,
dropping the most significant bit during indirect register reads and
writes. Reading or writing ports 4, 5, 6, and 7 registers was actually
manipulating, respectively, ports 0, 1, 2, and 3 registers.

rtl8365mb_phy_{read,write} will now returns -EINVAL if phy is greater
than 7.

v2:
- fix affected ports in commit message

Fixes: 4af2950c50c8 ("net: dsa: realtek-smi: add rtl8365mb subdriver for RTL8365MB-VC")
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
---
 drivers/net/dsa/rtl8365mb.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

Comments

Greg KH Nov. 26, 2021, 8:21 a.m. UTC | #1
On Fri, Nov 26, 2021 at 05:12:52AM -0300, luizluca@gmail.com wrote:
> From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> 
> This switch family can have up to 8 ports {0..7}. However,
> INDIRECT_ACCESS_ADDRESS_PHYNUM_MASK was using 2 bits instead of 3,
> dropping the most significant bit during indirect register reads and
> writes. Reading or writing ports 4, 5, 6, and 7 registers was actually
> manipulating, respectively, ports 0, 1, 2, and 3 registers.
> 
> rtl8365mb_phy_{read,write} will now returns -EINVAL if phy is greater
> than 7.
> 
> v2:
> - fix affected ports in commit message
> 
> Fixes: 4af2950c50c8 ("net: dsa: realtek-smi: add rtl8365mb subdriver for RTL8365MB-VC")
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> ---
>  drivers/net/dsa/rtl8365mb.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)

<formletter>

This is not the correct way to submit patches for inclusion in the
stable kernel tree.  Please read:
    https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html
for how to do this properly.

</formletter>
Alvin Šipraga Nov. 26, 2021, 9:34 a.m. UTC | #2
Hi Luiz,

Thanks for your patch.

You needn't cc the stable list, since rtl8365mb doesn't exist in any 
stable release just yet. If you send a v3, just target net:

[PATCH net v3] net: dsa: ...

Then the fix will land in 5.16. :-)

On 11/26/21 09:12, luizluca@gmail.com wrote:
> From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> 
> This switch family can have up to 8 ports {0..7}. However,
> INDIRECT_ACCESS_ADDRESS_PHYNUM_MASK was using 2 bits instead of 3,
> dropping the most significant bit during indirect register reads and
> writes. Reading or writing ports 4, 5, 6, and 7 registers was actually
> manipulating, respectively, ports 0, 1, 2, and 3 registers.

Nice catch. Out of curiosity can you share what switch you are testing? 
So far the driver only advertises support for RTL8365MB-VC. Since that 
switch only uses PHY addresses 0~3, it shouldn't be affected by a 
narrower (2-bit) PHYNUM_MASK, right? Are you able to add words to the 
effect of "... now this fixes the driver to work with RTL83xxxx"?

The change is OK except for some comments below:

> 
> rtl8365mb_phy_{read,write} will now returns -EINVAL if phy is greater
> than 7.

I don't think this is really necessary: a valid (device tree) 
configuration should never specify a PHY with address greater than 7. Or 
am I missing something?

> 
> v2:
> - fix affected ports in commit message

The changelog shouldn't end up in the final commit message - please move 
it out in v3.

> 
> Fixes: 4af2950c50c8 ("net: dsa: realtek-smi: add rtl8365mb subdriver for RTL8365MB-VC")
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> ---
>   drivers/net/dsa/rtl8365mb.c | 7 ++++++-
>   1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/dsa/rtl8365mb.c b/drivers/net/dsa/rtl8365mb.c
> index baaae97283c5..f4414ac74b61 100644
> --- a/drivers/net/dsa/rtl8365mb.c
> +++ b/drivers/net/dsa/rtl8365mb.c
> @@ -107,6 +107,7 @@
>   #define RTL8365MB_LEARN_LIMIT_MAX_8365MB_VC	2112
>   
>   /* Family-specific data and limits */
> +#define RTL8365MB_PHYADDRMAX	7
>   #define RTL8365MB_NUM_PHYREGS	32
>   #define RTL8365MB_PHYREGMAX	(RTL8365MB_NUM_PHYREGS - 1)
>   #define RTL8365MB_MAX_NUM_PORTS	(RTL8365MB_CPU_PORT_NUM_8365MB_VC + 1)
> @@ -176,7 +177,7 @@
>   #define RTL8365MB_INDIRECT_ACCESS_STATUS_REG			0x1F01
>   #define RTL8365MB_INDIRECT_ACCESS_ADDRESS_REG			0x1F02
>   #define   RTL8365MB_INDIRECT_ACCESS_ADDRESS_OCPADR_5_1_MASK	GENMASK(4, 0)
> -#define   RTL8365MB_INDIRECT_ACCESS_ADDRESS_PHYNUM_MASK		GENMASK(6, 5)
> +#define   RTL8365MB_INDIRECT_ACCESS_ADDRESS_PHYNUM_MASK		GENMASK(7, 5)
>   #define   RTL8365MB_INDIRECT_ACCESS_ADDRESS_OCPADR_9_6_MASK	GENMASK(11, 8)
>   #define   RTL8365MB_PHY_BASE					0x2000
>   #define RTL8365MB_INDIRECT_ACCESS_WRITE_DATA_REG		0x1F03
> @@ -679,6 +680,8 @@ static int rtl8365mb_phy_read(struct realtek_smi *smi, int phy, int regnum)
>   	u16 val;
>   	int ret;
>   
> +	if (phy > RTL8365MB_PHYADDRMAX)
> +		return -EINVAL;
>   	if (regnum > RTL8365MB_PHYREGMAX)

If you decide to keep these check, please add a newline after your returns.

>   		return -EINVAL;
>   
> @@ -704,6 +707,8 @@ static int rtl8365mb_phy_write(struct realtek_smi *smi, int phy, int regnum,
>   	u32 ocp_addr;
>   	int ret;
>   
> +	if (phy > RTL8365MB_PHYADDRMAX)
> +		return -EINVAL;
>   	if (regnum > RTL8365MB_PHYREGMAX)
>   		return -EINVAL;
>   
>
Luiz Angelo Daros de Luca Nov. 26, 2021, 8:01 p.m. UTC | #3
> Hi Luiz,
>
> Thanks for your patch.
>
> You needn't cc the stable list, since rtl8365mb doesn't exist in any
> stable release just yet. If you send a v3, just target net:
>
> [PATCH net v3] net: dsa: ...
>
> Then the fix will land in 5.16. :-)
>

OK. Thanks. Newbie mistakes...

> On 11/26/21 09:12, luizluca@gmail.com wrote:
> > From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> >
> > This switch family can have up to 8 ports {0..7}. However,
> > INDIRECT_ACCESS_ADDRESS_PHYNUM_MASK was using 2 bits instead of 3,
> > dropping the most significant bit during indirect register reads and
> > writes. Reading or writing ports 4, 5, 6, and 7 registers was actually
> > manipulating, respectively, ports 0, 1, 2, and 3 registers.
>
> Nice catch. Out of curiosity can you share what switch you are testing?
> So far the driver only advertises support for RTL8365MB-VC. Since that
> switch only uses PHY addresses 0~3, it shouldn't be affected by a
> narrower (2-bit) PHYNUM_MASK, right? Are you able to add words to the
> effect of "... now this fixes the driver to work with RTL83xxxx"?

RTL8365MB-VC is one of the smallest one. It was not affected by this
issue as all 4 UTP ports are below 4. I have a RTL8367S with 5
ports+CPU. It took me some days to figure out why wan port (4) was not
working and why indirect register access was mirroring the status from
port 0.

I'm finishing two improvements to the realtek switch driver:
1) realtek mdio interface
2) RTL8367S support (modifying RTL8365MB-VC driver)

Here is my current status:
https://github.com/luizluca/linux/tree/realtek_mdio_refactor (it is a
moving target as I occasionally do forced pushes)

I still don't know how to relate cpu_port to ext_port. I have port 7
and ext_int 2 but that same port 7 would be an UTP port in another
variant. Is there a fixed relation between ext interfaces and port
numbers for each variant? Or is this something defined by the board
configuration? For now, I'm using DSA to determine the CPU port and I
added a new DT property to define the external interface.

rtl8367c_phy_mode_supported also needs to be fixed. For now, it simply
returns true as the default mode is what I needed.

There are also dozens of initializations that the original realtek
device uses like disabling EEE and Gigabit lite that I'm not sure if
we need. I was thinking about adding an DT array property to allow
extra initializations without a kernel rebuild. With a little more
effort, this driver could be able to support other switch variants
only providing extra DT properties.

While looking for the cause of wan port not working, I was mapping
each init table value to a readable defined value but I'm not sure if
it is desired to expand the code with that much information. This
commit is outside my tree for now.

> The change is OK except for some comments below:
>
> >
> > rtl8365mb_phy_{read,write} will now returns -EINVAL if phy is greater
> > than 7.
>
> I don't think this is really necessary: a valid (device tree)
> configuration should never specify a PHY with address greater than 7. Or
> am I missing something?

No, you are correct. A correct DT will never access those register out
of range. However, DT is written by humans. This family supports up to
10 ports (8 UTP + 2 EXT). If someone define a port 8 or 9 in device
tree as an UTP port, the function will silently return port 0 data for
port 8. The error returned here could save some hours. I'll keep that
as it is a cheap test for a low traffic function.

Maybe we should also check if the port is not, according to device
tree, an ext port (fixed-link?) and fail right if it is port 8 or 9.

>
> >
> > v2:
> > - fix affected ports in commit message
>
> The changelog shouldn't end up in the final commit message - please move
> it out in v3.

OK

>
> >
> > Fixes: 4af2950c50c8 ("net: dsa: realtek-smi: add rtl8365mb subdriver for RTL8365MB-VC")
> > Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> > ---
> >   drivers/net/dsa/rtl8365mb.c | 7 ++++++-
> >   1 file changed, 6 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/dsa/rtl8365mb.c b/drivers/net/dsa/rtl8365mb.c
> > index baaae97283c5..f4414ac74b61 100644
> > --- a/drivers/net/dsa/rtl8365mb.c
> > +++ b/drivers/net/dsa/rtl8365mb.c
> > @@ -107,6 +107,7 @@
> >   #define RTL8365MB_LEARN_LIMIT_MAX_8365MB_VC 2112
> >
> >   /* Family-specific data and limits */
> > +#define RTL8365MB_PHYADDRMAX 7
> >   #define RTL8365MB_NUM_PHYREGS       32
> >   #define RTL8365MB_PHYREGMAX (RTL8365MB_NUM_PHYREGS - 1)
> >   #define RTL8365MB_MAX_NUM_PORTS     (RTL8365MB_CPU_PORT_NUM_8365MB_VC + 1)
> > @@ -176,7 +177,7 @@
> >   #define RTL8365MB_INDIRECT_ACCESS_STATUS_REG                        0x1F01
> >   #define RTL8365MB_INDIRECT_ACCESS_ADDRESS_REG                       0x1F02
> >   #define   RTL8365MB_INDIRECT_ACCESS_ADDRESS_OCPADR_5_1_MASK GENMASK(4, 0)
> > -#define   RTL8365MB_INDIRECT_ACCESS_ADDRESS_PHYNUM_MASK              GENMASK(6, 5)
> > +#define   RTL8365MB_INDIRECT_ACCESS_ADDRESS_PHYNUM_MASK              GENMASK(7, 5)
> >   #define   RTL8365MB_INDIRECT_ACCESS_ADDRESS_OCPADR_9_6_MASK GENMASK(11, 8)
> >   #define   RTL8365MB_PHY_BASE                                        0x2000
> >   #define RTL8365MB_INDIRECT_ACCESS_WRITE_DATA_REG            0x1F03
> > @@ -679,6 +680,8 @@ static int rtl8365mb_phy_read(struct realtek_smi *smi, int phy, int regnum)
> >       u16 val;
> >       int ret;
> >
> > +     if (phy > RTL8365MB_PHYADDRMAX)
> > +             return -EINVAL;
> >       if (regnum > RTL8365MB_PHYREGMAX)
>
> If you decide to keep these check, please add a newline after your returns.
>
> >               return -EINVAL;
> >
> > @@ -704,6 +707,8 @@ static int rtl8365mb_phy_write(struct realtek_smi *smi, int phy, int regnum,
> >       u32 ocp_addr;
> >       int ret;
> >
> > +     if (phy > RTL8365MB_PHYADDRMAX)
> > +             return -EINVAL;
> >       if (regnum > RTL8365MB_PHYREGMAX)
> >               return -EINVAL;
> >
> >
>
diff mbox series

Patch

diff --git a/drivers/net/dsa/rtl8365mb.c b/drivers/net/dsa/rtl8365mb.c
index baaae97283c5..f4414ac74b61 100644
--- a/drivers/net/dsa/rtl8365mb.c
+++ b/drivers/net/dsa/rtl8365mb.c
@@ -107,6 +107,7 @@ 
 #define RTL8365MB_LEARN_LIMIT_MAX_8365MB_VC	2112
 
 /* Family-specific data and limits */
+#define RTL8365MB_PHYADDRMAX	7
 #define RTL8365MB_NUM_PHYREGS	32
 #define RTL8365MB_PHYREGMAX	(RTL8365MB_NUM_PHYREGS - 1)
 #define RTL8365MB_MAX_NUM_PORTS	(RTL8365MB_CPU_PORT_NUM_8365MB_VC + 1)
@@ -176,7 +177,7 @@ 
 #define RTL8365MB_INDIRECT_ACCESS_STATUS_REG			0x1F01
 #define RTL8365MB_INDIRECT_ACCESS_ADDRESS_REG			0x1F02
 #define   RTL8365MB_INDIRECT_ACCESS_ADDRESS_OCPADR_5_1_MASK	GENMASK(4, 0)
-#define   RTL8365MB_INDIRECT_ACCESS_ADDRESS_PHYNUM_MASK		GENMASK(6, 5)
+#define   RTL8365MB_INDIRECT_ACCESS_ADDRESS_PHYNUM_MASK		GENMASK(7, 5)
 #define   RTL8365MB_INDIRECT_ACCESS_ADDRESS_OCPADR_9_6_MASK	GENMASK(11, 8)
 #define   RTL8365MB_PHY_BASE					0x2000
 #define RTL8365MB_INDIRECT_ACCESS_WRITE_DATA_REG		0x1F03
@@ -679,6 +680,8 @@  static int rtl8365mb_phy_read(struct realtek_smi *smi, int phy, int regnum)
 	u16 val;
 	int ret;
 
+	if (phy > RTL8365MB_PHYADDRMAX)
+		return -EINVAL;
 	if (regnum > RTL8365MB_PHYREGMAX)
 		return -EINVAL;
 
@@ -704,6 +707,8 @@  static int rtl8365mb_phy_write(struct realtek_smi *smi, int phy, int regnum,
 	u32 ocp_addr;
 	int ret;
 
+	if (phy > RTL8365MB_PHYADDRMAX)
+		return -EINVAL;
 	if (regnum > RTL8365MB_PHYREGMAX)
 		return -EINVAL;