Commit 328de467 authored by Oleksij Rempel's avatar Oleksij Rempel Committed by David S. Miller

net: dsa: microchip: add multi queue support for KSZ88X3 variants

KSZ88X3 switches support up to 4 queues. Rework ksz8795_set_prio_queue()
to support KSZ8795 and KSZ88X3 families of switches.

Per default, configure KSZ88X3 to use one queue, since it need special
handling due to priority related errata. Errata handling is implemented
in a separate patch.
Signed-off-by: default avatarOleksij Rempel <o.rempel@pengutronix.de>
Acked-by: default avatarArun Ramadoss <arun.ramadoss@microchip.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 768cf841
......@@ -127,37 +127,56 @@ int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu)
return -EOPNOTSUPP;
}
static void ksz8795_set_prio_queue(struct ksz_device *dev, int port, int queue)
static int ksz8_port_queue_split(struct ksz_device *dev, int port, int queues)
{
u8 hi, lo;
u8 mask_4q, mask_2q;
u8 reg_4q, reg_2q;
u8 data_4q = 0;
u8 data_2q = 0;
int ret;
/* Number of queues can only be 1, 2, or 4. */
switch (queue) {
case 4:
case 3:
queue = PORT_QUEUE_SPLIT_4;
break;
case 2:
queue = PORT_QUEUE_SPLIT_2;
break;
default:
queue = PORT_QUEUE_SPLIT_1;
if (ksz_is_ksz88x3(dev)) {
mask_4q = KSZ8873_PORT_4QUEUE_SPLIT_EN;
mask_2q = KSZ8873_PORT_2QUEUE_SPLIT_EN;
reg_4q = REG_PORT_CTRL_0;
reg_2q = REG_PORT_CTRL_2;
/* KSZ8795 family switches have Weighted Fair Queueing (WFQ)
* enabled by default. Enable it for KSZ8873 family switches
* too. Default value for KSZ8873 family is strict priority,
* which should be enabled by using TC_SETUP_QDISC_ETS, not
* by default.
*/
ret = ksz_rmw8(dev, REG_SW_CTRL_3, WEIGHTED_FAIR_QUEUE_ENABLE,
WEIGHTED_FAIR_QUEUE_ENABLE);
if (ret)
return ret;
} else {
mask_4q = KSZ8795_PORT_4QUEUE_SPLIT_EN;
mask_2q = KSZ8795_PORT_2QUEUE_SPLIT_EN;
reg_4q = REG_PORT_CTRL_13;
reg_2q = REG_PORT_CTRL_0;
/* TODO: this is legacy from initial KSZ8795 driver, should be
* moved to appropriate place in the future.
*/
ret = ksz_rmw8(dev, REG_SW_CTRL_19,
SW_OUT_RATE_LIMIT_QUEUE_BASED,
SW_OUT_RATE_LIMIT_QUEUE_BASED);
if (ret)
return ret;
}
ksz_pread8(dev, port, REG_PORT_CTRL_0, &lo);
ksz_pread8(dev, port, P_DROP_TAG_CTRL, &hi);
lo &= ~PORT_QUEUE_SPLIT_L;
if (queue & PORT_QUEUE_SPLIT_2)
lo |= PORT_QUEUE_SPLIT_L;
hi &= ~PORT_QUEUE_SPLIT_H;
if (queue & PORT_QUEUE_SPLIT_4)
hi |= PORT_QUEUE_SPLIT_H;
ksz_pwrite8(dev, port, REG_PORT_CTRL_0, lo);
ksz_pwrite8(dev, port, P_DROP_TAG_CTRL, hi);
/* Default is port based for egress rate limit. */
if (queue != PORT_QUEUE_SPLIT_1)
ksz_cfg(dev, REG_SW_CTRL_19, SW_OUT_RATE_LIMIT_QUEUE_BASED,
true);
if (queues == 4)
data_4q = mask_4q;
else if (queues == 2)
data_2q = mask_2q;
ret = ksz_prmw8(dev, port, reg_4q, mask_4q, data_4q);
if (ret)
return ret;
return ksz_prmw8(dev, port, reg_2q, mask_2q, data_2q);
}
void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt)
......@@ -1513,6 +1532,7 @@ void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
{
struct dsa_switch *ds = dev->ds;
const u32 *masks;
int queues;
u8 member;
masks = dev->info->masks;
......@@ -1520,8 +1540,15 @@ void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
/* enable broadcast storm limit */
ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true);
if (!ksz_is_ksz88x3(dev))
ksz8795_set_prio_queue(dev, port, 4);
/* For KSZ88x3 enable only one queue by default, otherwise we won't
* be able to get rid of PCP prios on Port 2.
*/
if (ksz_is_ksz88x3(dev))
queues = 1;
else
queues = dev->info->num_tx_queues;
ksz8_port_queue_split(dev, port, queues);
/* disable DiffServ priority */
ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_DIFFSERV_ENABLE, false);
......
......@@ -124,7 +124,8 @@
#define PORT_BASED_PRIO_3 3
#define PORT_INSERT_TAG BIT(2)
#define PORT_REMOVE_TAG BIT(1)
#define PORT_QUEUE_SPLIT_L BIT(0)
#define KSZ8795_PORT_2QUEUE_SPLIT_EN BIT(0)
#define KSZ8873_PORT_4QUEUE_SPLIT_EN BIT(0)
#define REG_PORT_1_CTRL_1 0x11
#define REG_PORT_2_CTRL_1 0x21
......@@ -143,6 +144,7 @@
#define REG_PORT_4_CTRL_2 0x42
#define REG_PORT_5_CTRL_2 0x52
#define KSZ8873_PORT_2QUEUE_SPLIT_EN BIT(7)
#define PORT_INGRESS_FILTER BIT(6)
#define PORT_DISCARD_NON_VID BIT(5)
#define PORT_FORCE_FLOW_CTRL BIT(4)
......@@ -463,10 +465,7 @@
#define REG_PORT_4_CTRL_13 0xE1
#define REG_PORT_5_CTRL_13 0xF1
#define PORT_QUEUE_SPLIT_H BIT(1)
#define PORT_QUEUE_SPLIT_1 0
#define PORT_QUEUE_SPLIT_2 1
#define PORT_QUEUE_SPLIT_4 2
#define KSZ8795_PORT_4QUEUE_SPLIT_EN BIT(1)
#define PORT_DROP_TAG BIT(0)
#define REG_PORT_1_CTRL_14 0xB2
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment