diff mbox series

[net] net: mscc: fix the injection header

Message ID 20180620085046.2377-1-antoine.tenart@bootlin.com
State Accepted, archived
Delegated to: David Miller
Headers show
Series [net] net: mscc: fix the injection header | expand

Commit Message

Antoine Tenart June 20, 2018, 8:50 a.m. UTC
When injecting frames in the Ocelot switch driver an injection header
(IFH) should be used to configure various parameters related to a given
frame, such as the port onto which the frame should be departed or its
vlan id. Other parameters in the switch configuration can led to an
injected frame being sent without an IFH but this led to various issues
as the per-frame parameters are then not used. This is especially true
when using multiple ports for injection.

The IFH was injected with the wrong endianness which led to the switch
not taking it into account as the IFH_INJ_BYPASS bit was then unset.
(The bit tells the switch to use the IFH over its internal
configuration). This patch fixes it.

In addition to the endianness fix, the IFH is also fixed. As it was
(unwillingly) unused, some of its fields were not configured the right
way.

Fixes: a556c76adc05 ("net: mscc: Add initial Ocelot switch support")
Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
 drivers/net/ethernet/mscc/ocelot.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

Comments

Alexandre Belloni June 20, 2018, 11:29 a.m. UTC | #1
On 20/06/2018 10:50:46+0200, Antoine Ténart wrote:
> When injecting frames in the Ocelot switch driver an injection header
> (IFH) should be used to configure various parameters related to a given
> frame, such as the port onto which the frame should be departed or its
> vlan id. Other parameters in the switch configuration can led to an
> injected frame being sent without an IFH but this led to various issues
> as the per-frame parameters are then not used. This is especially true
> when using multiple ports for injection.
> 
> The IFH was injected with the wrong endianness which led to the switch
> not taking it into account as the IFH_INJ_BYPASS bit was then unset.
> (The bit tells the switch to use the IFH over its internal
> configuration). This patch fixes it.
> 
> In addition to the endianness fix, the IFH is also fixed. As it was
> (unwillingly) unused, some of its fields were not configured the right
> way.
> 
> Fixes: a556c76adc05 ("net: mscc: Add initial Ocelot switch support")
> Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>

> ---
>  drivers/net/ethernet/mscc/ocelot.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
> index fb2c8f8071e6..52c57e0ff617 100644
> --- a/drivers/net/ethernet/mscc/ocelot.c
> +++ b/drivers/net/ethernet/mscc/ocelot.c
> @@ -344,10 +344,9 @@ static int ocelot_port_stop(struct net_device *dev)
>  static int ocelot_gen_ifh(u32 *ifh, struct frame_info *info)
>  {
>  	ifh[0] = IFH_INJ_BYPASS;
> -	ifh[1] = (0xff00 & info->port) >> 8;
> +	ifh[1] = (0xf00 & info->port) >> 8;
>  	ifh[2] = (0xff & info->port) << 24;
> -	ifh[3] = IFH_INJ_POP_CNT_DISABLE | (info->cpuq << 20) |
> -		 (info->tag_type << 16) | info->vid;
> +	ifh[3] = (info->tag_type << 16) | info->vid;
>  
>  	return 0;
>  }
> @@ -370,11 +369,12 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
>  			 QS_INJ_CTRL_SOF, QS_INJ_CTRL, grp);
>  
>  	info.port = BIT(port->chip_port);
> -	info.cpuq = 0xff;
> +	info.tag_type = IFH_TAG_TYPE_C;
> +	info.vid = skb_vlan_tag_get(skb);
>  	ocelot_gen_ifh(ifh, &info);
>  
>  	for (i = 0; i < IFH_LEN; i++)
> -		ocelot_write_rix(ocelot, ifh[i], QS_INJ_WR, grp);
> +		ocelot_write_rix(ocelot, cpu_to_be32(ifh[i]), QS_INJ_WR, grp);
>  
>  	count = (skb->len + 3) / 4;
>  	last = skb->len % 4;
> -- 
> 2.17.1
>
David Miller June 21, 2018, 1:30 a.m. UTC | #2
From: Antoine Tenart <antoine.tenart@bootlin.com>
Date: Wed, 20 Jun 2018 10:50:46 +0200

> When injecting frames in the Ocelot switch driver an injection header
> (IFH) should be used to configure various parameters related to a given
> frame, such as the port onto which the frame should be departed or its
> vlan id. Other parameters in the switch configuration can led to an
> injected frame being sent without an IFH but this led to various issues
> as the per-frame parameters are then not used. This is especially true
> when using multiple ports for injection.
> 
> The IFH was injected with the wrong endianness which led to the switch
> not taking it into account as the IFH_INJ_BYPASS bit was then unset.
> (The bit tells the switch to use the IFH over its internal
> configuration). This patch fixes it.
> 
> In addition to the endianness fix, the IFH is also fixed. As it was
> (unwillingly) unused, some of its fields were not configured the right
> way.
> 
> Fixes: a556c76adc05 ("net: mscc: Add initial Ocelot switch support")
> Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>

Applied, thank you.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index fb2c8f8071e6..52c57e0ff617 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -344,10 +344,9 @@  static int ocelot_port_stop(struct net_device *dev)
 static int ocelot_gen_ifh(u32 *ifh, struct frame_info *info)
 {
 	ifh[0] = IFH_INJ_BYPASS;
-	ifh[1] = (0xff00 & info->port) >> 8;
+	ifh[1] = (0xf00 & info->port) >> 8;
 	ifh[2] = (0xff & info->port) << 24;
-	ifh[3] = IFH_INJ_POP_CNT_DISABLE | (info->cpuq << 20) |
-		 (info->tag_type << 16) | info->vid;
+	ifh[3] = (info->tag_type << 16) | info->vid;
 
 	return 0;
 }
@@ -370,11 +369,12 @@  static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
 			 QS_INJ_CTRL_SOF, QS_INJ_CTRL, grp);
 
 	info.port = BIT(port->chip_port);
-	info.cpuq = 0xff;
+	info.tag_type = IFH_TAG_TYPE_C;
+	info.vid = skb_vlan_tag_get(skb);
 	ocelot_gen_ifh(ifh, &info);
 
 	for (i = 0; i < IFH_LEN; i++)
-		ocelot_write_rix(ocelot, ifh[i], QS_INJ_WR, grp);
+		ocelot_write_rix(ocelot, cpu_to_be32(ifh[i]), QS_INJ_WR, grp);
 
 	count = (skb->len + 3) / 4;
 	last = skb->len % 4;