ath79/mikrotik: use routerbootpart partitions
[oweals/openwrt.git] / target / linux / layerscape / patches-5.4 / 701-net-0225-enetc-Configure-the-Time-Aware-Scheduler-via-tc-tapr.patch
1 From 6ee2331a3a5627b062daf76aa5ed9f64fbbfa303 Mon Sep 17 00:00:00 2001
2 From: Po Liu <po.liu@nxp.com>
3 Date: Fri, 15 Nov 2019 03:33:33 +0000
4 Subject: [PATCH] enetc: Configure the Time-Aware Scheduler via tc-taprio
5  offload
6
7 ENETC supports in hardware for time-based egress shaping according
8 to IEEE 802.1Qbv. This patch implement the Qbv enablement by the
9 hardware offload method qdisc tc-taprio method.
10 Also update cbdr writeback to up level since control bd ring may
11 writeback data to control bd ring.
12
13 Signed-off-by: Po Liu <Po.Liu@nxp.com>
14 Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
15 Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
16 Signed-off-by: David S. Miller <davem@davemloft.net>
17 ---
18  drivers/net/ethernet/freescale/enetc/Kconfig      |  10 ++
19  drivers/net/ethernet/freescale/enetc/Makefile     |   2 +
20  drivers/net/ethernet/freescale/enetc/enetc.c      |  19 ++-
21  drivers/net/ethernet/freescale/enetc/enetc.h      |   7 ++
22  drivers/net/ethernet/freescale/enetc/enetc_cbdr.c |   5 +-
23  drivers/net/ethernet/freescale/enetc/enetc_hw.h   |  84 ++++++++++---
24  drivers/net/ethernet/freescale/enetc/enetc_qos.c  | 138 ++++++++++++++++++++++
25  7 files changed, 243 insertions(+), 22 deletions(-)
26  create mode 100644 drivers/net/ethernet/freescale/enetc/enetc_qos.c
27
28 --- a/drivers/net/ethernet/freescale/enetc/Kconfig
29 +++ b/drivers/net/ethernet/freescale/enetc/Kconfig
30 @@ -50,3 +50,13 @@ config FSL_ENETC_HW_TIMESTAMPING
31           allocation has not been supported and it is too expensive to use
32           extended RX BDs if timestamping is not used, this option enables
33           extended RX BDs in order to support hardware timestamping.
34 +
35 +config FSL_ENETC_QOS
36 +       bool "ENETC hardware Time-sensitive Network support"
37 +       depends on (FSL_ENETC || FSL_ENETC_VF) && NET_SCH_TAPRIO
38 +       help
39 +         There are Time-Sensitive Network(TSN) capabilities(802.1Qbv/802.1Qci
40 +         /802.1Qbu etc.) supported by ENETC. These TSN capabilities can be set
41 +         enable/disable from user space via Qos commands(tc). In the kernel
42 +         side, it can be loaded by Qos driver. Currently, it is only support
43 +         taprio(802.1Qbv).
44 --- a/drivers/net/ethernet/freescale/enetc/Makefile
45 +++ b/drivers/net/ethernet/freescale/enetc/Makefile
46 @@ -5,9 +5,11 @@ common-objs := enetc.o enetc_cbdr.o enet
47  obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o
48  fsl-enetc-y := enetc_pf.o enetc_mdio.o $(common-objs)
49  fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o
50 +fsl-enetc-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o
51  
52  obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o
53  fsl-enetc-vf-y := enetc_vf.o $(common-objs)
54 +fsl-enetc-vf-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o
55  
56  obj-$(CONFIG_FSL_ENETC_MDIO) += fsl-enetc-mdio.o
57  fsl-enetc-mdio-y := enetc_pci_mdio.o enetc_mdio.o
58 --- a/drivers/net/ethernet/freescale/enetc/enetc.c
59 +++ b/drivers/net/ethernet/freescale/enetc/enetc.c
60 @@ -1427,8 +1427,7 @@ int enetc_close(struct net_device *ndev)
61         return 0;
62  }
63  
64 -int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type,
65 -                  void *type_data)
66 +int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)
67  {
68         struct enetc_ndev_priv *priv = netdev_priv(ndev);
69         struct tc_mqprio_qopt *mqprio = type_data;
70 @@ -1436,9 +1435,6 @@ int enetc_setup_tc(struct net_device *nd
71         u8 num_tc;
72         int i;
73  
74 -       if (type != TC_SETUP_QDISC_MQPRIO)
75 -               return -EOPNOTSUPP;
76 -
77         mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
78         num_tc = mqprio->num_tc;
79  
80 @@ -1483,6 +1479,19 @@ int enetc_setup_tc(struct net_device *nd
81         return 0;
82  }
83  
84 +int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type,
85 +                  void *type_data)
86 +{
87 +       switch (type) {
88 +       case TC_SETUP_QDISC_MQPRIO:
89 +               return enetc_setup_tc_mqprio(ndev, type_data);
90 +       case TC_SETUP_QDISC_TAPRIO:
91 +               return enetc_setup_tc_taprio(ndev, type_data);
92 +       default:
93 +               return -EOPNOTSUPP;
94 +       }
95 +}
96 +
97  struct net_device_stats *enetc_get_stats(struct net_device *ndev)
98  {
99         struct enetc_ndev_priv *priv = netdev_priv(ndev);
100 --- a/drivers/net/ethernet/freescale/enetc/enetc.h
101 +++ b/drivers/net/ethernet/freescale/enetc/enetc.h
102 @@ -244,3 +244,10 @@ int enetc_set_fs_entry(struct enetc_si *
103  void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes);
104  int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
105  int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
106 +int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
107 +
108 +#ifdef CONFIG_FSL_ENETC_QOS
109 +int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data);
110 +#else
111 +#define enetc_setup_tc_taprio(ndev, type_data) -EOPNOTSUPP
112 +#endif
113 --- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
114 +++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
115 @@ -32,7 +32,7 @@ static int enetc_cbd_unused(struct enetc
116                 r->bd_count;
117  }
118  
119 -static int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd)
120 +int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd)
121  {
122         struct enetc_cbdr *ring = &si->cbd_ring;
123         int timeout = ENETC_CBDR_TIMEOUT;
124 @@ -66,6 +66,9 @@ static int enetc_send_cmd(struct enetc_s
125         if (!timeout)
126                 return -EBUSY;
127  
128 +       /* CBD may writeback data, feedback up level */
129 +       *cbd = *dest_cbd;
130 +
131         enetc_clean_cbdr(si);
132  
133         return 0;
134 --- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h
135 +++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
136 @@ -18,6 +18,7 @@
137  #define ENETC_SICTR0   0x18
138  #define ENETC_SICTR1   0x1c
139  #define ENETC_SIPCAPR0 0x20
140 +#define ENETC_SIPCAPR0_QBV     BIT(4)
141  #define ENETC_SIPCAPR0_RSS     BIT(8)
142  #define ENETC_SIPCAPR1 0x24
143  #define ENETC_SITGTGR  0x30
144 @@ -440,22 +441,6 @@ union enetc_rx_bd {
145  #define EMETC_MAC_ADDR_FILT_RES        3 /* # of reserved entries at the beginning */
146  #define ENETC_MAX_NUM_VFS      2
147  
148 -struct enetc_cbd {
149 -       union {
150 -               struct {
151 -                       __le32 addr[2];
152 -                       __le32 opt[4];
153 -               };
154 -               __le32 data[6];
155 -       };
156 -       __le16 index;
157 -       __le16 length;
158 -       u8 cmd;
159 -       u8 cls;
160 -       u8 _res;
161 -       u8 status_flags;
162 -};
163 -
164  #define ENETC_CBD_FLAGS_SF     BIT(7) /* short format */
165  #define ENETC_CBD_STATUS_MASK  0xf
166  
167 @@ -554,3 +539,70 @@ static inline void enetc_set_bdr_prio(st
168         val |= ENETC_TBMR_SET_PRIO(prio);
169         enetc_txbdr_wr(hw, bdr_idx, ENETC_TBMR, val);
170  }
171 +
172 +enum bdcr_cmd_class {
173 +       BDCR_CMD_UNSPEC = 0,
174 +       BDCR_CMD_MAC_FILTER,
175 +       BDCR_CMD_VLAN_FILTER,
176 +       BDCR_CMD_RSS,
177 +       BDCR_CMD_RFS,
178 +       BDCR_CMD_PORT_GCL,
179 +       BDCR_CMD_RECV_CLASSIFIER,
180 +       __BDCR_CMD_MAX_LEN,
181 +       BDCR_CMD_MAX_LEN = __BDCR_CMD_MAX_LEN - 1,
182 +};
183 +
184 +/* class 5, command 0 */
185 +struct tgs_gcl_conf {
186 +       u8      atc;    /* init gate value */
187 +       u8      res[7];
188 +       struct {
189 +               u8      res1[4];
190 +               __le16  acl_len;
191 +               u8      res2[2];
192 +       };
193 +};
194 +
195 +/* gate control list entry */
196 +struct gce {
197 +       __le32  period;
198 +       u8      gate;
199 +       u8      res[3];
200 +};
201 +
202 +/* tgs_gcl_conf address point to this data space */
203 +struct tgs_gcl_data {
204 +       __le32          btl;
205 +       __le32          bth;
206 +       __le32          ct;
207 +       __le32          cte;
208 +       struct gce      entry[0];
209 +};
210 +
211 +struct enetc_cbd {
212 +       union{
213 +               struct {
214 +                       __le32  addr[2];
215 +                       union {
216 +                               __le32  opt[4];
217 +                               struct tgs_gcl_conf     gcl_conf;
218 +                       };
219 +               };      /* Long format */
220 +               __le32 data[6];
221 +       };
222 +       __le16 index;
223 +       __le16 length;
224 +       u8 cmd;
225 +       u8 cls;
226 +       u8 _res;
227 +       u8 status_flags;
228 +};
229 +
230 +/* port time gating control register */
231 +#define ENETC_QBV_PTGCR_OFFSET         0x11a00
232 +#define ENETC_QBV_TGE                  BIT(31)
233 +#define ENETC_QBV_TGPE                 BIT(30)
234 +
235 +/* Port time gating capability register */
236 +#define ENETC_QBV_PTGCAPR_OFFSET       0x11a08
237 +#define ENETC_QBV_MAX_GCL_LEN_MASK     GENMASK(15, 0)
238 --- /dev/null
239 +++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
240 @@ -0,0 +1,138 @@
241 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
242 +/* Copyright 2019 NXP */
243 +
244 +#include "enetc.h"
245 +
246 +#include <net/pkt_sched.h>
247 +
248 +static u16 enetc_get_max_gcl_len(struct enetc_hw *hw)
249 +{
250 +       return enetc_rd(hw, ENETC_QBV_PTGCAPR_OFFSET)
251 +               & ENETC_QBV_MAX_GCL_LEN_MASK;
252 +}
253 +
254 +static int enetc_setup_taprio(struct net_device *ndev,
255 +                             struct tc_taprio_qopt_offload *admin_conf)
256 +{
257 +       struct enetc_ndev_priv *priv = netdev_priv(ndev);
258 +       struct enetc_cbd cbd = {.cmd = 0};
259 +       struct tgs_gcl_conf *gcl_config;
260 +       struct tgs_gcl_data *gcl_data;
261 +       struct gce *gce;
262 +       dma_addr_t dma;
263 +       u16 data_size;
264 +       u16 gcl_len;
265 +       u32 tge;
266 +       int err;
267 +       int i;
268 +
269 +       if (admin_conf->num_entries > enetc_get_max_gcl_len(&priv->si->hw))
270 +               return -EINVAL;
271 +       gcl_len = admin_conf->num_entries;
272 +
273 +       tge = enetc_rd(&priv->si->hw, ENETC_QBV_PTGCR_OFFSET);
274 +       if (!admin_conf->enable) {
275 +               enetc_wr(&priv->si->hw,
276 +                        ENETC_QBV_PTGCR_OFFSET,
277 +                        tge & (~ENETC_QBV_TGE));
278 +               return 0;
279 +       }
280 +
281 +       if (admin_conf->cycle_time > U32_MAX ||
282 +           admin_conf->cycle_time_extension > U32_MAX)
283 +               return -EINVAL;
284 +
285 +       /* Configure the (administrative) gate control list using the
286 +        * control BD descriptor.
287 +        */
288 +       gcl_config = &cbd.gcl_conf;
289 +
290 +       data_size = struct_size(gcl_data, entry, gcl_len);
291 +       gcl_data = kzalloc(data_size, __GFP_DMA | GFP_KERNEL);
292 +       if (!gcl_data)
293 +               return -ENOMEM;
294 +
295 +       gce = (struct gce *)(gcl_data + 1);
296 +
297 +       /* Set all gates open as default */
298 +       gcl_config->atc = 0xff;
299 +       gcl_config->acl_len = cpu_to_le16(gcl_len);
300 +
301 +       if (!admin_conf->base_time) {
302 +               gcl_data->btl =
303 +                       cpu_to_le32(enetc_rd(&priv->si->hw, ENETC_SICTR0));
304 +               gcl_data->bth =
305 +                       cpu_to_le32(enetc_rd(&priv->si->hw, ENETC_SICTR1));
306 +       } else {
307 +               gcl_data->btl =
308 +                       cpu_to_le32(lower_32_bits(admin_conf->base_time));
309 +               gcl_data->bth =
310 +                       cpu_to_le32(upper_32_bits(admin_conf->base_time));
311 +       }
312 +
313 +       gcl_data->ct = cpu_to_le32(admin_conf->cycle_time);
314 +       gcl_data->cte = cpu_to_le32(admin_conf->cycle_time_extension);
315 +
316 +       for (i = 0; i < gcl_len; i++) {
317 +               struct tc_taprio_sched_entry *temp_entry;
318 +               struct gce *temp_gce = gce + i;
319 +
320 +               temp_entry = &admin_conf->entries[i];
321 +
322 +               temp_gce->gate = (u8)temp_entry->gate_mask;
323 +               temp_gce->period = cpu_to_le32(temp_entry->interval);
324 +       }
325 +
326 +       cbd.length = cpu_to_le16(data_size);
327 +       cbd.status_flags = 0;
328 +
329 +       dma = dma_map_single(&priv->si->pdev->dev, gcl_data,
330 +                            data_size, DMA_TO_DEVICE);
331 +       if (dma_mapping_error(&priv->si->pdev->dev, dma)) {
332 +               netdev_err(priv->si->ndev, "DMA mapping failed!\n");
333 +               kfree(gcl_data);
334 +               return -ENOMEM;
335 +       }
336 +
337 +       cbd.addr[0] = lower_32_bits(dma);
338 +       cbd.addr[1] = upper_32_bits(dma);
339 +       cbd.cls = BDCR_CMD_PORT_GCL;
340 +       cbd.status_flags = 0;
341 +
342 +       enetc_wr(&priv->si->hw, ENETC_QBV_PTGCR_OFFSET,
343 +                tge | ENETC_QBV_TGE);
344 +
345 +       err = enetc_send_cmd(priv->si, &cbd);
346 +       if (err)
347 +               enetc_wr(&priv->si->hw,
348 +                        ENETC_QBV_PTGCR_OFFSET,
349 +                        tge & (~ENETC_QBV_TGE));
350 +
351 +       dma_unmap_single(&priv->si->pdev->dev, dma, data_size, DMA_TO_DEVICE);
352 +       kfree(gcl_data);
353 +
354 +       return err;
355 +}
356 +
357 +int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data)
358 +{
359 +       struct tc_taprio_qopt_offload *taprio = type_data;
360 +       struct enetc_ndev_priv *priv = netdev_priv(ndev);
361 +       int err;
362 +       int i;
363 +
364 +       for (i = 0; i < priv->num_tx_rings; i++)
365 +               enetc_set_bdr_prio(&priv->si->hw,
366 +                                  priv->tx_ring[i]->index,
367 +                                  taprio->enable ? i : 0);
368 +
369 +       err = enetc_setup_taprio(ndev, taprio);
370 +
371 +       if (err)
372 +               for (i = 0; i < priv->num_tx_rings; i++)
373 +                       enetc_set_bdr_prio(&priv->si->hw,
374 +                                          priv->tx_ring[i]->index,
375 +                                          taprio->enable ? 0 : i);
376 +
377 +       return err;
378 +}