4e19ed3bcf0283c25ae090142e12c09e88220119
[openwrt/staging/blogic.git] /
1 From 877119a3f6bce2d9091faa4e51490917be8a3158 Mon Sep 17 00:00:00 2001
2 From: Po Liu <po.liu@nxp.com>
3 Date: Fri, 15 Nov 2019 03:33:41 +0000
4 Subject: [PATCH] enetc: update TSN Qbv PSPEED set according to adjust link
5 speed
6
7 ENETC has a register PSPEED to indicate the link speed of hardware.
8 It is need to update accordingly. PSPEED field needs to be updated
9 with the port speed for QBV scheduling purposes. Or else there is
10 chance for gate slot not free by frame taking the MAC if PSPEED and
11 phy speed not match. So update PSPEED when link adjust. This is
12 implement by the adjust_link.
13
14 Signed-off-by: Po Liu <Po.Liu@nxp.com>
15 Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
16 Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
17 Signed-off-by: David S. Miller <davem@davemloft.net>
18 ---
19 drivers/net/ethernet/freescale/enetc/enetc.c | 13 +++++++--
20 drivers/net/ethernet/freescale/enetc/enetc.h | 8 ++++++
21 drivers/net/ethernet/freescale/enetc/enetc_hw.h | 5 ++++
22 drivers/net/ethernet/freescale/enetc/enetc_pf.c | 3 +++
23 drivers/net/ethernet/freescale/enetc/enetc_qos.c | 34 ++++++++++++++++++++++++
24 5 files changed, 61 insertions(+), 2 deletions(-)
25
26 --- a/drivers/net/ethernet/freescale/enetc/enetc.c
27 +++ b/drivers/net/ethernet/freescale/enetc/enetc.c
28 @@ -742,9 +742,14 @@ void enetc_get_si_caps(struct enetc_si *
29 si->num_rss = 0;
30 val = enetc_rd(hw, ENETC_SIPCAPR0);
31 if (val & ENETC_SIPCAPR0_RSS) {
32 - val = enetc_rd(hw, ENETC_SIRSSCAPR);
33 - si->num_rss = ENETC_SIRSSCAPR_GET_NUM_RSS(val);
34 + u32 rss;
35 +
36 + rss = enetc_rd(hw, ENETC_SIRSSCAPR);
37 + si->num_rss = ENETC_SIRSSCAPR_GET_NUM_RSS(rss);
38 }
39 +
40 + if (val & ENETC_SIPCAPR0_QBV)
41 + si->hw_features |= ENETC_SI_F_QBV;
42 }
43
44 static int enetc_dma_alloc_bdr(struct enetc_bdr *r, size_t bd_size)
45 @@ -1314,8 +1319,12 @@ static void enetc_disable_interrupts(str
46
47 static void adjust_link(struct net_device *ndev)
48 {
49 + struct enetc_ndev_priv *priv = netdev_priv(ndev);
50 struct phy_device *phydev = ndev->phydev;
51
52 + if (priv->active_offloads & ENETC_F_QBV)
53 + enetc_sched_speed_set(ndev);
54 +
55 phy_print_status(phydev);
56 }
57
58 --- a/drivers/net/ethernet/freescale/enetc/enetc.h
59 +++ b/drivers/net/ethernet/freescale/enetc/enetc.h
60 @@ -118,6 +118,8 @@ enum enetc_errata {
61 ENETC_ERR_UCMCSWP = BIT(2),
62 };
63
64 +#define ENETC_SI_F_QBV BIT(0)
65 +
66 /* PCI IEP device data */
67 struct enetc_si {
68 struct pci_dev *pdev;
69 @@ -133,6 +135,7 @@ struct enetc_si {
70 int num_fs_entries;
71 int num_rss; /* number of RSS buckets */
72 unsigned short pad;
73 + int hw_features;
74 };
75
76 #define ENETC_SI_ALIGN 32
77 @@ -173,6 +176,7 @@ struct enetc_cls_rule {
78 enum enetc_active_offloads {
79 ENETC_F_RX_TSTAMP = BIT(0),
80 ENETC_F_TX_TSTAMP = BIT(1),
81 + ENETC_F_QBV = BIT(2),
82 };
83
84 struct enetc_ndev_priv {
85 @@ -188,6 +192,8 @@ struct enetc_ndev_priv {
86 u16 msg_enable;
87 int active_offloads;
88
89 + u32 speed; /* store speed for compare update pspeed */
90 +
91 struct enetc_bdr *tx_ring[16];
92 struct enetc_bdr *rx_ring[16];
93
94 @@ -248,6 +254,8 @@ int enetc_send_cmd(struct enetc_si *si,
95
96 #ifdef CONFIG_FSL_ENETC_QOS
97 int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data);
98 +void enetc_sched_speed_set(struct net_device *ndev);
99 #else
100 #define enetc_setup_tc_taprio(ndev, type_data) -EOPNOTSUPP
101 +#define enetc_sched_speed_set(ndev) (void)0
102 #endif
103 --- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h
104 +++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
105 @@ -149,6 +149,11 @@ enum enetc_bdr_type {TX, RX};
106 #define ENETC_PORT_BASE 0x10000
107 #define ENETC_PMR 0x0000
108 #define ENETC_PMR_EN GENMASK(18, 16)
109 +#define ENETC_PMR_PSPEED_MASK GENMASK(11, 8)
110 +#define ENETC_PMR_PSPEED_10M 0
111 +#define ENETC_PMR_PSPEED_100M BIT(8)
112 +#define ENETC_PMR_PSPEED_1000M BIT(9)
113 +#define ENETC_PMR_PSPEED_2500M BIT(10)
114 #define ENETC_PSR 0x0004 /* RO */
115 #define ENETC_PSIPMR 0x0018
116 #define ENETC_PSIPMR_SET_UP(n) BIT(n) /* n = SI index */
117 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
118 +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
119 @@ -742,6 +742,9 @@ static void enetc_pf_netdev_setup(struct
120
121 ndev->priv_flags |= IFF_UNICAST_FLT;
122
123 + if (si->hw_features & ENETC_SI_F_QBV)
124 + priv->active_offloads |= ENETC_F_QBV;
125 +
126 /* pick up primary MAC address from SI */
127 enetc_get_primary_mac_addr(&si->hw, ndev->dev_addr);
128 }
129 --- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c
130 +++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
131 @@ -11,6 +11,40 @@ static u16 enetc_get_max_gcl_len(struct
132 & ENETC_QBV_MAX_GCL_LEN_MASK;
133 }
134
135 +void enetc_sched_speed_set(struct net_device *ndev)
136 +{
137 + struct enetc_ndev_priv *priv = netdev_priv(ndev);
138 + struct phy_device *phydev = ndev->phydev;
139 + u32 old_speed = priv->speed;
140 + u32 speed, pspeed;
141 +
142 + if (phydev->speed == old_speed)
143 + return;
144 +
145 + speed = phydev->speed;
146 + switch (speed) {
147 + case SPEED_1000:
148 + pspeed = ENETC_PMR_PSPEED_1000M;
149 + break;
150 + case SPEED_2500:
151 + pspeed = ENETC_PMR_PSPEED_2500M;
152 + break;
153 + case SPEED_100:
154 + pspeed = ENETC_PMR_PSPEED_100M;
155 + break;
156 + case SPEED_10:
157 + default:
158 + pspeed = ENETC_PMR_PSPEED_10M;
159 + netdev_err(ndev, "Qbv PSPEED set speed link down.\n");
160 + }
161 +
162 + priv->speed = speed;
163 + enetc_port_wr(&priv->si->hw, ENETC_PMR,
164 + (enetc_port_rd(&priv->si->hw, ENETC_PMR)
165 + & (~ENETC_PMR_PSPEED_MASK))
166 + | pspeed);
167 +}
168 +
169 static int enetc_setup_taprio(struct net_device *ndev,
170 struct tc_taprio_qopt_offload *admin_conf)
171 {