Commit 3aba35bb authored by David S. Miller's avatar David S. Miller

Merge branch 'lan966x-mqprio-taprio'

Horatiu Vultur says:

====================
net: lan966x: Add mqprio and taprio support

Add support for offloading QoS features with tc command to lan966x. The
offloaded QoS features are mqprio and taprio.

v1->v2:
- fix compilation warning
- rename lan966x_taprio_enable/disable to lan966x_taprio_add/del
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f948ac23 e462b271
......@@ -8,4 +8,5 @@ obj-$(CONFIG_LAN966X_SWITCH) += lan966x-switch.o
lan966x-switch-objs := lan966x_main.o lan966x_phylink.o lan966x_port.o \
lan966x_mac.o lan966x_ethtool.o lan966x_switchdev.o \
lan966x_vlan.o lan966x_fdb.o lan966x_mdb.o \
lan966x_ptp.o lan966x_fdma.o lan966x_lag.o
lan966x_ptp.o lan966x_fdma.o lan966x_lag.o \
lan966x_tc.o lan966x_mqprio.o lan966x_taprio.o
......@@ -466,6 +466,7 @@ static const struct net_device_ops lan966x_port_netdev_ops = {
.ndo_set_mac_address = lan966x_port_set_mac_address,
.ndo_get_port_parent_id = lan966x_port_get_parent_id,
.ndo_eth_ioctl = lan966x_port_ioctl,
.ndo_setup_tc = lan966x_tc_setup,
};
bool lan966x_netdevice_check(const struct net_device *dev)
......@@ -738,7 +739,8 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
return -EINVAL;
dev = devm_alloc_etherdev_mqs(lan966x->dev,
sizeof(struct lan966x_port), 8, 1);
sizeof(struct lan966x_port),
NUM_PRIO_QUEUES, 1);
if (!dev)
return -ENOMEM;
......@@ -754,7 +756,9 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
dev->netdev_ops = &lan966x_port_netdev_ops;
dev->ethtool_ops = &lan966x_ethtool_ops;
dev->features |= NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_STAG_TX;
NETIF_F_HW_VLAN_STAG_TX |
NETIF_F_HW_TC;
dev->hw_features |= NETIF_F_HW_TC;
dev->needed_headroom = IFH_LEN * sizeof(u32);
eth_hw_addr_gen(dev, lan966x->base_mac, p + 1);
......@@ -959,6 +963,8 @@ static void lan966x_init(struct lan966x *lan966x)
lan966x, ANA_ANAINTR);
spin_lock_init(&lan966x->tx_lock);
lan966x_taprio_init(lan966x);
}
static int lan966x_ram_init(struct lan966x *lan966x)
......@@ -1168,6 +1174,7 @@ static int lan966x_remove(struct platform_device *pdev)
{
struct lan966x *lan966x = platform_get_drvdata(pdev);
lan966x_taprio_deinit(lan966x);
lan966x_fdma_deinit(lan966x);
lan966x_cleanup_ports(lan966x);
......
......@@ -9,6 +9,7 @@
#include <linux/phy.h>
#include <linux/phylink.h>
#include <linux/ptp_clock_kernel.h>
#include <net/pkt_sched.h>
#include <net/switchdev.h>
#include "lan966x_regs.h"
......@@ -36,6 +37,7 @@
#define NUM_PHYS_PORTS 8
#define CPU_PORT 8
#define NUM_PRIO_QUEUES 8
/* Reserved PGIDs */
#define PGID_CPU (PGID_AGGR - 6)
......@@ -409,6 +411,8 @@ void lan966x_ptp_txtstamp_release(struct lan966x_port *port,
struct sk_buff *skb);
irqreturn_t lan966x_ptp_irq_handler(int irq, void *args);
irqreturn_t lan966x_ptp_ext_irq_handler(int irq, void *args);
u32 lan966x_ptp_get_period_ps(void);
int lan966x_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts);
int lan966x_fdma_xmit(struct sk_buff *skb, __be32 *ifh, struct net_device *dev);
int lan966x_fdma_change_mtu(struct lan966x *lan966x);
......@@ -445,6 +449,19 @@ void lan966x_port_ageing_set(struct lan966x_port *port,
unsigned long ageing_clock_t);
void lan966x_update_fwd_mask(struct lan966x *lan966x);
int lan966x_tc_setup(struct net_device *dev, enum tc_setup_type type,
void *type_data);
int lan966x_mqprio_add(struct lan966x_port *port, u8 num_tc);
int lan966x_mqprio_del(struct lan966x_port *port);
void lan966x_taprio_init(struct lan966x *lan966x);
void lan966x_taprio_deinit(struct lan966x *lan966x);
int lan966x_taprio_add(struct lan966x_port *port,
struct tc_taprio_qopt_offload *qopt);
int lan966x_taprio_del(struct lan966x_port *port);
int lan966x_taprio_speed_set(struct lan966x_port *port, int speed);
static inline void __iomem *lan_addr(void __iomem *base[],
int id, int tinst, int tcnt,
int gbase, int ginst,
......
// SPDX-License-Identifier: GPL-2.0+
#include "lan966x_main.h"
int lan966x_mqprio_add(struct lan966x_port *port, u8 num_tc)
{
u8 i;
if (num_tc != NUM_PRIO_QUEUES) {
netdev_err(port->dev, "Only %d tarffic classes supported\n",
NUM_PRIO_QUEUES);
return -EINVAL;
}
netdev_set_num_tc(port->dev, num_tc);
for (i = 0; i < num_tc; ++i)
netdev_set_tc_queue(port->dev, i, 1, i);
return 0;
}
int lan966x_mqprio_del(struct lan966x_port *port)
{
netdev_reset_tc(port->dev);
return 0;
}
......@@ -165,6 +165,8 @@ static void lan966x_port_link_up(struct lan966x_port *port)
break;
}
lan966x_taprio_speed_set(port, config->speed);
/* Also the GIGA_MODE_ENA(1) needs to be set regardless of the
* port speed for QSGMII ports.
*/
......
......@@ -464,8 +464,7 @@ static int lan966x_ptp_settime64(struct ptp_clock_info *ptp,
return 0;
}
static int lan966x_ptp_gettime64(struct ptp_clock_info *ptp,
struct timespec64 *ts)
int lan966x_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
{
struct lan966x_phc *phc = container_of(ptp, struct lan966x_phc, info);
struct lan966x *lan966x = phc->lan966x;
......@@ -890,3 +889,9 @@ void lan966x_ptp_rxtstamp(struct lan966x *lan966x, struct sk_buff *skb,
shhwtstamps = skb_hwtstamps(skb);
shhwtstamps->hwtstamp = full_ts_in_ns;
}
u32 lan966x_ptp_get_period_ps(void)
{
/* This represents the system clock period in picoseconds */
return 15125;
}
......@@ -1018,6 +1018,165 @@ enum lan966x_target {
/* QSYS:RES_CTRL:RES_CFG */
#define QSYS_RES_CFG(g) __REG(TARGET_QSYS, 0, 1, 32768, g, 1024, 8, 0, 0, 1, 4)
/* QSYS:TAS_CONFIG:TAS_CFG_CTRL */
#define QSYS_TAS_CFG_CTRL __REG(TARGET_QSYS, 0, 1, 57372, 0, 1, 12, 0, 0, 1, 4)
#define QSYS_TAS_CFG_CTRL_LIST_NUM_MAX GENMASK(27, 23)
#define QSYS_TAS_CFG_CTRL_LIST_NUM_MAX_SET(x)\
FIELD_PREP(QSYS_TAS_CFG_CTRL_LIST_NUM_MAX, x)
#define QSYS_TAS_CFG_CTRL_LIST_NUM_MAX_GET(x)\
FIELD_GET(QSYS_TAS_CFG_CTRL_LIST_NUM_MAX, x)
#define QSYS_TAS_CFG_CTRL_LIST_NUM GENMASK(22, 18)
#define QSYS_TAS_CFG_CTRL_LIST_NUM_SET(x)\
FIELD_PREP(QSYS_TAS_CFG_CTRL_LIST_NUM, x)
#define QSYS_TAS_CFG_CTRL_LIST_NUM_GET(x)\
FIELD_GET(QSYS_TAS_CFG_CTRL_LIST_NUM, x)
#define QSYS_TAS_CFG_CTRL_ALWAYS_GB_SCH_Q BIT(17)
#define QSYS_TAS_CFG_CTRL_ALWAYS_GB_SCH_Q_SET(x)\
FIELD_PREP(QSYS_TAS_CFG_CTRL_ALWAYS_GB_SCH_Q, x)
#define QSYS_TAS_CFG_CTRL_ALWAYS_GB_SCH_Q_GET(x)\
FIELD_GET(QSYS_TAS_CFG_CTRL_ALWAYS_GB_SCH_Q, x)
#define QSYS_TAS_CFG_CTRL_GCL_ENTRY_NUM GENMASK(16, 5)
#define QSYS_TAS_CFG_CTRL_GCL_ENTRY_NUM_SET(x)\
FIELD_PREP(QSYS_TAS_CFG_CTRL_GCL_ENTRY_NUM, x)
#define QSYS_TAS_CFG_CTRL_GCL_ENTRY_NUM_GET(x)\
FIELD_GET(QSYS_TAS_CFG_CTRL_GCL_ENTRY_NUM, x)
/* QSYS:TAS_CONFIG:TAS_GATE_STATE_CTRL */
#define QSYS_TAS_GS_CTRL __REG(TARGET_QSYS, 0, 1, 57372, 0, 1, 12, 4, 0, 1, 4)
#define QSYS_TAS_GS_CTRL_HSCH_POS GENMASK(2, 0)
#define QSYS_TAS_GS_CTRL_HSCH_POS_SET(x)\
FIELD_PREP(QSYS_TAS_GS_CTRL_HSCH_POS, x)
#define QSYS_TAS_GS_CTRL_HSCH_POS_GET(x)\
FIELD_GET(QSYS_TAS_GS_CTRL_HSCH_POS, x)
/* QSYS:TAS_CONFIG:TAS_STATEMACHINE_CFG */
#define QSYS_TAS_STM_CFG __REG(TARGET_QSYS, 0, 1, 57372, 0, 1, 12, 8, 0, 1, 4)
#define QSYS_TAS_STM_CFG_REVISIT_DLY GENMASK(7, 0)
#define QSYS_TAS_STM_CFG_REVISIT_DLY_SET(x)\
FIELD_PREP(QSYS_TAS_STM_CFG_REVISIT_DLY, x)
#define QSYS_TAS_STM_CFG_REVISIT_DLY_GET(x)\
FIELD_GET(QSYS_TAS_STM_CFG_REVISIT_DLY, x)
/* QSYS:TAS_PROFILE_CFG:TAS_PROFILE_CONFIG */
#define QSYS_TAS_PROFILE_CFG(g) __REG(TARGET_QSYS, 0, 1, 30720, g, 16, 64, 32, 0, 1, 4)
#define QSYS_TAS_PROFILE_CFG_PORT_NUM GENMASK(21, 19)
#define QSYS_TAS_PROFILE_CFG_PORT_NUM_SET(x)\
FIELD_PREP(QSYS_TAS_PROFILE_CFG_PORT_NUM, x)
#define QSYS_TAS_PROFILE_CFG_PORT_NUM_GET(x)\
FIELD_GET(QSYS_TAS_PROFILE_CFG_PORT_NUM, x)
#define QSYS_TAS_PROFILE_CFG_LINK_SPEED GENMASK(18, 16)
#define QSYS_TAS_PROFILE_CFG_LINK_SPEED_SET(x)\
FIELD_PREP(QSYS_TAS_PROFILE_CFG_LINK_SPEED, x)
#define QSYS_TAS_PROFILE_CFG_LINK_SPEED_GET(x)\
FIELD_GET(QSYS_TAS_PROFILE_CFG_LINK_SPEED, x)
/* QSYS:TAS_LIST_CFG:TAS_BASE_TIME_NSEC */
#define QSYS_TAS_BT_NSEC __REG(TARGET_QSYS, 0, 1, 27904, 0, 1, 64, 0, 0, 1, 4)
#define QSYS_TAS_BT_NSEC_NSEC GENMASK(29, 0)
#define QSYS_TAS_BT_NSEC_NSEC_SET(x)\
FIELD_PREP(QSYS_TAS_BT_NSEC_NSEC, x)
#define QSYS_TAS_BT_NSEC_NSEC_GET(x)\
FIELD_GET(QSYS_TAS_BT_NSEC_NSEC, x)
/* QSYS:TAS_LIST_CFG:TAS_BASE_TIME_SEC_LSB */
#define QSYS_TAS_BT_SEC_LSB __REG(TARGET_QSYS, 0, 1, 27904, 0, 1, 64, 4, 0, 1, 4)
/* QSYS:TAS_LIST_CFG:TAS_BASE_TIME_SEC_MSB */
#define QSYS_TAS_BT_SEC_MSB __REG(TARGET_QSYS, 0, 1, 27904, 0, 1, 64, 8, 0, 1, 4)
#define QSYS_TAS_BT_SEC_MSB_SEC_MSB GENMASK(15, 0)
#define QSYS_TAS_BT_SEC_MSB_SEC_MSB_SET(x)\
FIELD_PREP(QSYS_TAS_BT_SEC_MSB_SEC_MSB, x)
#define QSYS_TAS_BT_SEC_MSB_SEC_MSB_GET(x)\
FIELD_GET(QSYS_TAS_BT_SEC_MSB_SEC_MSB, x)
/* QSYS:TAS_LIST_CFG:TAS_CYCLE_TIME_CFG */
#define QSYS_TAS_CT_CFG __REG(TARGET_QSYS, 0, 1, 27904, 0, 1, 64, 24, 0, 1, 4)
/* QSYS:TAS_LIST_CFG:TAS_STARTUP_CFG */
#define QSYS_TAS_STARTUP_CFG __REG(TARGET_QSYS, 0, 1, 27904, 0, 1, 64, 28, 0, 1, 4)
#define QSYS_TAS_STARTUP_CFG_OBSOLETE_IDX GENMASK(27, 23)
#define QSYS_TAS_STARTUP_CFG_OBSOLETE_IDX_SET(x)\
FIELD_PREP(QSYS_TAS_STARTUP_CFG_OBSOLETE_IDX, x)
#define QSYS_TAS_STARTUP_CFG_OBSOLETE_IDX_GET(x)\
FIELD_GET(QSYS_TAS_STARTUP_CFG_OBSOLETE_IDX, x)
/* QSYS:TAS_LIST_CFG:TAS_LIST_CFG */
#define QSYS_TAS_LIST_CFG __REG(TARGET_QSYS, 0, 1, 27904, 0, 1, 64, 32, 0, 1, 4)
#define QSYS_TAS_LIST_CFG_LIST_BASE_ADDR GENMASK(11, 0)
#define QSYS_TAS_LIST_CFG_LIST_BASE_ADDR_SET(x)\
FIELD_PREP(QSYS_TAS_LIST_CFG_LIST_BASE_ADDR, x)
#define QSYS_TAS_LIST_CFG_LIST_BASE_ADDR_GET(x)\
FIELD_GET(QSYS_TAS_LIST_CFG_LIST_BASE_ADDR, x)
/* QSYS:TAS_LIST_CFG:TAS_LIST_STATE */
#define QSYS_TAS_LST __REG(TARGET_QSYS, 0, 1, 27904, 0, 1, 64, 36, 0, 1, 4)
#define QSYS_TAS_LST_LIST_STATE GENMASK(2, 0)
#define QSYS_TAS_LST_LIST_STATE_SET(x)\
FIELD_PREP(QSYS_TAS_LST_LIST_STATE, x)
#define QSYS_TAS_LST_LIST_STATE_GET(x)\
FIELD_GET(QSYS_TAS_LST_LIST_STATE, x)
/* QSYS:TAS_GCL_CFG:TAS_GCL_CTRL_CFG */
#define QSYS_TAS_GCL_CT_CFG __REG(TARGET_QSYS, 0, 1, 27968, 0, 1, 16, 0, 0, 1, 4)
#define QSYS_TAS_GCL_CT_CFG_HSCH_POS GENMASK(12, 10)
#define QSYS_TAS_GCL_CT_CFG_HSCH_POS_SET(x)\
FIELD_PREP(QSYS_TAS_GCL_CT_CFG_HSCH_POS, x)
#define QSYS_TAS_GCL_CT_CFG_HSCH_POS_GET(x)\
FIELD_GET(QSYS_TAS_GCL_CT_CFG_HSCH_POS, x)
#define QSYS_TAS_GCL_CT_CFG_GATE_STATE GENMASK(9, 2)
#define QSYS_TAS_GCL_CT_CFG_GATE_STATE_SET(x)\
FIELD_PREP(QSYS_TAS_GCL_CT_CFG_GATE_STATE, x)
#define QSYS_TAS_GCL_CT_CFG_GATE_STATE_GET(x)\
FIELD_GET(QSYS_TAS_GCL_CT_CFG_GATE_STATE, x)
#define QSYS_TAS_GCL_CT_CFG_OP_TYPE GENMASK(1, 0)
#define QSYS_TAS_GCL_CT_CFG_OP_TYPE_SET(x)\
FIELD_PREP(QSYS_TAS_GCL_CT_CFG_OP_TYPE, x)
#define QSYS_TAS_GCL_CT_CFG_OP_TYPE_GET(x)\
FIELD_GET(QSYS_TAS_GCL_CT_CFG_OP_TYPE, x)
/* QSYS:TAS_GCL_CFG:TAS_GCL_CTRL_CFG2 */
#define QSYS_TAS_GCL_CT_CFG2 __REG(TARGET_QSYS, 0, 1, 27968, 0, 1, 16, 4, 0, 1, 4)
#define QSYS_TAS_GCL_CT_CFG2_PORT_PROFILE GENMASK(15, 12)
#define QSYS_TAS_GCL_CT_CFG2_PORT_PROFILE_SET(x)\
FIELD_PREP(QSYS_TAS_GCL_CT_CFG2_PORT_PROFILE, x)
#define QSYS_TAS_GCL_CT_CFG2_PORT_PROFILE_GET(x)\
FIELD_GET(QSYS_TAS_GCL_CT_CFG2_PORT_PROFILE, x)
#define QSYS_TAS_GCL_CT_CFG2_NEXT_GCL GENMASK(11, 0)
#define QSYS_TAS_GCL_CT_CFG2_NEXT_GCL_SET(x)\
FIELD_PREP(QSYS_TAS_GCL_CT_CFG2_NEXT_GCL, x)
#define QSYS_TAS_GCL_CT_CFG2_NEXT_GCL_GET(x)\
FIELD_GET(QSYS_TAS_GCL_CT_CFG2_NEXT_GCL, x)
/* QSYS:TAS_GCL_CFG:TAS_GCL_TIME_CFG */
#define QSYS_TAS_GCL_TM_CFG __REG(TARGET_QSYS, 0, 1, 27968, 0, 1, 16, 8, 0, 1, 4)
/* QSYS:HSCH_TAS_STATE:TAS_GATE_STATE */
#define QSYS_TAS_GATE_STATE __REG(TARGET_QSYS, 0, 1, 28004, 0, 1, 4, 0, 0, 1, 4)
#define QSYS_TAS_GATE_STATE_TAS_GATE_STATE GENMASK(7, 0)
#define QSYS_TAS_GATE_STATE_TAS_GATE_STATE_SET(x)\
FIELD_PREP(QSYS_TAS_GATE_STATE_TAS_GATE_STATE, x)
#define QSYS_TAS_GATE_STATE_TAS_GATE_STATE_GET(x)\
FIELD_GET(QSYS_TAS_GATE_STATE_TAS_GATE_STATE, x)
/* REW:PORT:PORT_VLAN_CFG */
#define REW_PORT_VLAN_CFG(g) __REG(TARGET_REW, 0, 1, 0, g, 10, 128, 0, 0, 1, 4)
......
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0+
#include <net/pkt_cls.h>
#include "lan966x_main.h"
static int lan966x_tc_setup_qdisc_mqprio(struct lan966x_port *port,
struct tc_mqprio_qopt_offload *mqprio)
{
u8 num_tc = mqprio->qopt.num_tc;
mqprio->qopt.hw = TC_MQPRIO_HW_OFFLOAD_TCS;
return num_tc ? lan966x_mqprio_add(port, num_tc) :
lan966x_mqprio_del(port);
}
static int lan966x_tc_setup_qdisc_taprio(struct lan966x_port *port,
struct tc_taprio_qopt_offload *taprio)
{
return taprio->enable ? lan966x_taprio_add(port, taprio) :
lan966x_taprio_del(port);
}
int lan966x_tc_setup(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
struct lan966x_port *port = netdev_priv(dev);
switch (type) {
case TC_SETUP_QDISC_MQPRIO:
return lan966x_tc_setup_qdisc_mqprio(port, type_data);
case TC_SETUP_QDISC_TAPRIO:
return lan966x_tc_setup_qdisc_taprio(port, type_data);
default:
return -EOPNOTSUPP;
}
return 0;
}
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