diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 554fe2df9365..d7b53d53c116 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -103,6 +103,7 @@ static void bcm_sf2_brcm_hdr_setup(struct bcm_sf2_priv *priv, int port) static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port) { struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); + unsigned int i; u32 reg, offset; if (priv->type == BCM7445_DEVICE_ID) @@ -129,6 +130,14 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port) reg |= MII_DUMB_FWDG_EN; core_writel(priv, reg, CORE_SWITCH_CTRL); + /* Configure Traffic Class to QoS mapping, allow each priority to map + * to a different queue number + */ + reg = core_readl(priv, CORE_PORT_TC2_QOS_MAP_PORT(port)); + for (i = 0; i < SF2_NUM_EGRESS_QUEUES; i++) + reg |= i << (PRT_TO_QID_SHIFT * i); + core_writel(priv, reg, CORE_PORT_TC2_QOS_MAP_PORT(port)); + bcm_sf2_brcm_hdr_setup(priv, port); /* Force link status for IMP port */ @@ -244,7 +253,7 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port, * to a different queue number */ reg = core_readl(priv, CORE_PORT_TC2_QOS_MAP_PORT(port)); - for (i = 0; i < 8; i++) + for (i = 0; i < SF2_NUM_EGRESS_QUEUES; i++) reg |= i << (PRT_TO_QID_SHIFT * i); core_writel(priv, reg, CORE_PORT_TC2_QOS_MAP_PORT(port)); @@ -1151,6 +1160,9 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev) ds = dev->ds; ds->ops = &bcm_sf2_ops; + /* Advertise the 8 egress queues */ + ds->num_tx_queues = SF2_NUM_EGRESS_QUEUES; + dev_set_drvdata(&pdev->dev, priv); spin_lock_init(&priv->indir_lock); diff --git a/drivers/net/dsa/bcm_sf2_regs.h b/drivers/net/dsa/bcm_sf2_regs.h index 26052450091e..49695fcc2ea8 100644 --- a/drivers/net/dsa/bcm_sf2_regs.h +++ b/drivers/net/dsa/bcm_sf2_regs.h @@ -401,4 +401,7 @@ enum bcm_sf2_reg_offs { #define CFP_NUM_RULES 256 +/* Number of egress queues per port */ +#define SF2_NUM_EGRESS_QUEUES 8 + #endif /* __BCM_SF2_REGS_H */ diff --git a/include/net/dsa.h b/include/net/dsa.h index 398ca8d70ccd..dd44d6ce1097 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -243,6 +243,9 @@ struct dsa_switch { /* devlink used to represent this switch device */ struct devlink *devlink; + /* Number of switch port queues */ + unsigned int num_tx_queues; + /* Dynamically allocated ports, keep last */ size_t num_ports; struct dsa_port ports[]; diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 78e78a6e6833..2afa99506f8b 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1259,8 +1259,12 @@ int dsa_slave_create(struct dsa_port *port, const char *name) cpu_dp = ds->dst->cpu_dp; master = cpu_dp->netdev; - slave_dev = alloc_netdev(sizeof(struct dsa_slave_priv), name, - NET_NAME_UNKNOWN, ether_setup); + if (!ds->num_tx_queues) + ds->num_tx_queues = 1; + + slave_dev = alloc_netdev_mqs(sizeof(struct dsa_slave_priv), name, + NET_NAME_UNKNOWN, ether_setup, + ds->num_tx_queues, 1); if (slave_dev == NULL) return -ENOMEM; diff --git a/net/dsa/tag_brcm.c b/net/dsa/tag_brcm.c index de74c3f77818..dbb016434ace 100644 --- a/net/dsa/tag_brcm.c +++ b/net/dsa/tag_brcm.c @@ -62,6 +62,7 @@ static struct sk_buff *brcm_tag_xmit(struct sk_buff *skb, struct net_device *dev) { struct dsa_slave_priv *p = netdev_priv(dev); + u16 queue = skb_get_queue_mapping(skb); u8 *brcm_tag; if (skb_cow_head(skb, BRCM_TAG_LEN) < 0) @@ -78,7 +79,7 @@ static struct sk_buff *brcm_tag_xmit(struct sk_buff *skb, struct net_device *dev * deprecated */ brcm_tag[0] = (1 << BRCM_OPCODE_SHIFT) | - ((skb->priority << BRCM_IG_TC_SHIFT) & BRCM_IG_TC_MASK); + ((queue & BRCM_IG_TC_MASK) << BRCM_IG_TC_SHIFT); brcm_tag[1] = 0; brcm_tag[2] = 0; if (p->dp->index == 8)