Commit 90e05ef3 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'net-dsa-microchip-add-support-for-credit-based-shaper'

Arun Ramadoss says:

====================
net: dsa: microchip: add support for credit based shaper

LAN937x switch family, KSZ9477, KSZ9567, KSZ9563 and KSZ8563 supports
the credit based shaper. But there were few difference between LAN937x and KSZ
switch like
- number of queues for LAN937x is 8 and for others it is 4.
- size of credit increment register for LAN937x is 24 and for other is 16-bit.
This patch series add the credit based shaper with common implementation for
LAN937x and KSZ swithes.
====================

Link: https://lore.kernel.org/r/20230120052135.32120-1-arun.ramadoss@microchip.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 3176eb82 71d7920f
...@@ -980,6 +980,22 @@ int ksz9477_set_ageing_time(struct ksz_device *dev, unsigned int msecs) ...@@ -980,6 +980,22 @@ int ksz9477_set_ageing_time(struct ksz_device *dev, unsigned int msecs)
return ksz_write8(dev, REG_SW_LUE_CTRL_0, value); return ksz_write8(dev, REG_SW_LUE_CTRL_0, value);
} }
void ksz9477_port_queue_split(struct ksz_device *dev, int port)
{
u8 data;
if (dev->info->num_tx_queues == 8)
data = PORT_EIGHT_QUEUE;
else if (dev->info->num_tx_queues == 4)
data = PORT_FOUR_QUEUE;
else if (dev->info->num_tx_queues == 2)
data = PORT_TWO_QUEUE;
else
data = PORT_SINGLE_QUEUE;
ksz_prmw8(dev, port, REG_PORT_CTRL_0, PORT_QUEUE_SPLIT_MASK, data);
}
void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
{ {
struct dsa_switch *ds = dev->ds; struct dsa_switch *ds = dev->ds;
...@@ -991,6 +1007,8 @@ void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) ...@@ -991,6 +1007,8 @@ void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
ksz_port_cfg(dev, port, REG_PORT_CTRL_0, PORT_TAIL_TAG_ENABLE, ksz_port_cfg(dev, port, REG_PORT_CTRL_0, PORT_TAIL_TAG_ENABLE,
true); true);
ksz9477_port_queue_split(dev, port);
ksz_port_cfg(dev, port, REG_PORT_CTRL_0, PORT_MAC_LOOPBACK, false); ksz_port_cfg(dev, port, REG_PORT_CTRL_0, PORT_MAC_LOOPBACK, false);
/* set back pressure */ /* set back pressure */
...@@ -1166,6 +1184,13 @@ u32 ksz9477_get_port_addr(int port, int offset) ...@@ -1166,6 +1184,13 @@ u32 ksz9477_get_port_addr(int port, int offset)
return PORT_CTRL_ADDR(port, offset); return PORT_CTRL_ADDR(port, offset);
} }
int ksz9477_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val)
{
val = val >> 8;
return ksz_pwrite16(dev, port, REG_PORT_MTI_CREDIT_INCREMENT, val);
}
int ksz9477_switch_init(struct ksz_device *dev) int ksz9477_switch_init(struct ksz_device *dev)
{ {
u8 data8; u8 data8;
......
...@@ -51,10 +51,12 @@ int ksz9477_mdb_del(struct ksz_device *dev, int port, ...@@ -51,10 +51,12 @@ int ksz9477_mdb_del(struct ksz_device *dev, int port,
const struct switchdev_obj_port_mdb *mdb, struct dsa_db db); const struct switchdev_obj_port_mdb *mdb, struct dsa_db db);
int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu); int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu);
void ksz9477_config_cpu_port(struct dsa_switch *ds); void ksz9477_config_cpu_port(struct dsa_switch *ds);
int ksz9477_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val);
int ksz9477_enable_stp_addr(struct ksz_device *dev); int ksz9477_enable_stp_addr(struct ksz_device *dev);
int ksz9477_reset_switch(struct ksz_device *dev); int ksz9477_reset_switch(struct ksz_device *dev);
int ksz9477_dsa_init(struct ksz_device *dev); int ksz9477_dsa_init(struct ksz_device *dev);
int ksz9477_switch_init(struct ksz_device *dev); int ksz9477_switch_init(struct ksz_device *dev);
void ksz9477_switch_exit(struct ksz_device *dev); void ksz9477_switch_exit(struct ksz_device *dev);
void ksz9477_port_queue_split(struct ksz_device *dev, int port);
#endif #endif
...@@ -850,7 +850,11 @@ ...@@ -850,7 +850,11 @@
#define PORT_FORCE_TX_FLOW_CTRL BIT(4) #define PORT_FORCE_TX_FLOW_CTRL BIT(4)
#define PORT_FORCE_RX_FLOW_CTRL BIT(3) #define PORT_FORCE_RX_FLOW_CTRL BIT(3)
#define PORT_TAIL_TAG_ENABLE BIT(2) #define PORT_TAIL_TAG_ENABLE BIT(2)
#define PORT_QUEUE_SPLIT_ENABLE 0x3 #define PORT_QUEUE_SPLIT_MASK GENMASK(1, 0)
#define PORT_EIGHT_QUEUE 0x3
#define PORT_FOUR_QUEUE 0x2
#define PORT_TWO_QUEUE 0x1
#define PORT_SINGLE_QUEUE 0x0
#define REG_PORT_CTRL_1 0x0021 #define REG_PORT_CTRL_1 0x0021
...@@ -1480,33 +1484,10 @@ ...@@ -1480,33 +1484,10 @@
/* 9 - Shaping */ /* 9 - Shaping */
#define REG_PORT_MTI_QUEUE_INDEX__4 0x0900
#define REG_PORT_MTI_QUEUE_CTRL_0__4 0x0904 #define REG_PORT_MTI_QUEUE_CTRL_0__4 0x0904
#define MTI_PVID_REPLACE BIT(0) #define MTI_PVID_REPLACE BIT(0)
#define REG_PORT_MTI_QUEUE_CTRL_0 0x0914
#define MTI_SCHEDULE_MODE_M 0x3
#define MTI_SCHEDULE_MODE_S 6
#define MTI_SCHEDULE_STRICT_PRIO 0
#define MTI_SCHEDULE_WRR 2
#define MTI_SHAPING_M 0x3
#define MTI_SHAPING_S 4
#define MTI_SHAPING_OFF 0
#define MTI_SHAPING_SRP 1
#define MTI_SHAPING_TIME_AWARE 2
#define REG_PORT_MTI_QUEUE_CTRL_1 0x0915
#define MTI_TX_RATIO_M (BIT(7) - 1)
#define REG_PORT_MTI_QUEUE_CTRL_2__2 0x0916
#define REG_PORT_MTI_HI_WATER_MARK 0x0916
#define REG_PORT_MTI_QUEUE_CTRL_3__2 0x0918
#define REG_PORT_MTI_LO_WATER_MARK 0x0918
#define REG_PORT_MTI_QUEUE_CTRL_4__2 0x091A
#define REG_PORT_MTI_CREDIT_INCREMENT 0x091A #define REG_PORT_MTI_CREDIT_INCREMENT 0x091A
/* A - QM */ /* A - QM */
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/of_net.h> #include <linux/of_net.h>
#include <linux/micrel_phy.h> #include <linux/micrel_phy.h>
#include <net/dsa.h> #include <net/dsa.h>
#include <net/pkt_cls.h>
#include <net/switchdev.h> #include <net/switchdev.h>
#include "ksz_common.h" #include "ksz_common.h"
...@@ -31,6 +32,10 @@ ...@@ -31,6 +32,10 @@
#include "ksz9477.h" #include "ksz9477.h"
#include "lan937x.h" #include "lan937x.h"
#define KSZ_CBS_ENABLE ((MTI_SCHEDULE_STRICT_PRIO << MTI_SCHEDULE_MODE_S) | \
(MTI_SHAPING_SRP << MTI_SHAPING_S))
#define KSZ_CBS_DISABLE ((MTI_SCHEDULE_WRR << MTI_SCHEDULE_MODE_S) |\
(MTI_SHAPING_OFF << MTI_SHAPING_S))
#define MIB_COUNTER_NUM 0x20 #define MIB_COUNTER_NUM 0x20
struct ksz_stats_raw { struct ksz_stats_raw {
...@@ -250,6 +255,7 @@ static const struct ksz_dev_ops ksz9477_dev_ops = { ...@@ -250,6 +255,7 @@ static const struct ksz_dev_ops ksz9477_dev_ops = {
.change_mtu = ksz9477_change_mtu, .change_mtu = ksz9477_change_mtu,
.phylink_mac_link_up = ksz9477_phylink_mac_link_up, .phylink_mac_link_up = ksz9477_phylink_mac_link_up,
.config_cpu_port = ksz9477_config_cpu_port, .config_cpu_port = ksz9477_config_cpu_port,
.tc_cbs_set_cinc = ksz9477_tc_cbs_set_cinc,
.enable_stp_addr = ksz9477_enable_stp_addr, .enable_stp_addr = ksz9477_enable_stp_addr,
.reset = ksz9477_reset_switch, .reset = ksz9477_reset_switch,
.init = ksz9477_switch_init, .init = ksz9477_switch_init,
...@@ -286,6 +292,7 @@ static const struct ksz_dev_ops lan937x_dev_ops = { ...@@ -286,6 +292,7 @@ static const struct ksz_dev_ops lan937x_dev_ops = {
.change_mtu = lan937x_change_mtu, .change_mtu = lan937x_change_mtu,
.phylink_mac_link_up = ksz9477_phylink_mac_link_up, .phylink_mac_link_up = ksz9477_phylink_mac_link_up,
.config_cpu_port = lan937x_config_cpu_port, .config_cpu_port = lan937x_config_cpu_port,
.tc_cbs_set_cinc = lan937x_tc_cbs_set_cinc,
.enable_stp_addr = ksz9477_enable_stp_addr, .enable_stp_addr = ksz9477_enable_stp_addr,
.reset = lan937x_reset_switch, .reset = lan937x_reset_switch,
.init = lan937x_switch_init, .init = lan937x_switch_init,
...@@ -1080,6 +1087,8 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1080,6 +1087,8 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.cpu_ports = 0x07, /* can be configured as cpu port */ .cpu_ports = 0x07, /* can be configured as cpu port */
.port_cnt = 3, /* total port count */ .port_cnt = 3, /* total port count */
.port_nirqs = 3, .port_nirqs = 3,
.num_tx_queues = 4,
.tc_cbs_supported = true,
.ops = &ksz9477_dev_ops, .ops = &ksz9477_dev_ops,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
...@@ -1106,6 +1115,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1106,6 +1115,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_statics = 8, .num_statics = 8,
.cpu_ports = 0x10, /* can be configured as cpu port */ .cpu_ports = 0x10, /* can be configured as cpu port */
.port_cnt = 5, /* total cpu and user ports */ .port_cnt = 5, /* total cpu and user ports */
.num_tx_queues = 4,
.ops = &ksz8_dev_ops, .ops = &ksz8_dev_ops,
.ksz87xx_eee_link_erratum = true, .ksz87xx_eee_link_erratum = true,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
...@@ -1144,6 +1154,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1144,6 +1154,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_statics = 8, .num_statics = 8,
.cpu_ports = 0x10, /* can be configured as cpu port */ .cpu_ports = 0x10, /* can be configured as cpu port */
.port_cnt = 5, /* total cpu and user ports */ .port_cnt = 5, /* total cpu and user ports */
.num_tx_queues = 4,
.ops = &ksz8_dev_ops, .ops = &ksz8_dev_ops,
.ksz87xx_eee_link_erratum = true, .ksz87xx_eee_link_erratum = true,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
...@@ -1168,6 +1179,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1168,6 +1179,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_statics = 8, .num_statics = 8,
.cpu_ports = 0x10, /* can be configured as cpu port */ .cpu_ports = 0x10, /* can be configured as cpu port */
.port_cnt = 5, /* total cpu and user ports */ .port_cnt = 5, /* total cpu and user ports */
.num_tx_queues = 4,
.ops = &ksz8_dev_ops, .ops = &ksz8_dev_ops,
.ksz87xx_eee_link_erratum = true, .ksz87xx_eee_link_erratum = true,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
...@@ -1192,6 +1204,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1192,6 +1204,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.num_statics = 8, .num_statics = 8,
.cpu_ports = 0x4, /* can be configured as cpu port */ .cpu_ports = 0x4, /* can be configured as cpu port */
.port_cnt = 3, .port_cnt = 3,
.num_tx_queues = 4,
.ops = &ksz8_dev_ops, .ops = &ksz8_dev_ops,
.mib_names = ksz88xx_mib_names, .mib_names = ksz88xx_mib_names,
.mib_cnt = ARRAY_SIZE(ksz88xx_mib_names), .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names),
...@@ -1213,6 +1226,8 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1213,6 +1226,8 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.cpu_ports = 0x7F, /* can be configured as cpu port */ .cpu_ports = 0x7F, /* can be configured as cpu port */
.port_cnt = 7, /* total physical port count */ .port_cnt = 7, /* total physical port count */
.port_nirqs = 4, .port_nirqs = 4,
.num_tx_queues = 4,
.tc_cbs_supported = true,
.ops = &ksz9477_dev_ops, .ops = &ksz9477_dev_ops,
.phy_errata_9477 = true, .phy_errata_9477 = true,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
...@@ -1245,6 +1260,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1245,6 +1260,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.cpu_ports = 0x3F, /* can be configured as cpu port */ .cpu_ports = 0x3F, /* can be configured as cpu port */
.port_cnt = 6, /* total physical port count */ .port_cnt = 6, /* total physical port count */
.port_nirqs = 2, .port_nirqs = 2,
.num_tx_queues = 4,
.ops = &ksz9477_dev_ops, .ops = &ksz9477_dev_ops,
.phy_errata_9477 = true, .phy_errata_9477 = true,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
...@@ -1277,6 +1293,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1277,6 +1293,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.cpu_ports = 0x7F, /* can be configured as cpu port */ .cpu_ports = 0x7F, /* can be configured as cpu port */
.port_cnt = 7, /* total physical port count */ .port_cnt = 7, /* total physical port count */
.port_nirqs = 2, .port_nirqs = 2,
.num_tx_queues = 4,
.ops = &ksz9477_dev_ops, .ops = &ksz9477_dev_ops,
.phy_errata_9477 = true, .phy_errata_9477 = true,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
...@@ -1307,6 +1324,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1307,6 +1324,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.cpu_ports = 0x07, /* can be configured as cpu port */ .cpu_ports = 0x07, /* can be configured as cpu port */
.port_cnt = 3, /* total port count */ .port_cnt = 3, /* total port count */
.port_nirqs = 2, .port_nirqs = 2,
.num_tx_queues = 4,
.ops = &ksz9477_dev_ops, .ops = &ksz9477_dev_ops,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
...@@ -1332,6 +1350,8 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1332,6 +1350,8 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.cpu_ports = 0x07, /* can be configured as cpu port */ .cpu_ports = 0x07, /* can be configured as cpu port */
.port_cnt = 3, /* total port count */ .port_cnt = 3, /* total port count */
.port_nirqs = 3, .port_nirqs = 3,
.num_tx_queues = 4,
.tc_cbs_supported = true,
.ops = &ksz9477_dev_ops, .ops = &ksz9477_dev_ops,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
...@@ -1357,6 +1377,8 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1357,6 +1377,8 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.cpu_ports = 0x7F, /* can be configured as cpu port */ .cpu_ports = 0x7F, /* can be configured as cpu port */
.port_cnt = 7, /* total physical port count */ .port_cnt = 7, /* total physical port count */
.port_nirqs = 3, .port_nirqs = 3,
.num_tx_queues = 4,
.tc_cbs_supported = true,
.ops = &ksz9477_dev_ops, .ops = &ksz9477_dev_ops,
.phy_errata_9477 = true, .phy_errata_9477 = true,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
...@@ -1387,6 +1409,8 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1387,6 +1409,8 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.cpu_ports = 0x10, /* can be configured as cpu port */ .cpu_ports = 0x10, /* can be configured as cpu port */
.port_cnt = 5, /* total physical port count */ .port_cnt = 5, /* total physical port count */
.port_nirqs = 6, .port_nirqs = 6,
.num_tx_queues = 8,
.tc_cbs_supported = true,
.ops = &lan937x_dev_ops, .ops = &lan937x_dev_ops,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
...@@ -1411,6 +1435,8 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1411,6 +1435,8 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.cpu_ports = 0x30, /* can be configured as cpu port */ .cpu_ports = 0x30, /* can be configured as cpu port */
.port_cnt = 6, /* total physical port count */ .port_cnt = 6, /* total physical port count */
.port_nirqs = 6, .port_nirqs = 6,
.num_tx_queues = 8,
.tc_cbs_supported = true,
.ops = &lan937x_dev_ops, .ops = &lan937x_dev_ops,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
...@@ -1435,6 +1461,8 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1435,6 +1461,8 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.cpu_ports = 0x30, /* can be configured as cpu port */ .cpu_ports = 0x30, /* can be configured as cpu port */
.port_cnt = 8, /* total physical port count */ .port_cnt = 8, /* total physical port count */
.port_nirqs = 6, .port_nirqs = 6,
.num_tx_queues = 8,
.tc_cbs_supported = true,
.ops = &lan937x_dev_ops, .ops = &lan937x_dev_ops,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
...@@ -1463,6 +1491,8 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1463,6 +1491,8 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.cpu_ports = 0x38, /* can be configured as cpu port */ .cpu_ports = 0x38, /* can be configured as cpu port */
.port_cnt = 5, /* total physical port count */ .port_cnt = 5, /* total physical port count */
.port_nirqs = 6, .port_nirqs = 6,
.num_tx_queues = 8,
.tc_cbs_supported = true,
.ops = &lan937x_dev_ops, .ops = &lan937x_dev_ops,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
...@@ -1491,6 +1521,8 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1491,6 +1521,8 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.cpu_ports = 0x30, /* can be configured as cpu port */ .cpu_ports = 0x30, /* can be configured as cpu port */
.port_cnt = 8, /* total physical port count */ .port_cnt = 8, /* total physical port count */
.port_nirqs = 6, .port_nirqs = 6,
.num_tx_queues = 8,
.tc_cbs_supported = true,
.ops = &lan937x_dev_ops, .ops = &lan937x_dev_ops,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
...@@ -2065,6 +2097,8 @@ static int ksz_setup(struct dsa_switch *ds) ...@@ -2065,6 +2097,8 @@ static int ksz_setup(struct dsa_switch *ds)
dev->dev_ops->enable_stp_addr(dev); dev->dev_ops->enable_stp_addr(dev);
ds->num_tx_queues = dev->info->num_tx_queues;
regmap_update_bits(dev->regmap[0], regs[S_MULTICAST_CTRL], regmap_update_bits(dev->regmap[0], regs[S_MULTICAST_CTRL],
MULTICAST_STORM_DISABLE, MULTICAST_STORM_DISABLE); MULTICAST_STORM_DISABLE, MULTICAST_STORM_DISABLE);
...@@ -2958,6 +2992,101 @@ static int ksz_switch_detect(struct ksz_device *dev) ...@@ -2958,6 +2992,101 @@ static int ksz_switch_detect(struct ksz_device *dev)
return 0; return 0;
} }
/* Bandwidth is calculated by idle slope/transmission speed. Then the Bandwidth
* is converted to Hex-decimal using the successive multiplication method. On
* every step, integer part is taken and decimal part is carry forwarded.
*/
static int cinc_cal(s32 idle_slope, s32 send_slope, u32 *bw)
{
u32 cinc = 0;
u32 txrate;
u32 rate;
u8 temp;
u8 i;
txrate = idle_slope - send_slope;
if (!txrate)
return -EINVAL;
rate = idle_slope;
/* 24 bit register */
for (i = 0; i < 6; i++) {
rate = rate * 16;
temp = rate / txrate;
rate %= txrate;
cinc = ((cinc << 4) | temp);
}
*bw = cinc;
return 0;
}
static int ksz_setup_tc_cbs(struct dsa_switch *ds, int port,
struct tc_cbs_qopt_offload *qopt)
{
struct ksz_device *dev = ds->priv;
int ret;
u32 bw;
if (!dev->info->tc_cbs_supported)
return -EOPNOTSUPP;
if (qopt->queue > dev->info->num_tx_queues)
return -EINVAL;
/* Queue Selection */
ret = ksz_pwrite32(dev, port, REG_PORT_MTI_QUEUE_INDEX__4, qopt->queue);
if (ret)
return ret;
if (!qopt->enable)
return ksz_pwrite8(dev, port, REG_PORT_MTI_QUEUE_CTRL_0,
KSZ_CBS_DISABLE);
/* High Credit */
ret = ksz_pwrite16(dev, port, REG_PORT_MTI_HI_WATER_MARK,
qopt->hicredit);
if (ret)
return ret;
/* Low Credit */
ret = ksz_pwrite16(dev, port, REG_PORT_MTI_LO_WATER_MARK,
qopt->locredit);
if (ret)
return ret;
/* Credit Increment Register */
ret = cinc_cal(qopt->idleslope, qopt->sendslope, &bw);
if (ret)
return ret;
if (dev->dev_ops->tc_cbs_set_cinc) {
ret = dev->dev_ops->tc_cbs_set_cinc(dev, port, bw);
if (ret)
return ret;
}
return ksz_pwrite8(dev, port, REG_PORT_MTI_QUEUE_CTRL_0,
KSZ_CBS_ENABLE);
}
static int ksz_setup_tc(struct dsa_switch *ds, int port,
enum tc_setup_type type, void *type_data)
{
switch (type) {
case TC_SETUP_QDISC_CBS:
return ksz_setup_tc_cbs(ds, port, type_data);
default:
return -EOPNOTSUPP;
}
}
static const struct dsa_switch_ops ksz_switch_ops = { static const struct dsa_switch_ops ksz_switch_ops = {
.get_tag_protocol = ksz_get_tag_protocol, .get_tag_protocol = ksz_get_tag_protocol,
.connect_tag_protocol = ksz_connect_tag_protocol, .connect_tag_protocol = ksz_connect_tag_protocol,
...@@ -3000,6 +3129,7 @@ static const struct dsa_switch_ops ksz_switch_ops = { ...@@ -3000,6 +3129,7 @@ static const struct dsa_switch_ops ksz_switch_ops = {
.port_hwtstamp_set = ksz_hwtstamp_set, .port_hwtstamp_set = ksz_hwtstamp_set,
.port_txtstamp = ksz_port_txtstamp, .port_txtstamp = ksz_port_txtstamp,
.port_rxtstamp = ksz_port_rxtstamp, .port_rxtstamp = ksz_port_rxtstamp,
.port_setup_tc = ksz_setup_tc,
}; };
struct ksz_device *ksz_switch_alloc(struct device *base, void *priv) struct ksz_device *ksz_switch_alloc(struct device *base, void *priv)
......
...@@ -49,6 +49,8 @@ struct ksz_chip_data { ...@@ -49,6 +49,8 @@ struct ksz_chip_data {
int cpu_ports; int cpu_ports;
int port_cnt; int port_cnt;
u8 port_nirqs; u8 port_nirqs;
u8 num_tx_queues;
bool tc_cbs_supported;
const struct ksz_dev_ops *ops; const struct ksz_dev_ops *ops;
bool phy_errata_9477; bool phy_errata_9477;
bool ksz87xx_eee_link_erratum; bool ksz87xx_eee_link_erratum;
...@@ -353,6 +355,7 @@ struct ksz_dev_ops { ...@@ -353,6 +355,7 @@ struct ksz_dev_ops {
struct phy_device *phydev, int speed, struct phy_device *phydev, int speed,
int duplex, bool tx_pause, bool rx_pause); int duplex, bool tx_pause, bool rx_pause);
void (*setup_rgmii_delay)(struct ksz_device *dev, int port); void (*setup_rgmii_delay)(struct ksz_device *dev, int port);
int (*tc_cbs_set_cinc)(struct ksz_device *dev, int port, u32 val);
void (*config_cpu_port)(struct dsa_switch *ds); void (*config_cpu_port)(struct dsa_switch *ds);
int (*enable_stp_addr)(struct ksz_device *dev); int (*enable_stp_addr)(struct ksz_device *dev);
int (*reset)(struct ksz_device *dev); int (*reset)(struct ksz_device *dev);
...@@ -646,6 +649,24 @@ static inline int is_lan937x(struct ksz_device *dev) ...@@ -646,6 +649,24 @@ static inline int is_lan937x(struct ksz_device *dev)
#define KSZ8_LEGAL_PACKET_SIZE 1518 #define KSZ8_LEGAL_PACKET_SIZE 1518
#define KSZ9477_MAX_FRAME_SIZE 9000 #define KSZ9477_MAX_FRAME_SIZE 9000
/* CBS related registers */
#define REG_PORT_MTI_QUEUE_INDEX__4 0x0900
#define REG_PORT_MTI_QUEUE_CTRL_0 0x0914
#define MTI_SCHEDULE_MODE_M 0x3
#define MTI_SCHEDULE_MODE_S 6
#define MTI_SCHEDULE_STRICT_PRIO 0
#define MTI_SCHEDULE_WRR 2
#define MTI_SHAPING_M 0x3
#define MTI_SHAPING_S 4
#define MTI_SHAPING_OFF 0
#define MTI_SHAPING_SRP 1
#define MTI_SHAPING_TIME_AWARE 2
#define REG_PORT_MTI_HI_WATER_MARK 0x0916
#define REG_PORT_MTI_LO_WATER_MARK 0x0918
/* Regmap tables generation */ /* Regmap tables generation */
#define KSZ_SPI_OP_RD 3 #define KSZ_SPI_OP_RD 3
#define KSZ_SPI_OP_WR 2 #define KSZ_SPI_OP_WR 2
......
...@@ -20,4 +20,5 @@ void lan937x_phylink_get_caps(struct ksz_device *dev, int port, ...@@ -20,4 +20,5 @@ void lan937x_phylink_get_caps(struct ksz_device *dev, int port,
struct phylink_config *config); struct phylink_config *config);
void lan937x_setup_rgmii_delay(struct ksz_device *dev, int port); void lan937x_setup_rgmii_delay(struct ksz_device *dev, int port);
int lan937x_set_ageing_time(struct ksz_device *dev, unsigned int msecs); int lan937x_set_ageing_time(struct ksz_device *dev, unsigned int msecs);
int lan937x_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val);
#endif #endif
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "lan937x_reg.h" #include "lan937x_reg.h"
#include "ksz_common.h" #include "ksz_common.h"
#include "ksz9477.h"
#include "lan937x.h" #include "lan937x.h"
static int lan937x_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set) static int lan937x_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
...@@ -180,6 +181,9 @@ void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port) ...@@ -180,6 +181,9 @@ void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port)
lan937x_port_cfg(dev, port, REG_PORT_CTRL_0, lan937x_port_cfg(dev, port, REG_PORT_CTRL_0,
PORT_TAIL_TAG_ENABLE, true); PORT_TAIL_TAG_ENABLE, true);
/* Enable the Port Queue split */
ksz9477_port_queue_split(dev, port);
/* set back pressure for half duplex */ /* set back pressure for half duplex */
lan937x_port_cfg(dev, port, REG_PORT_MAC_CTRL_1, PORT_BACK_PRESSURE, lan937x_port_cfg(dev, port, REG_PORT_MAC_CTRL_1, PORT_BACK_PRESSURE,
true); true);
...@@ -336,6 +340,11 @@ void lan937x_setup_rgmii_delay(struct ksz_device *dev, int port) ...@@ -336,6 +340,11 @@ void lan937x_setup_rgmii_delay(struct ksz_device *dev, int port)
} }
} }
int lan937x_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val)
{
return ksz_pwrite32(dev, port, REG_PORT_MTI_CREDIT_INCREMENT, val);
}
int lan937x_switch_init(struct ksz_device *dev) int lan937x_switch_init(struct ksz_device *dev)
{ {
dev->port_mask = (1 << dev->info->port_cnt) - 1; dev->port_mask = (1 << dev->info->port_cnt) - 1;
......
...@@ -185,6 +185,9 @@ ...@@ -185,6 +185,9 @@
#define P_PRIO_CTRL REG_PORT_MRI_PRIO_CTRL #define P_PRIO_CTRL REG_PORT_MRI_PRIO_CTRL
/* 9 - Shaping */
#define REG_PORT_MTI_CREDIT_INCREMENT 0x091C
/* The port number as per the datasheet */ /* The port number as per the datasheet */
#define RGMII_2_PORT_NUM 5 #define RGMII_2_PORT_NUM 5
#define RGMII_1_PORT_NUM 6 #define RGMII_1_PORT_NUM 6
......
...@@ -178,6 +178,7 @@ MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ8795, KSZ8795_NAME); ...@@ -178,6 +178,7 @@ MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ8795, KSZ8795_NAME);
#define KSZ9477_PTP_TAG_LEN 4 #define KSZ9477_PTP_TAG_LEN 4
#define KSZ9477_PTP_TAG_INDICATION 0x80 #define KSZ9477_PTP_TAG_INDICATION 0x80
#define KSZ9477_TAIL_TAG_PRIO GENMASK(8, 7)
#define KSZ9477_TAIL_TAG_OVERRIDE BIT(9) #define KSZ9477_TAIL_TAG_OVERRIDE BIT(9)
#define KSZ9477_TAIL_TAG_LOOKUP BIT(10) #define KSZ9477_TAIL_TAG_LOOKUP BIT(10)
...@@ -269,6 +270,8 @@ static struct sk_buff *ksz_defer_xmit(struct dsa_port *dp, struct sk_buff *skb) ...@@ -269,6 +270,8 @@ static struct sk_buff *ksz_defer_xmit(struct dsa_port *dp, struct sk_buff *skb)
static struct sk_buff *ksz9477_xmit(struct sk_buff *skb, static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,
struct net_device *dev) struct net_device *dev)
{ {
u16 queue_mapping = skb_get_queue_mapping(skb);
u8 prio = netdev_txq_to_tc(dev, queue_mapping);
struct dsa_port *dp = dsa_slave_to_port(dev); struct dsa_port *dp = dsa_slave_to_port(dev);
__be16 *tag; __be16 *tag;
u8 *addr; u8 *addr;
...@@ -285,6 +288,8 @@ static struct sk_buff *ksz9477_xmit(struct sk_buff *skb, ...@@ -285,6 +288,8 @@ static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,
val = BIT(dp->index); val = BIT(dp->index);
val |= FIELD_PREP(KSZ9477_TAIL_TAG_PRIO, prio);
if (is_link_local_ether_addr(addr)) if (is_link_local_ether_addr(addr))
val |= KSZ9477_TAIL_TAG_OVERRIDE; val |= KSZ9477_TAIL_TAG_OVERRIDE;
...@@ -322,12 +327,15 @@ static const struct dsa_device_ops ksz9477_netdev_ops = { ...@@ -322,12 +327,15 @@ static const struct dsa_device_ops ksz9477_netdev_ops = {
DSA_TAG_DRIVER(ksz9477_netdev_ops); DSA_TAG_DRIVER(ksz9477_netdev_ops);
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9477, KSZ9477_NAME); MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9477, KSZ9477_NAME);
#define KSZ9893_TAIL_TAG_PRIO GENMASK(4, 3)
#define KSZ9893_TAIL_TAG_OVERRIDE BIT(5) #define KSZ9893_TAIL_TAG_OVERRIDE BIT(5)
#define KSZ9893_TAIL_TAG_LOOKUP BIT(6) #define KSZ9893_TAIL_TAG_LOOKUP BIT(6)
static struct sk_buff *ksz9893_xmit(struct sk_buff *skb, static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,
struct net_device *dev) struct net_device *dev)
{ {
u16 queue_mapping = skb_get_queue_mapping(skb);
u8 prio = netdev_txq_to_tc(dev, queue_mapping);
struct dsa_port *dp = dsa_slave_to_port(dev); struct dsa_port *dp = dsa_slave_to_port(dev);
u8 *addr; u8 *addr;
u8 *tag; u8 *tag;
...@@ -343,6 +351,8 @@ static struct sk_buff *ksz9893_xmit(struct sk_buff *skb, ...@@ -343,6 +351,8 @@ static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,
*tag = BIT(dp->index); *tag = BIT(dp->index);
*tag |= FIELD_PREP(KSZ9893_TAIL_TAG_PRIO, prio);
if (is_link_local_ether_addr(addr)) if (is_link_local_ether_addr(addr))
*tag |= KSZ9893_TAIL_TAG_OVERRIDE; *tag |= KSZ9893_TAIL_TAG_OVERRIDE;
...@@ -384,11 +394,14 @@ MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9893, KSZ9893_NAME); ...@@ -384,11 +394,14 @@ MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9893, KSZ9893_NAME);
#define LAN937X_TAIL_TAG_BLOCKING_OVERRIDE BIT(11) #define LAN937X_TAIL_TAG_BLOCKING_OVERRIDE BIT(11)
#define LAN937X_TAIL_TAG_LOOKUP BIT(12) #define LAN937X_TAIL_TAG_LOOKUP BIT(12)
#define LAN937X_TAIL_TAG_VALID BIT(13) #define LAN937X_TAIL_TAG_VALID BIT(13)
#define LAN937X_TAIL_TAG_PRIO GENMASK(10, 8)
#define LAN937X_TAIL_TAG_PORT_MASK 7 #define LAN937X_TAIL_TAG_PORT_MASK 7
static struct sk_buff *lan937x_xmit(struct sk_buff *skb, static struct sk_buff *lan937x_xmit(struct sk_buff *skb,
struct net_device *dev) struct net_device *dev)
{ {
u16 queue_mapping = skb_get_queue_mapping(skb);
u8 prio = netdev_txq_to_tc(dev, queue_mapping);
struct dsa_port *dp = dsa_slave_to_port(dev); struct dsa_port *dp = dsa_slave_to_port(dev);
const struct ethhdr *hdr = eth_hdr(skb); const struct ethhdr *hdr = eth_hdr(skb);
__be16 *tag; __be16 *tag;
...@@ -403,6 +416,8 @@ static struct sk_buff *lan937x_xmit(struct sk_buff *skb, ...@@ -403,6 +416,8 @@ static struct sk_buff *lan937x_xmit(struct sk_buff *skb,
val = BIT(dp->index); val = BIT(dp->index);
val |= FIELD_PREP(LAN937X_TAIL_TAG_PRIO, prio);
if (is_link_local_ether_addr(hdr->h_dest)) if (is_link_local_ether_addr(hdr->h_dest))
val |= LAN937X_TAIL_TAG_BLOCKING_OVERRIDE; val |= LAN937X_TAIL_TAG_BLOCKING_OVERRIDE;
......
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