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

Merge branch 'stmmac-taprio'

Jose Abreu says:

====================
net: stmmac: TSN support using TAPRIO API

This series adds TSN support (EST and Frame Preemption) for stmmac driver.

1) Adds the HW specific support for EST in GMAC5+ cores.

2) Adds the HW specific support for EST in XGMAC3+ cores.

3) Integrates EST HW specific support with TAPRIO scheduler API.

4) Adds the Frame Preemption suppor on stmmac TAPRIO implementation.

5) Adds the HW specific support for Frame Preemption in GMAC5+ cores.

6) Adds the HW specific support for Frame Preemption in XGMAC3+ cores.

7) Adds support for HW debug counters for Frame Preemption available in
GMAC5+ cores.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6dbb2e91 ea77b8c8
......@@ -363,6 +363,11 @@ struct dma_features {
unsigned int dvlan;
unsigned int l3l4fnum;
unsigned int arpoffsel;
/* TSN Features */
unsigned int estwid;
unsigned int estdep;
unsigned int estsel;
unsigned int fpesel;
};
/* GMAC TX FIFO is 8K, Rx FIFO is 16K */
......
......@@ -64,6 +64,8 @@
#define GMAC_RXQCTRL_MCBCQEN_SHIFT 20
#define GMAC_RXQCTRL_TACPQE BIT(21)
#define GMAC_RXQCTRL_TACPQE_SHIFT 21
#define GMAC_RXQCTRL_FPRQ GENMASK(26, 24)
#define GMAC_RXQCTRL_FPRQ_SHIFT 24
/* MAC Packet Filtering */
#define GMAC_PACKET_FILTER_PR BIT(0)
......@@ -176,6 +178,8 @@ enum power_event {
#define GMAC_CONFIG_SARC GENMASK(30, 28)
#define GMAC_CONFIG_SARC_SHIFT 28
#define GMAC_CONFIG_IPC BIT(27)
#define GMAC_CONFIG_IPG GENMASK(26, 24)
#define GMAC_CONFIG_IPG_SHIFT 24
#define GMAC_CONFIG_2K BIT(22)
#define GMAC_CONFIG_ACS BIT(20)
#define GMAC_CONFIG_BE BIT(18)
......@@ -183,6 +187,7 @@ enum power_event {
#define GMAC_CONFIG_JE BIT(16)
#define GMAC_CONFIG_PS BIT(15)
#define GMAC_CONFIG_FES BIT(14)
#define GMAC_CONFIG_FES_SHIFT 14
#define GMAC_CONFIG_DM BIT(13)
#define GMAC_CONFIG_LM BIT(12)
#define GMAC_CONFIG_DCRS BIT(9)
......@@ -190,6 +195,9 @@ enum power_event {
#define GMAC_CONFIG_RE BIT(0)
/* MAC extended config */
#define GMAC_CONFIG_EIPG GENMASK(29, 25)
#define GMAC_CONFIG_EIPG_SHIFT 25
#define GMAC_CONFIG_EIPG_EN BIT(24)
#define GMAC_CONFIG_HDSMS GENMASK(22, 20)
#define GMAC_CONFIG_HDSMS_SHIFT 20
#define GMAC_CONFIG_HDSMS_256 (0x2 << GMAC_CONFIG_HDSMS_SHIFT)
......@@ -231,6 +239,10 @@ enum power_event {
/* MAC HW features3 bitmap */
#define GMAC_HW_FEAT_ASP GENMASK(29, 28)
#define GMAC_HW_FEAT_FPESEL BIT(26)
#define GMAC_HW_FEAT_ESTWID GENMASK(21, 20)
#define GMAC_HW_FEAT_ESTDEP GENMASK(19, 17)
#define GMAC_HW_FEAT_ESTSEL BIT(16)
#define GMAC_HW_FEAT_FRPES GENMASK(14, 13)
#define GMAC_HW_FEAT_FRPBS GENMASK(12, 11)
#define GMAC_HW_FEAT_FRPSEL BIT(10)
......
......@@ -984,6 +984,8 @@ const struct stmmac_ops dwmac410_ops = {
.set_arp_offload = dwmac4_set_arp_offload,
.config_l3_filter = dwmac4_config_l3_filter,
.config_l4_filter = dwmac4_config_l4_filter,
.est_configure = dwmac5_est_configure,
.fpe_configure = dwmac5_fpe_configure,
};
const struct stmmac_ops dwmac510_ops = {
......@@ -1027,6 +1029,8 @@ const struct stmmac_ops dwmac510_ops = {
.set_arp_offload = dwmac4_set_arp_offload,
.config_l3_filter = dwmac4_config_l3_filter,
.config_l4_filter = dwmac4_config_l4_filter,
.est_configure = dwmac5_est_configure,
.fpe_configure = dwmac5_fpe_configure,
};
int dwmac4_setup(struct stmmac_priv *priv)
......
......@@ -404,6 +404,10 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr,
/* 5.10 Features */
dma_cap->asp = (hw_cap & GMAC_HW_FEAT_ASP) >> 28;
dma_cap->fpesel = (hw_cap & GMAC_HW_FEAT_FPESEL) >> 26;
dma_cap->estwid = (hw_cap & GMAC_HW_FEAT_ESTWID) >> 20;
dma_cap->estdep = (hw_cap & GMAC_HW_FEAT_ESTDEP) >> 17;
dma_cap->estsel = (hw_cap & GMAC_HW_FEAT_ESTSEL) >> 16;
dma_cap->frpes = (hw_cap & GMAC_HW_FEAT_FRPES) >> 13;
dma_cap->frpbs = (hw_cap & GMAC_HW_FEAT_FRPBS) >> 11;
dma_cap->frpsel = (hw_cap & GMAC_HW_FEAT_FRPSEL) >> 10;
......
......@@ -550,3 +550,121 @@ int dwmac5_flex_pps_config(void __iomem *ioaddr, int index,
writel(val, ioaddr + MAC_PPS_CONTROL);
return 0;
}
static int dwmac5_est_write(void __iomem *ioaddr, u32 reg, u32 val, bool gcl)
{
u32 ctrl;
writel(val, ioaddr + MTL_EST_GCL_DATA);
ctrl = (reg << ADDR_SHIFT);
ctrl |= gcl ? 0 : GCRR;
writel(ctrl, ioaddr + MTL_EST_GCL_CONTROL);
ctrl |= SRWO;
writel(ctrl, ioaddr + MTL_EST_GCL_CONTROL);
return readl_poll_timeout(ioaddr + MTL_EST_GCL_CONTROL,
ctrl, !(ctrl & SRWO), 100, 5000);
}
int dwmac5_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg,
unsigned int ptp_rate)
{
u32 speed, total_offset, offset, ctrl, ctr_low;
u32 extcfg = readl(ioaddr + GMAC_EXT_CONFIG);
u32 mac_cfg = readl(ioaddr + GMAC_CONFIG);
int i, ret = 0x0;
u64 total_ctr;
if (extcfg & GMAC_CONFIG_EIPG_EN) {
offset = (extcfg & GMAC_CONFIG_EIPG) >> GMAC_CONFIG_EIPG_SHIFT;
offset = 104 + (offset * 8);
} else {
offset = (mac_cfg & GMAC_CONFIG_IPG) >> GMAC_CONFIG_IPG_SHIFT;
offset = 96 - (offset * 8);
}
speed = mac_cfg & (GMAC_CONFIG_PS | GMAC_CONFIG_FES);
speed = speed >> GMAC_CONFIG_FES_SHIFT;
switch (speed) {
case 0x0:
offset = offset * 1000; /* 1G */
break;
case 0x1:
offset = offset * 400; /* 2.5G */
break;
case 0x2:
offset = offset * 100000; /* 10M */
break;
case 0x3:
offset = offset * 10000; /* 100M */
break;
default:
return -EINVAL;
}
offset = offset / 1000;
ret |= dwmac5_est_write(ioaddr, BTR_LOW, cfg->btr[0], false);
ret |= dwmac5_est_write(ioaddr, BTR_HIGH, cfg->btr[1], false);
ret |= dwmac5_est_write(ioaddr, TER, cfg->ter, false);
ret |= dwmac5_est_write(ioaddr, LLR, cfg->gcl_size, false);
if (ret)
return ret;
total_offset = 0;
for (i = 0; i < cfg->gcl_size; i++) {
ret = dwmac5_est_write(ioaddr, i, cfg->gcl[i] + offset, true);
if (ret)
return ret;
total_offset += offset;
}
total_ctr = cfg->ctr[0] + cfg->ctr[1] * 1000000000;
total_ctr += total_offset;
ctr_low = do_div(total_ctr, 1000000000);
ret |= dwmac5_est_write(ioaddr, CTR_LOW, ctr_low, false);
ret |= dwmac5_est_write(ioaddr, CTR_HIGH, total_ctr, false);
if (ret)
return ret;
ctrl = readl(ioaddr + MTL_EST_CONTROL);
ctrl &= ~PTOV;
ctrl |= ((1000000000 / ptp_rate) * 6) << PTOV_SHIFT;
if (cfg->enable)
ctrl |= EEST | SSWL;
else
ctrl &= ~EEST;
writel(ctrl, ioaddr + MTL_EST_CONTROL);
return 0;
}
void dwmac5_fpe_configure(void __iomem *ioaddr, u32 num_txq, u32 num_rxq,
bool enable)
{
u32 value;
if (!enable) {
value = readl(ioaddr + MAC_FPE_CTRL_STS);
value &= ~EFPE;
writel(value, ioaddr + MAC_FPE_CTRL_STS);
}
value = readl(ioaddr + GMAC_RXQ_CTRL1);
value &= ~GMAC_RXQCTRL_FPRQ;
value |= (num_rxq - 1) << GMAC_RXQCTRL_FPRQ_SHIFT;
writel(value, ioaddr + GMAC_RXQ_CTRL1);
value = readl(ioaddr + MAC_FPE_CTRL_STS);
value |= EFPE;
writel(value, ioaddr + MAC_FPE_CTRL_STS);
}
......@@ -11,6 +11,9 @@
#define PRTYEN BIT(1)
#define TMOUTEN BIT(0)
#define MAC_FPE_CTRL_STS 0x00000234
#define EFPE BIT(0)
#define MAC_PPS_CONTROL 0x00000b70
#define PPS_MAXIDX(x) ((((x) + 1) * 8) - 1)
#define PPS_MINIDX(x) ((x) * 8)
......@@ -30,6 +33,23 @@
#define MAC_PPSx_INTERVAL(x) (0x00000b88 + ((x) * 0x10))
#define MAC_PPSx_WIDTH(x) (0x00000b8c + ((x) * 0x10))
#define MTL_EST_CONTROL 0x00000c50
#define PTOV GENMASK(31, 24)
#define PTOV_SHIFT 24
#define SSWL BIT(1)
#define EEST BIT(0)
#define MTL_EST_GCL_CONTROL 0x00000c80
#define BTR_LOW 0x0
#define BTR_HIGH 0x1
#define CTR_LOW 0x2
#define CTR_HIGH 0x3
#define TER 0x4
#define LLR 0x5
#define ADDR_SHIFT 8
#define GCRR BIT(2)
#define SRWO BIT(0)
#define MTL_EST_GCL_DATA 0x00000c84
#define MTL_RXP_CONTROL_STATUS 0x00000ca0
#define RXPI BIT(31)
#define NPE GENMASK(23, 16)
......@@ -83,5 +103,9 @@ int dwmac5_rxp_config(void __iomem *ioaddr, struct stmmac_tc_entry *entries,
int dwmac5_flex_pps_config(void __iomem *ioaddr, int index,
struct stmmac_pps_cfg *cfg, bool enable,
u32 sub_second_inc, u32 systime_flags);
int dwmac5_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg,
unsigned int ptp_rate);
void dwmac5_fpe_configure(void __iomem *ioaddr, u32 num_txq, u32 num_rxq,
bool enable);
#endif /* __DWMAC5_H__ */
......@@ -73,6 +73,9 @@
#define XGMAC_RXQ_CTRL0 0x000000a0
#define XGMAC_RXQEN(x) GENMASK((x) * 2 + 1, (x) * 2)
#define XGMAC_RXQEN_SHIFT(x) ((x) * 2)
#define XGMAC_RXQ_CTRL1 0x000000a4
#define XGMAC_RQ GENMASK(7, 4)
#define XGMAC_RQ_SHIFT 4
#define XGMAC_RXQ_CTRL2 0x000000a8
#define XGMAC_RXQ_CTRL3 0x000000ac
#define XGMAC_PSRQ(x) GENMASK((x) * 8 + 7, (x) * 8)
......@@ -136,6 +139,10 @@
#define XGMAC_HWFEAT_TXQCNT GENMASK(9, 6)
#define XGMAC_HWFEAT_RXQCNT GENMASK(3, 0)
#define XGMAC_HW_FEATURE3 0x00000128
#define XGMAC_HWFEAT_FPESEL BIT(26)
#define XGMAC_HWFEAT_ESTWID GENMASK(24, 23)
#define XGMAC_HWFEAT_ESTDEP GENMASK(22, 20)
#define XGMAC_HWFEAT_ESTSEL BIT(19)
#define XGMAC_HWFEAT_ASP GENMASK(15, 14)
#define XGMAC_HWFEAT_DVLAN BIT(13)
#define XGMAC_HWFEAT_FRPES GENMASK(12, 11)
......@@ -148,6 +155,8 @@
#define XGMAC_MDIO_ADDR 0x00000200
#define XGMAC_MDIO_DATA 0x00000204
#define XGMAC_MDIO_C22P 0x00000220
#define XGMAC_FPE_CTRL_STS 0x00000280
#define XGMAC_EFPE BIT(0)
#define XGMAC_ADDRx_HIGH(x) (0x00000300 + (x) * 0x8)
#define XGMAC_ADDR_MAX 32
#define XGMAC_AE BIT(31)
......@@ -237,6 +246,22 @@
#define XGMAC_TC_PRTY_MAP1 0x00001044
#define XGMAC_PSTC(x) GENMASK((x) * 8 + 7, (x) * 8)
#define XGMAC_PSTC_SHIFT(x) ((x) * 8)
#define XGMAC_MTL_EST_CONTROL 0x00001050
#define XGMAC_PTOV GENMASK(31, 23)
#define XGMAC_PTOV_SHIFT 23
#define XGMAC_SSWL BIT(1)
#define XGMAC_EEST BIT(0)
#define XGMAC_MTL_EST_GCL_CONTROL 0x00001080
#define XGMAC_BTR_LOW 0x0
#define XGMAC_BTR_HIGH 0x1
#define XGMAC_CTR_LOW 0x2
#define XGMAC_CTR_HIGH 0x3
#define XGMAC_TER 0x4
#define XGMAC_LLR 0x5
#define XGMAC_ADDR_SHIFT 8
#define XGMAC_GCRR BIT(2)
#define XGMAC_SRWO BIT(0)
#define XGMAC_MTL_EST_GCL_DATA 0x00001084
#define XGMAC_MTL_RXP_CONTROL_STATUS 0x000010a0
#define XGMAC_RXPI BIT(31)
#define XGMAC_NPE GENMASK(23, 16)
......
......@@ -1359,6 +1359,80 @@ static void dwxgmac2_set_arp_offload(struct mac_device_info *hw, bool en,
writel(value, ioaddr + XGMAC_RX_CONFIG);
}
static int dwxgmac3_est_write(void __iomem *ioaddr, u32 reg, u32 val, bool gcl)
{
u32 ctrl;
writel(val, ioaddr + XGMAC_MTL_EST_GCL_DATA);
ctrl = (reg << XGMAC_ADDR_SHIFT);
ctrl |= gcl ? 0 : XGMAC_GCRR;
writel(ctrl, ioaddr + XGMAC_MTL_EST_GCL_CONTROL);
ctrl |= XGMAC_SRWO;
writel(ctrl, ioaddr + XGMAC_MTL_EST_GCL_CONTROL);
return readl_poll_timeout_atomic(ioaddr + XGMAC_MTL_EST_GCL_CONTROL,
ctrl, !(ctrl & XGMAC_SRWO), 100, 5000);
}
static int dwxgmac3_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg,
unsigned int ptp_rate)
{
int i, ret = 0x0;
u32 ctrl;
ret |= dwxgmac3_est_write(ioaddr, XGMAC_BTR_LOW, cfg->btr[0], false);
ret |= dwxgmac3_est_write(ioaddr, XGMAC_BTR_HIGH, cfg->btr[1], false);
ret |= dwxgmac3_est_write(ioaddr, XGMAC_TER, cfg->ter, false);
ret |= dwxgmac3_est_write(ioaddr, XGMAC_LLR, cfg->gcl_size, false);
ret |= dwxgmac3_est_write(ioaddr, XGMAC_CTR_LOW, cfg->ctr[0], false);
ret |= dwxgmac3_est_write(ioaddr, XGMAC_CTR_HIGH, cfg->ctr[1], false);
if (ret)
return ret;
for (i = 0; i < cfg->gcl_size; i++) {
ret = dwxgmac3_est_write(ioaddr, i, cfg->gcl[i], true);
if (ret)
return ret;
}
ctrl = readl(ioaddr + XGMAC_MTL_EST_CONTROL);
ctrl &= ~XGMAC_PTOV;
ctrl |= ((1000000000 / ptp_rate) * 9) << XGMAC_PTOV_SHIFT;
if (cfg->enable)
ctrl |= XGMAC_EEST | XGMAC_SSWL;
else
ctrl &= ~XGMAC_EEST;
writel(ctrl, ioaddr + XGMAC_MTL_EST_CONTROL);
return 0;
}
static void dwxgmac3_fpe_configure(void __iomem *ioaddr, u32 num_txq,
u32 num_rxq, bool enable)
{
u32 value;
if (!enable) {
value = readl(ioaddr + XGMAC_FPE_CTRL_STS);
value &= ~XGMAC_EFPE;
writel(value, ioaddr + XGMAC_FPE_CTRL_STS);
}
value = readl(ioaddr + XGMAC_RXQ_CTRL1);
value &= ~XGMAC_RQ;
value |= (num_rxq - 1) << XGMAC_RQ_SHIFT;
writel(value, ioaddr + XGMAC_RXQ_CTRL1);
value = readl(ioaddr + XGMAC_FPE_CTRL_STS);
value |= XGMAC_EFPE;
writel(value, ioaddr + XGMAC_FPE_CTRL_STS);
}
const struct stmmac_ops dwxgmac210_ops = {
.core_init = dwxgmac2_core_init,
.set_mac = dwxgmac2_set_mac,
......@@ -1402,6 +1476,8 @@ const struct stmmac_ops dwxgmac210_ops = {
.config_l3_filter = dwxgmac2_config_l3_filter,
.config_l4_filter = dwxgmac2_config_l4_filter,
.set_arp_offload = dwxgmac2_set_arp_offload,
.est_configure = dwxgmac3_est_configure,
.fpe_configure = dwxgmac3_fpe_configure,
};
int dwxgmac2_setup(struct stmmac_priv *priv)
......
......@@ -429,6 +429,10 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,
/* MAC HW feature 3 */
hw_cap = readl(ioaddr + XGMAC_HW_FEATURE3);
dma_cap->fpesel = (hw_cap & XGMAC_HWFEAT_FPESEL) >> 26;
dma_cap->estwid = (hw_cap & XGMAC_HWFEAT_ESTWID) >> 23;
dma_cap->estdep = (hw_cap & XGMAC_HWFEAT_ESTDEP) >> 20;
dma_cap->estsel = (hw_cap & XGMAC_HWFEAT_ESTSEL) >> 19;
dma_cap->asp = (hw_cap & XGMAC_HWFEAT_ASP) >> 14;
dma_cap->dvlan = (hw_cap & XGMAC_HWFEAT_DVLAN) >> 13;
dma_cap->frpes = (hw_cap & XGMAC_HWFEAT_FRPES) >> 11;
......
......@@ -276,6 +276,7 @@ struct stmmac_safety_stats;
struct stmmac_tc_entry;
struct stmmac_pps_cfg;
struct stmmac_rss;
struct stmmac_est;
/* Helpers to program the MAC core */
struct stmmac_ops {
......@@ -373,6 +374,10 @@ struct stmmac_ops {
bool en, bool udp, bool sa, bool inv,
u32 match);
void (*set_arp_offload)(struct mac_device_info *hw, bool en, u32 addr);
int (*est_configure)(void __iomem *ioaddr, struct stmmac_est *cfg,
unsigned int ptp_rate);
void (*fpe_configure)(void __iomem *ioaddr, u32 num_txq, u32 num_rxq,
bool enable);
};
#define stmmac_core_init(__priv, __args...) \
......@@ -459,6 +464,10 @@ struct stmmac_ops {
stmmac_do_callback(__priv, mac, config_l4_filter, __args)
#define stmmac_set_arp_offload(__priv, __args...) \
stmmac_do_void_callback(__priv, mac, set_arp_offload, __args)
#define stmmac_est_configure(__priv, __args...) \
stmmac_do_callback(__priv, mac, est_configure, __args)
#define stmmac_fpe_configure(__priv, __args...) \
stmmac_do_void_callback(__priv, mac, fpe_configure, __args)
/* PTP and HW Timer helpers */
struct stmmac_hwtimestamp {
......@@ -516,6 +525,7 @@ struct stmmac_priv;
struct tc_cls_u32_offload;
struct tc_cbs_qopt_offload;
struct flow_cls_offload;
struct tc_taprio_qopt_offload;
struct stmmac_tc_ops {
int (*init)(struct stmmac_priv *priv);
......@@ -525,6 +535,8 @@ struct stmmac_tc_ops {
struct tc_cbs_qopt_offload *qopt);
int (*setup_cls)(struct stmmac_priv *priv,
struct flow_cls_offload *cls);
int (*setup_taprio)(struct stmmac_priv *priv,
struct tc_taprio_qopt_offload *qopt);
};
#define stmmac_tc_init(__priv, __args...) \
......@@ -535,6 +547,8 @@ struct stmmac_tc_ops {
stmmac_do_callback(__priv, tc, setup_cbs, __args)
#define stmmac_tc_setup_cls(__priv, __args...) \
stmmac_do_callback(__priv, tc, setup_cls, __args)
#define stmmac_tc_setup_taprio(__priv, __args...) \
stmmac_do_callback(__priv, tc, setup_taprio, __args)
struct stmmac_counters;
......
......@@ -119,6 +119,13 @@
#define MMC_RX_ICMP_GD_OCTETS 0x180
#define MMC_RX_ICMP_ERR_OCTETS 0x184
#define MMC_TX_FPE_FRAG 0x1a8
#define MMC_TX_HOLD_REQ 0x1ac
#define MMC_RX_PKT_ASSEMBLY_ERR 0x1c8
#define MMC_RX_PKT_SMD_ERR 0x1cc
#define MMC_RX_PKT_ASSEMBLY_OK 0x1d0
#define MMC_RX_FPE_FRAG 0x1d4
/* XGMAC MMC Registers */
#define MMC_XGMAC_TX_OCTET_GB 0x14
#define MMC_XGMAC_TX_PKT_GB 0x1c
......@@ -315,6 +322,15 @@ static void dwmac_mmc_read(void __iomem *mmcaddr, struct stmmac_counters *mmc)
mmc->mmc_rx_tcp_err_octets += readl(mmcaddr + MMC_RX_TCP_ERR_OCTETS);
mmc->mmc_rx_icmp_gd_octets += readl(mmcaddr + MMC_RX_ICMP_GD_OCTETS);
mmc->mmc_rx_icmp_err_octets += readl(mmcaddr + MMC_RX_ICMP_ERR_OCTETS);
mmc->mmc_tx_fpe_fragment_cntr += readl(mmcaddr + MMC_TX_FPE_FRAG);
mmc->mmc_tx_hold_req_cntr += readl(mmcaddr + MMC_TX_HOLD_REQ);
mmc->mmc_rx_packet_assembly_err_cntr +=
readl(mmcaddr + MMC_RX_PKT_ASSEMBLY_ERR);
mmc->mmc_rx_packet_smd_err_cntr += readl(mmcaddr + MMC_RX_PKT_SMD_ERR);
mmc->mmc_rx_packet_assembly_ok_cntr +=
readl(mmcaddr + MMC_RX_PKT_ASSEMBLY_OK);
mmc->mmc_rx_fpe_fragment_cntr += readl(mmcaddr + MMC_RX_FPE_FRAG);
}
const struct stmmac_mmc_ops dwmac_mmc_ops = {
......
......@@ -4076,6 +4076,8 @@ static int stmmac_setup_tc(struct net_device *ndev, enum tc_setup_type type,
priv, priv, true);
case TC_SETUP_QDISC_CBS:
return stmmac_tc_setup_cbs(priv, priv, type_data);
case TC_SETUP_QDISC_TAPRIO:
return stmmac_tc_setup_taprio(priv, priv, type_data);
default:
return -EOPNOTSUPP;
}
......
......@@ -591,9 +591,144 @@ static int tc_setup_cls(struct stmmac_priv *priv,
return ret;
}
static int tc_setup_taprio(struct stmmac_priv *priv,
struct tc_taprio_qopt_offload *qopt)
{
u32 size, wid = priv->dma_cap.estwid, dep = priv->dma_cap.estdep;
struct plat_stmmacenet_data *plat = priv->plat;
struct timespec64 time;
bool fpe = false;
int i, ret = 0;
if (!priv->dma_cap.estsel)
return -EOPNOTSUPP;
switch (wid) {
case 0x1:
wid = 16;
break;
case 0x2:
wid = 20;
break;
case 0x3:
wid = 24;
break;
default:
return -EOPNOTSUPP;
}
switch (dep) {
case 0x1:
dep = 64;
break;
case 0x2:
dep = 128;
break;
case 0x3:
dep = 256;
break;
case 0x4:
dep = 512;
break;
case 0x5:
dep = 1024;
break;
default:
return -EOPNOTSUPP;
}
if (!qopt->enable)
goto disable;
if (qopt->num_entries >= dep)
return -EINVAL;
if (!qopt->base_time)
return -ERANGE;
if (!qopt->cycle_time)
return -ERANGE;
if (!plat->est) {
plat->est = devm_kzalloc(priv->device, sizeof(*plat->est),
GFP_KERNEL);
if (!plat->est)
return -ENOMEM;
} else {
memset(plat->est, 0, sizeof(*plat->est));
}
size = qopt->num_entries;
priv->plat->est->gcl_size = size;
priv->plat->est->enable = qopt->enable;
for (i = 0; i < size; i++) {
s64 delta_ns = qopt->entries[i].interval;
u32 gates = qopt->entries[i].gate_mask;
if (delta_ns > GENMASK(wid, 0))
return -ERANGE;
if (gates > GENMASK(31 - wid, 0))
return -ERANGE;
switch (qopt->entries[i].command) {
case TC_TAPRIO_CMD_SET_GATES:
if (fpe)
return -EINVAL;
break;
case TC_TAPRIO_CMD_SET_AND_HOLD:
gates |= BIT(0);
fpe = true;
break;
case TC_TAPRIO_CMD_SET_AND_RELEASE:
gates &= ~BIT(0);
fpe = true;
break;
default:
return -EOPNOTSUPP;
}
priv->plat->est->gcl[i] = delta_ns | (gates << wid);
}
/* Adjust for real system time */
time = ktime_to_timespec64(qopt->base_time);
priv->plat->est->btr[0] = (u32)time.tv_nsec;
priv->plat->est->btr[1] = (u32)time.tv_sec;
priv->plat->est->ctr[0] = (u32)(qopt->cycle_time % NSEC_PER_SEC);
priv->plat->est->ctr[1] = (u32)(qopt->cycle_time / NSEC_PER_SEC);
if (fpe && !priv->dma_cap.fpesel)
return -EOPNOTSUPP;
ret = stmmac_fpe_configure(priv, priv->ioaddr,
priv->plat->tx_queues_to_use,
priv->plat->rx_queues_to_use, fpe);
if (ret && fpe) {
netdev_err(priv->dev, "failed to enable Frame Preemption\n");
return ret;
}
ret = stmmac_est_configure(priv, priv->ioaddr, priv->plat->est,
priv->plat->clk_ptp_rate);
if (ret) {
netdev_err(priv->dev, "failed to configure EST\n");
goto disable;
}
netdev_info(priv->dev, "configured EST\n");
return 0;
disable:
priv->plat->est->enable = false;
stmmac_est_configure(priv, priv->ioaddr, priv->plat->est,
priv->plat->clk_ptp_rate);
return ret;
}
const struct stmmac_tc_ops dwmac510_tc_ops = {
.init = tc_init,
.setup_cls_u32 = tc_setup_cls_u32,
.setup_cbs = tc_setup_cbs,
.setup_cls = tc_setup_cls,
.setup_taprio = tc_setup_taprio,
};
......@@ -109,6 +109,18 @@ struct stmmac_axi {
bool axi_rb;
};
#define EST_GCL 1024
struct stmmac_est {
int enable;
u32 btr_offset[2];
u32 btr[2];
u32 ctr[2];
u32 ter;
u32 gcl_unaligned[EST_GCL];
u32 gcl[EST_GCL];
u32 gcl_size;
};
struct stmmac_rxq_cfg {
u8 mode_to_use;
u32 chan;
......@@ -139,6 +151,7 @@ struct plat_stmmacenet_data {
struct device_node *phylink_node;
struct device_node *mdio_node;
struct stmmac_dma_cfg *dma_cfg;
struct stmmac_est *est;
int clk_csr;
int has_gmac;
int enh_desc;
......
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