mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 13:23:02 -04:00
net: dsa: microchip: handle KSZ8-specific tc setup in ksz8.c
The setup of QDISC_ETS isn't the same for the KSZ8 switches than for the other switches. It leads to is_ksz8() branches in the common code. Move the KSZ8-specific portions into ksz8.c by creating two setup_tc() functions, one dedicated to the KSZ87xx family that only handles the TC_SETUP_QDISC_CBS case, one for the rest of the KSZ8 that handles both TC_SETUP_QDISC_CBS and TC_SETUP_QDISC_ETS cases. It remains some is_kszXXXX() branches because inside the ksz88xx family, only the ksz88x3 switches support QDISC_ETS. Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com> Link: https://patch.msgid.link/20260702-clean-ksz-4th-v1-7-93441e695fa4@bootlin.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
committed by
Paolo Abeni
parent
ab4b571d44
commit
610106257c
@@ -1782,6 +1782,159 @@ static void ksz8_port_mirror_del(struct dsa_switch *ds, int port,
|
||||
PORT_MIRROR_SNIFFER, false);
|
||||
}
|
||||
|
||||
static u8 ksz8463_tc_ctrl(int port, int queue)
|
||||
{
|
||||
u8 reg;
|
||||
|
||||
reg = 0xC8 + port * 4;
|
||||
reg += ((3 - queue) / 2) * 2;
|
||||
reg++;
|
||||
reg -= (queue & 1);
|
||||
return reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* ksz88x3_tc_ets_add - Configure ETS (Enhanced Transmission Selection)
|
||||
* for a port on KSZ88x3 switch
|
||||
* @dev: Pointer to the KSZ switch device structure
|
||||
* @port: Port number to configure
|
||||
* @p: Pointer to offload replace parameters describing ETS bands and mapping
|
||||
*
|
||||
* The KSZ88x3 supports two scheduling modes: Strict Priority and
|
||||
* Weighted Fair Queuing (WFQ). Both modes have fixed behavior:
|
||||
* - No configurable queue-to-priority mapping
|
||||
* - No weight adjustment in WFQ mode
|
||||
*
|
||||
* This function configures the switch to use strict priority mode by
|
||||
* clearing the WFQ enable bit for all queues associated with ETS bands.
|
||||
* If strict priority is not explicitly requested, the switch will default
|
||||
* to WFQ mode.
|
||||
*
|
||||
* Return: 0 on success, or a negative error code on failure
|
||||
*/
|
||||
static int ksz88x3_tc_ets_add(struct ksz_device *dev, int port,
|
||||
struct tc_ets_qopt_offload_replace_params *p)
|
||||
{
|
||||
int ret, band;
|
||||
|
||||
/* Only strict priority mode is supported for now.
|
||||
* WFQ is implicitly enabled when strict mode is disabled.
|
||||
*/
|
||||
for (band = 0; band < p->bands; band++) {
|
||||
int queue = ksz_ets_band_to_queue(p, band);
|
||||
u8 reg;
|
||||
|
||||
/* Calculate TXQ Split Control register address for this
|
||||
* port/queue
|
||||
*/
|
||||
reg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue);
|
||||
if (ksz_is_ksz8463(dev))
|
||||
reg = ksz8463_tc_ctrl(port, queue);
|
||||
|
||||
/* Clear WFQ enable bit to select strict priority scheduling */
|
||||
ret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ksz88x3_tc_ets_del - Reset ETS (Enhanced Transmission Selection) config
|
||||
* for a port on KSZ88x3 switch
|
||||
* @dev: Pointer to the KSZ switch device structure
|
||||
* @port: Port number to reset
|
||||
*
|
||||
* The KSZ88x3 supports only fixed scheduling modes: Strict Priority or
|
||||
* Weighted Fair Queuing (WFQ), with no reconfiguration of weights or
|
||||
* queue mapping. This function resets the port’s scheduling mode to
|
||||
* the default, which is WFQ, by enabling the WFQ bit for all queues.
|
||||
*
|
||||
* Return: 0 on success, or a negative error code on failure
|
||||
*/
|
||||
static int ksz88x3_tc_ets_del(struct ksz_device *dev, int port)
|
||||
{
|
||||
int ret, queue;
|
||||
|
||||
/* Iterate over all transmit queues for this port */
|
||||
for (queue = 0; queue < dev->info->num_tx_queues; queue++) {
|
||||
u8 reg;
|
||||
|
||||
/* Calculate TXQ Split Control register address for this
|
||||
* port/queue
|
||||
*/
|
||||
reg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue);
|
||||
if (ksz_is_ksz8463(dev))
|
||||
reg = ksz8463_tc_ctrl(port, queue);
|
||||
|
||||
/* Set WFQ enable bit to revert back to default scheduling
|
||||
* mode
|
||||
*/
|
||||
ret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE,
|
||||
KSZ8873_TXQ_WFQ_ENABLE);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ksz8_tc_setup_qdisc_ets(struct dsa_switch *ds, int port,
|
||||
struct tc_ets_qopt_offload *qopt)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
int ret;
|
||||
|
||||
if (!(ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (qopt->parent != TC_H_ROOT) {
|
||||
dev_err(dev->dev, "Parent should be \"root\"\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
switch (qopt->command) {
|
||||
case TC_ETS_REPLACE:
|
||||
ret = ksz_tc_ets_validate(dev, port, &qopt->replace_params);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ksz88x3_tc_ets_add(dev, port, &qopt->replace_params);
|
||||
case TC_ETS_DESTROY:
|
||||
return ksz88x3_tc_ets_del(dev, port);
|
||||
case TC_ETS_STATS:
|
||||
case TC_ETS_GRAFT:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int ksz87xx_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 int ksz8_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);
|
||||
case TC_SETUP_QDISC_ETS:
|
||||
return ksz8_tc_setup_qdisc_ets(ds, port, type_data);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static void ksz8795_cpu_interface_select(struct ksz_device *dev, int port)
|
||||
{
|
||||
struct ksz_port *p = &dev->ports[port];
|
||||
@@ -2645,7 +2798,7 @@ const struct dsa_switch_ops ksz8463_switch_ops = {
|
||||
.port_hwtstamp_set = ksz_hwtstamp_set,
|
||||
.port_txtstamp = ksz_port_txtstamp,
|
||||
.port_rxtstamp = ksz_port_rxtstamp,
|
||||
.port_setup_tc = ksz_setup_tc,
|
||||
.port_setup_tc = ksz8_setup_tc,
|
||||
.port_get_default_prio = ksz_port_get_default_prio,
|
||||
.port_set_default_prio = ksz_port_set_default_prio,
|
||||
.port_get_dscp_prio = ksz_port_get_dscp_prio,
|
||||
@@ -2695,7 +2848,7 @@ const struct dsa_switch_ops ksz87xx_switch_ops = {
|
||||
.port_hwtstamp_set = ksz_hwtstamp_set,
|
||||
.port_txtstamp = ksz_port_txtstamp,
|
||||
.port_rxtstamp = ksz_port_rxtstamp,
|
||||
.port_setup_tc = ksz_setup_tc,
|
||||
.port_setup_tc = ksz87xx_setup_tc,
|
||||
.port_get_default_prio = ksz_port_get_default_prio,
|
||||
.port_set_default_prio = ksz_port_set_default_prio,
|
||||
.port_get_dscp_prio = ksz_port_get_dscp_prio,
|
||||
@@ -2748,7 +2901,7 @@ const struct dsa_switch_ops ksz88xx_switch_ops = {
|
||||
.port_hwtstamp_set = ksz_hwtstamp_set,
|
||||
.port_txtstamp = ksz_port_txtstamp,
|
||||
.port_rxtstamp = ksz_port_rxtstamp,
|
||||
.port_setup_tc = ksz_setup_tc,
|
||||
.port_setup_tc = ksz8_setup_tc,
|
||||
.port_get_default_prio = ksz_port_get_default_prio,
|
||||
.port_set_default_prio = ksz_port_set_default_prio,
|
||||
.port_get_dscp_prio = ksz_port_get_dscp_prio,
|
||||
|
||||
@@ -3097,8 +3097,8 @@ static int ksz_setup_tc_mode(struct ksz_device *dev, int port, u8 scheduler,
|
||||
FIELD_PREP(MTI_SHAPING_M, shaper));
|
||||
}
|
||||
|
||||
static int ksz_setup_tc_cbs(struct dsa_switch *ds, int port,
|
||||
struct tc_cbs_qopt_offload *qopt)
|
||||
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;
|
||||
@@ -3163,8 +3163,8 @@ static int ksz_disable_egress_rate_limit(struct ksz_device *dev, int port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p,
|
||||
int band)
|
||||
int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p,
|
||||
int band)
|
||||
{
|
||||
/* Compared to queues, bands prioritize packets differently. In strict
|
||||
* priority mode, the lowest priority is assigned to Queue 0 while the
|
||||
@@ -3173,104 +3173,6 @@ static int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p,
|
||||
return p->bands - 1 - band;
|
||||
}
|
||||
|
||||
static u8 ksz8463_tc_ctrl(int port, int queue)
|
||||
{
|
||||
u8 reg;
|
||||
|
||||
reg = 0xC8 + port * 4;
|
||||
reg += ((3 - queue) / 2) * 2;
|
||||
reg++;
|
||||
reg -= (queue & 1);
|
||||
return reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* ksz88x3_tc_ets_add - Configure ETS (Enhanced Transmission Selection)
|
||||
* for a port on KSZ88x3 switch
|
||||
* @dev: Pointer to the KSZ switch device structure
|
||||
* @port: Port number to configure
|
||||
* @p: Pointer to offload replace parameters describing ETS bands and mapping
|
||||
*
|
||||
* The KSZ88x3 supports two scheduling modes: Strict Priority and
|
||||
* Weighted Fair Queuing (WFQ). Both modes have fixed behavior:
|
||||
* - No configurable queue-to-priority mapping
|
||||
* - No weight adjustment in WFQ mode
|
||||
*
|
||||
* This function configures the switch to use strict priority mode by
|
||||
* clearing the WFQ enable bit for all queues associated with ETS bands.
|
||||
* If strict priority is not explicitly requested, the switch will default
|
||||
* to WFQ mode.
|
||||
*
|
||||
* Return: 0 on success, or a negative error code on failure
|
||||
*/
|
||||
static int ksz88x3_tc_ets_add(struct ksz_device *dev, int port,
|
||||
struct tc_ets_qopt_offload_replace_params *p)
|
||||
{
|
||||
int ret, band;
|
||||
|
||||
/* Only strict priority mode is supported for now.
|
||||
* WFQ is implicitly enabled when strict mode is disabled.
|
||||
*/
|
||||
for (band = 0; band < p->bands; band++) {
|
||||
int queue = ksz_ets_band_to_queue(p, band);
|
||||
u8 reg;
|
||||
|
||||
/* Calculate TXQ Split Control register address for this
|
||||
* port/queue
|
||||
*/
|
||||
reg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue);
|
||||
if (ksz_is_ksz8463(dev))
|
||||
reg = ksz8463_tc_ctrl(port, queue);
|
||||
|
||||
/* Clear WFQ enable bit to select strict priority scheduling */
|
||||
ret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ksz88x3_tc_ets_del - Reset ETS (Enhanced Transmission Selection) config
|
||||
* for a port on KSZ88x3 switch
|
||||
* @dev: Pointer to the KSZ switch device structure
|
||||
* @port: Port number to reset
|
||||
*
|
||||
* The KSZ88x3 supports only fixed scheduling modes: Strict Priority or
|
||||
* Weighted Fair Queuing (WFQ), with no reconfiguration of weights or
|
||||
* queue mapping. This function resets the port’s scheduling mode to
|
||||
* the default, which is WFQ, by enabling the WFQ bit for all queues.
|
||||
*
|
||||
* Return: 0 on success, or a negative error code on failure
|
||||
*/
|
||||
static int ksz88x3_tc_ets_del(struct ksz_device *dev, int port)
|
||||
{
|
||||
int ret, queue;
|
||||
|
||||
/* Iterate over all transmit queues for this port */
|
||||
for (queue = 0; queue < dev->info->num_tx_queues; queue++) {
|
||||
u8 reg;
|
||||
|
||||
/* Calculate TXQ Split Control register address for this
|
||||
* port/queue
|
||||
*/
|
||||
reg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue);
|
||||
if (ksz_is_ksz8463(dev))
|
||||
reg = ksz8463_tc_ctrl(port, queue);
|
||||
|
||||
/* Set WFQ enable bit to revert back to default scheduling
|
||||
* mode
|
||||
*/
|
||||
ret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE,
|
||||
KSZ8873_TXQ_WFQ_ENABLE);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ksz_queue_set_strict(struct ksz_device *dev, int port, int queue)
|
||||
{
|
||||
int ret;
|
||||
@@ -3363,8 +3265,8 @@ static int ksz_tc_ets_del(struct ksz_device *dev, int port)
|
||||
return ksz9477_set_default_prio_queue_mapping(dev, port);
|
||||
}
|
||||
|
||||
static int ksz_tc_ets_validate(struct ksz_device *dev, int port,
|
||||
struct tc_ets_qopt_offload_replace_params *p)
|
||||
int ksz_tc_ets_validate(struct ksz_device *dev, int port,
|
||||
struct tc_ets_qopt_offload_replace_params *p)
|
||||
{
|
||||
int band;
|
||||
|
||||
@@ -3405,9 +3307,6 @@ static int ksz_tc_setup_qdisc_ets(struct dsa_switch *ds, int port,
|
||||
struct ksz_device *dev = ds->priv;
|
||||
int ret;
|
||||
|
||||
if (is_ksz8(dev) && !(ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (qopt->parent != TC_H_ROOT) {
|
||||
dev_err(dev->dev, "Parent should be \"root\"\n");
|
||||
return -EOPNOTSUPP;
|
||||
@@ -3419,16 +3318,9 @@ static int ksz_tc_setup_qdisc_ets(struct dsa_switch *ds, int port,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev))
|
||||
return ksz88x3_tc_ets_add(dev, port,
|
||||
&qopt->replace_params);
|
||||
else
|
||||
return ksz_tc_ets_add(dev, port, &qopt->replace_params);
|
||||
return ksz_tc_ets_add(dev, port, &qopt->replace_params);
|
||||
case TC_ETS_DESTROY:
|
||||
if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev))
|
||||
return ksz88x3_tc_ets_del(dev, port);
|
||||
else
|
||||
return ksz_tc_ets_del(dev, port);
|
||||
return ksz_tc_ets_del(dev, port);
|
||||
case TC_ETS_STATS:
|
||||
case TC_ETS_GRAFT:
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/phy.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <net/dsa.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/platform_data/microchip-ksz.h>
|
||||
|
||||
@@ -481,6 +482,12 @@ void ksz_phylink_mac_link_down(struct phylink_config *config,
|
||||
int ksz_set_mac_eee(struct dsa_switch *ds, int port,
|
||||
struct ethtool_keee *e);
|
||||
|
||||
int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p,
|
||||
int band);
|
||||
int ksz_setup_tc_cbs(struct dsa_switch *ds, int port,
|
||||
struct tc_cbs_qopt_offload *qopt);
|
||||
int ksz_tc_ets_validate(struct ksz_device *dev, int port,
|
||||
struct tc_ets_qopt_offload_replace_params *p);
|
||||
int ksz_setup_tc(struct dsa_switch *ds, int port,
|
||||
enum tc_setup_type type, void *type_data);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user