RE: [EXT] Re: [net-next] net: dsa: felix: disable always guard band bit for TAS config

2021-04-20 Thread Xiaoliang Yang
Hi Vladimir,

On Tue, Apr 20, 2021 at 16:27:10AM +0800, Vladimir Oltean wrote:
>
> On Tue, Apr 20, 2021 at 03:06:40AM +, Xiaoliang Yang wrote:
>> Hi Vladimir.
>>
>> On Mon, Apr 19, 2021 at 20:38PM +0800, Vladimir Oltean wrote:
>> >
>> >What is a scheduled queue? When time-aware scheduling is enabled on 
>> >the port, why are some queues scheduled and some not?
>>
>> The felix vsc9959 device can set SCH_TRAFFIC_QUEUES field bits to 
>> define which queue is scheduled. Only the set queues serves schedule 
>> traffic. In this driver we set all 8 queues to be scheduled in 
>> default, so all the traffic are schedule queues to schedule queue.
>
> I understand this, what I don't really understand is the distinction that the 
> switch makes between 'scheduled' and 'non-scheduled' traffic.
> What else does this distinction affect, apart from the guard bands added 
> implicitly here? The tc-taprio qdisc has no notion of 'scheduled'
> queues, all queues are 'scheduled'. Do we ever need to set the scheduled 
> queues mask to something other than 0xff? If so, when and why?

Yes, it seems only affect the guard band. If disabling always guard band bit, 
we can use SCH_TRAFFIC_QUEUES to determine which queue is non-scheduled queue. 
Only the non-scheduled queue traffic will reserve the guard band. But tc-taprio 
qdisc cannot set scheduled or non-scheduled queue now. Adding this feature can 
be discussed in future. 

It is not reasonable to add guardband in each queue traffic in default, so I 
disable the always guard band bit for TAS config.

Thanks,
Xiaoliang Yang


RE: [EXT] Re: [net-next] net: dsa: felix: disable always guard band bit for TAS config

2021-04-19 Thread Xiaoliang Yang
Hi Vladimir.

On Mon, Apr 19, 2021 at 20:38PM +0800, Vladimir Oltean wrote:
>
>What is a scheduled queue? When time-aware scheduling is enabled on the port, 
>why are some queues scheduled and some not?

The felix vsc9959 device can set SCH_TRAFFIC_QUEUES field bits to define which 
queue is scheduled. Only the set queues serves schedule traffic. In this driver 
we set all 8 queues to be scheduled in default, so all the traffic are schedule 
queues to
schedule queue.

Thanks,
Xiaoliang Yang


[net-next] net: dsa: felix: disable always guard band bit for TAS config

2021-04-19 Thread Xiaoliang Yang
ALWAYS_GUARD_BAND_SCH_Q bit in TAS config register is descripted as
this:
0: Guard band is implemented for nonschedule queues to schedule
   queues transition.
1: Guard band is implemented for any queue to schedule queue
   transition.

The driver set guard band be implemented for any queue to schedule queue
transition before, which will make each GCL time slot reserve a guard
band time that can pass the max SDU frame. Because guard band time could
not be set in tc-taprio now, it will use about 12000ns to pass 1500B max
SDU. This limits each GCL time interval to be more than 12000ns.

This patch change the guard band to be only implemented for nonschedule
queues to schedule queues transition, so that there is no need to reserve
guard band on each GCL. Users can manually add guard band time for each
schedule queues in their configuration if they want.

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix_vsc9959.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 789fe08cae50..2473bebe48e6 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -1227,8 +1227,12 @@ static int vsc9959_qos_port_tas_set(struct ocelot 
*ocelot, int port,
if (taprio->num_entries > VSC9959_TAS_GCL_ENTRY_MAX)
return -ERANGE;
 
-   ocelot_rmw(ocelot, QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM(port) |
-  QSYS_TAS_PARAM_CFG_CTRL_ALWAYS_GUARD_BAND_SCH_Q,
+   /* Set port num and disable ALWAYS_GUARD_BAND_SCH_Q, which means set
+* guard band to be implemented for nonschedule queues to schedule
+* queues transition.
+*/
+   ocelot_rmw(ocelot,
+  QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM(port),
   QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM_M |
   QSYS_TAS_PARAM_CFG_CTRL_ALWAYS_GUARD_BAND_SCH_Q,
   QSYS_TAS_PARAM_CFG_CTRL);
-- 
2.17.1



[RFC, net-next] net: qos: introduce a redundancy flow action

2020-11-16 Thread Xiaoliang Yang
This patch introduce a redundancy flow action to implement frame
replication and elimination for reliability, which is defined in
IEEE P802.1CB.

There are two modes for redundancy action: generator and recover mode.
Generator mode add redundancy tag and replicate the frame to different
egress ports. Recover mode drop the repeat frames and remove redundancy
tag from the frame.

Below is the setting example in user space:
> tc qdisc add dev swp0 clsact
> tc filter add dev swp0 ingress protocol 802.1Q flower \
skip_hw dst_mac 00:01:02:03:04:05 vlan_id 1 \
action redundancy generator split dev swp1 dev swp2

> tc filter add dev swp0 ingress protocol 802.1Q flower
skip_hw dst_mac 00:01:02:03:04:06 vlan_id 1 \
action redundancy recover

Signed-off-by: Xiaoliang Yang 
---
 include/net/flow_offload.h|   6 +
 include/net/tc_act/tc_redundancy.h|  69 +++
 include/uapi/linux/if_ether.h |   1 +
 include/uapi/linux/pkt_cls.h  |   1 +
 include/uapi/linux/tc_act/tc_redundancy.h |  36 ++
 net/sched/Kconfig |  14 +
 net/sched/Makefile|   1 +
 net/sched/act_redundancy.c| 495 ++
 net/sched/cls_api.c   |  31 ++
 9 files changed, 654 insertions(+)
 create mode 100644 include/net/tc_act/tc_redundancy.h
 create mode 100644 include/uapi/linux/tc_act/tc_redundancy.h
 create mode 100644 net/sched/act_redundancy.c

diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h
index 123b1e9ea304..aed41f3801b7 100644
--- a/include/net/flow_offload.h
+++ b/include/net/flow_offload.h
@@ -147,6 +147,7 @@ enum flow_action_id {
FLOW_ACTION_MPLS_POP,
FLOW_ACTION_MPLS_MANGLE,
FLOW_ACTION_GATE,
+   FLOW_ACTION_REDUNDANCY,
NUM_FLOW_ACTIONS,
 };
 
@@ -271,6 +272,11 @@ struct flow_action_entry {
u32 num_entries;
struct action_gate_entry *entries;
} gate;
+   struct {
+   u8  mode;
+   u32 split_num;
+   struct net_device **split_devs;
+   } redundancy;
};
struct flow_action_cookie *cookie; /* user defined action cookie */
 };
diff --git a/include/net/tc_act/tc_redundancy.h 
b/include/net/tc_act/tc_redundancy.h
new file mode 100644
index ..77b043636f93
--- /dev/null
+++ b/include/net/tc_act/tc_redundancy.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright 2020 NXP */
+
+#ifndef __NET_TC_REDUNDANCY_H
+#define __NET_TC_REDUNDANCY_H
+
+#include 
+#include 
+
+struct tcf_redundancy_split_dev {
+   struct list_head list;
+   struct net_device *dev;
+};
+
+struct tcf_redundancy {
+   struct tc_actioncommon;
+   u8  mode;
+   struct list_headsplit_list;
+   u32 gen_seq_num;
+   u32 sequence_history;
+   u32 recov_seq_num;
+};
+
+#define to_redundancy(a) ((struct tcf_redundancy *)a)
+
+static inline bool is_tcf_redundancy(const struct tc_action *a)
+{
+#ifdef CONFIG_NET_CLS_ACT
+   if (a->ops && a->ops->id == TCA_ID_REDUNDANCY)
+   return true;
+#endif
+   return false;
+}
+
+static inline u8 tcf_redundancy_mode(const struct tc_action *a)
+{
+   u8 mode;
+
+   mode = to_redundancy(a)->mode;
+
+   return mode;
+}
+
+static inline struct net_device **
+   tcf_redundancy_create_dev_array(const struct tc_action *a, int *len)
+{
+   struct tcf_redundancy_split_dev *entry;
+   struct tcf_redundancy *red_act;
+   struct net_device **devices;
+   int i = 0;
+
+   red_act = to_redundancy(a);
+
+   list_for_each_entry(entry, _act->split_list, list)
+   i++;
+
+   devices = kcalloc(i, sizeof(*devices), GFP_ATOMIC);
+   if (!devices)
+   return NULL;
+   *len = i;
+
+   i = 0;
+   list_for_each_entry(entry, _act->split_list, list)
+   devices[i++] = entry->dev;
+
+   return devices;
+}
+
+#endif
diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
index a0b637911d3c..c465d68b1d93 100644
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -114,6 +114,7 @@
 #define ETH_P_EDSA 0xDADA  /* Ethertype DSA [ NOT AN OFFICIALLY 
REGISTERED ID ] */
 #define ETH_P_DSA_8021Q0xDADB  /* Fake VLAN Header for DSA [ 
NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_IFE  0xED3E  /* ForCES inter-FE LFB type */
+#define ETH_P_RTAG 0xF1C1  /* Redundancy Tag(IEEE 802.1CB) */
 #define ETH_P_AF_IUCV   0xFBFB /* IBM af_iucv [ NOT AN OFFICIALLY 
REGISTERED ID ] */
 

[PATCH v1 net-next 3/5] net: dsa: felix: add gate action offload based on tc flower

2020-10-20 Thread Xiaoliang Yang
VSC9959 supports Per-Stream Filtering and Policing(PSFP). Sream is
identified by Null Stream identification which is defined in
IEEE802.1Qci.

For IEEE 802.1Qci, there are four tables need to set: stream table,
stream filter table, stream gate table, and flow meter table. This
patch is using TC flower gate action to set stream gate table, using
TC flower keys{dst_mac, vlan_id} to identify a stream and set the
stream table. Stream filter table is maintained automatically, and
it's index is determined by SGID(stream gate index) and FMID(flow
meter index).

On the ocelot driver, there is also a TC flower offload to set up
VCAPs. We check the chain ID to offload the rule on felix driver to
run PSFP flow.

An example to set stream gate:
> tc qdisc add dev swp0 clsact
> tc filter add dev swp0 ingress chain 3 protocol 802.1Q
flower skip_sw dst_mac  CA:9C:00:BC:6D:68 vlan_id 1 \
action gate index 1 base-time 0 \
sched-entry CLOSE 6000 3 -1

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/Makefile|   3 +-
 drivers/net/dsa/ocelot/felix.c |  23 +
 drivers/net/dsa/ocelot/felix.h |  16 +
 drivers/net/dsa/ocelot/felix_flower.c  | 651 +
 drivers/net/dsa/ocelot/felix_vsc9959.c |  10 +-
 include/soc/mscc/ocelot_ana.h  |  10 +
 6 files changed, 709 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/dsa/ocelot/felix_flower.c

diff --git a/drivers/net/dsa/ocelot/Makefile b/drivers/net/dsa/ocelot/Makefile
index f6dd131e7491..22f3f98914e3 100644
--- a/drivers/net/dsa/ocelot/Makefile
+++ b/drivers/net/dsa/ocelot/Makefile
@@ -4,7 +4,8 @@ obj-$(CONFIG_NET_DSA_MSCC_SEVILLE) += mscc_seville.o
 
 mscc_felix-objs := \
felix.o \
-   felix_vsc9959.o
+   felix_vsc9959.o \
+   felix_flower.o
 
 mscc_seville-objs := \
felix.o \
diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index f791860d495f..42f972d10539 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -716,6 +716,13 @@ static int felix_cls_flower_add(struct dsa_switch *ds, int 
port,
struct flow_cls_offload *cls, bool ingress)
 {
struct ocelot *ocelot = ds->priv;
+   struct felix *felix = ocelot_to_felix(ocelot);
+
+   if (felix->info->flower_replace) {
+   if (cls->common.chain_index == OCELOT_PSFP_CHAIN)
+   return felix->info->flower_replace(ocelot, port, cls,
+  ingress);
+   }
 
return ocelot_cls_flower_replace(ocelot, port, cls, ingress);
 }
@@ -724,6 +731,14 @@ static int felix_cls_flower_del(struct dsa_switch *ds, int 
port,
struct flow_cls_offload *cls, bool ingress)
 {
struct ocelot *ocelot = ds->priv;
+   struct felix *felix = ocelot_to_felix(ocelot);
+   int ret;
+
+   if (felix->info->flower_destroy) {
+   ret = felix->info->flower_destroy(ocelot, port, cls, ingress);
+   if (!ret)
+   return 0;
+   }
 
return ocelot_cls_flower_destroy(ocelot, port, cls, ingress);
 }
@@ -732,6 +747,14 @@ static int felix_cls_flower_stats(struct dsa_switch *ds, 
int port,
  struct flow_cls_offload *cls, bool ingress)
 {
struct ocelot *ocelot = ds->priv;
+   struct felix *felix = ocelot_to_felix(ocelot);
+   int ret;
+
+   if (felix->info->flower_stats) {
+   ret = felix->info->flower_stats(ocelot, port, cls, ingress);
+   if (!ret)
+   return 0;
+   }
 
return ocelot_cls_flower_stats(ocelot, port, cls, ingress);
 }
diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index 4c717324ac2f..9ea880deb2a0 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -37,6 +37,12 @@ struct felix_info {
void(*port_sched_speed_set)(struct ocelot *ocelot, int port,
u32 speed);
void(*xmit_template_populate)(struct ocelot *ocelot, int port);
+   int (*flower_replace)(struct ocelot *ocelot, int port,
+ struct flow_cls_offload *f, bool ingress);
+   int (*flower_destroy)(struct ocelot *ocelot, int port,
+ struct flow_cls_offload *f, bool ingress);
+   int (*flower_stats)(struct ocelot *ocelot, int port,
+   struct flow_cls_offload *f, bool ingress);
 };
 
 extern const struct dsa_switch_ops felix_switch_ops;
@@ -55,4 +61,14 @@ struct felix {
 struct net_device *felix_port_to_netdev(struct ocelot *ocelot, int port);
 int felix_netdev_to_port(struct net_device *dev);
 
+void vsc9959_new_base_time(struct ocelot *ocelot, ktime_

[PATCH v1 net-next 4/5] net: mscc: ocelot: use index to set vcap policer

2020-10-20 Thread Xiaoliang Yang
Police action of tc flower now uses index to set an entry. This patch
uses the police index to add or delete vcap policers, so that one
policer can be shared by several rules.

VCAP policers and PSFP policers share a same policer pool, so VCAP policer
add or delete operations can be exported and shared with PSFP set.

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix.c|   2 +
 drivers/net/dsa/ocelot/felix.h|   2 +
 drivers/net/dsa/ocelot/felix_vsc9959.c|   4 +
 drivers/net/ethernet/mscc/ocelot_flower.c |   5 +
 drivers/net/ethernet/mscc/ocelot_vcap.c   | 107 ++
 include/soc/mscc/ocelot.h |  11 ++-
 6 files changed, 94 insertions(+), 37 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index 42f972d10539..d2185ead36e1 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -435,6 +435,8 @@ static int felix_init_structs(struct felix *felix, int 
num_phys_ports)
ocelot->shared_queue_sz = felix->info->shared_queue_sz;
ocelot->num_mact_rows   = felix->info->num_mact_rows;
ocelot->vcap= felix->info->vcap;
+   ocelot->vcap_pol.base   = felix->info->vcap_pol_base;
+   ocelot->vcap_pol.max= felix->info->vcap_pol_max;
ocelot->ops = felix->info->ops;
ocelot->inj_prefix  = OCELOT_TAG_PREFIX_SHORT;
ocelot->xtr_prefix  = OCELOT_TAG_PREFIX_SHORT;
diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index 9ea880deb2a0..41a147c978f4 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -22,6 +22,8 @@ struct felix_info {
int num_ports;
int num_tx_queues;
struct vcap_props   *vcap;
+   u16 vcap_pol_base;
+   u16 vcap_pol_max;
int switch_pci_bar;
int imdio_pci_bar;
const struct ptp_clock_info *ptp_caps;
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index f171e6f3fc98..32c9b4f60575 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -17,6 +17,8 @@
 #include "felix.h"
 
 #define VSC9959_TAS_GCL_ENTRY_MAX  63
+#define VSC9959_VCAP_POLICER_BASE  63
+#define VSC9959_VCAP_POLICER_MAX   383
 
 static const u32 vsc9959_ana_regmap[] = {
REG(ANA_ADVLEARN,   0x0089a0),
@@ -1357,6 +1359,8 @@ static const struct felix_info felix_info_vsc9959 = {
.stats_layout   = vsc9959_stats_layout,
.num_stats  = ARRAY_SIZE(vsc9959_stats_layout),
.vcap   = vsc9959_vcap_props,
+   .vcap_pol_base  = VSC9959_VCAP_POLICER_BASE,
+   .vcap_pol_max   = VSC9959_VCAP_POLICER_MAX,
.shared_queue_sz= 128 * 1024,
.num_mact_rows  = 2048,
.num_ports  = 6,
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c 
b/drivers/net/ethernet/mscc/ocelot_flower.c
index 89f35aecbda7..4957016d503e 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -225,6 +225,11 @@ static int ocelot_flower_parse_action(struct ocelot 
*ocelot, int port,
return -EOPNOTSUPP;
}
filter->action.police_ena = true;
+   filter->action.pol_ix = a->police.index +
+   ocelot->vcap_pol.base;
+   if (filter->action.pol_ix > ocelot->vcap_pol.max)
+   return -EINVAL;
+
rate = a->police.rate_bytes_ps;
filter->action.pol.rate = div_u64(rate, 1000) * 8;
filter->action.pol.burst = a->police.burst;
diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.c 
b/drivers/net/ethernet/mscc/ocelot_vcap.c
index d8c778ee6f1b..f68b5af591b1 100644
--- a/drivers/net/ethernet/mscc/ocelot_vcap.c
+++ b/drivers/net/ethernet/mscc/ocelot_vcap.c
@@ -886,10 +886,19 @@ static void vcap_entry_set(struct ocelot *ocelot, int ix,
return es0_entry_set(ocelot, ix, filter);
 }
 
-static int ocelot_vcap_policer_add(struct ocelot *ocelot, u32 pol_ix,
-  struct ocelot_policer *pol)
+struct vcap_policer_entry {
+   struct list_head list;
+   refcount_t refcount;
+   u32 pol_ix;
+};
+
+int ocelot_vcap_policer_add(struct ocelot *ocelot, u32 pol_ix,
+   struct ocelot_policer *pol)
 {
struct qos_policer_conf pp = { 0 };
+   struct vcap_policer_entry *tmp;

[PATCH v1 net-next 1/5] net: mscc: ocelot: add and export MAC table lookup operations

2020-10-20 Thread Xiaoliang Yang
Add ocelot_mact_lookup() function to retrieve the row and column at
which an FDB entry with the given {DMAC, VID} key is found.

This function is needed in felix DSA driver, so export it.

Signed-off-by: Vladimir Oltean 
Signed-off-by: Xiaoliang Yang 
---
 drivers/net/ethernet/mscc/ocelot.c | 33 --
 drivers/net/ethernet/mscc/ocelot.h | 13 
 include/soc/mscc/ocelot.h  | 22 
 3 files changed, 49 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c 
b/drivers/net/ethernet/mscc/ocelot.c
index 70bf8c67d7ef..5571867a11db 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -12,12 +12,6 @@
 #define TABLE_UPDATE_SLEEP_US 10
 #define TABLE_UPDATE_TIMEOUT_US 10
 
-struct ocelot_mact_entry {
-   u8 mac[ETH_ALEN];
-   u16 vid;
-   enum macaccess_entry_type type;
-};
-
 static inline u32 ocelot_mact_read_macaccess(struct ocelot *ocelot)
 {
return ocelot_read(ocelot, ANA_TABLES_MACACCESS);
@@ -87,6 +81,33 @@ int ocelot_mact_forget(struct ocelot *ocelot,
 }
 EXPORT_SYMBOL(ocelot_mact_forget);
 
+int ocelot_mact_lookup(struct ocelot *ocelot, const unsigned char 
mac[ETH_ALEN],
+  unsigned int vid, int *row, int *col)
+{
+   int val;
+
+   ocelot_mact_select(ocelot, mac, vid);
+
+   /* Issue a read command with MACACCESS_VALID=1. */
+   ocelot_write(ocelot, ANA_TABLES_MACACCESS_VALID |
+ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_READ),
+ANA_TABLES_MACACCESS);
+
+   if (ocelot_mact_wait_for_completion(ocelot))
+   return -ETIMEDOUT;
+
+   /* Read back the entry flags */
+   val = ocelot_read(ocelot, ANA_TABLES_MACACCESS);
+   if (!(val & ANA_TABLES_MACACCESS_VALID))
+   return -ENOENT;
+
+   ocelot_field_read(ocelot, ANA_TABLES_MACTINDX_M_INDEX, row);
+   ocelot_field_read(ocelot, ANA_TABLES_MACTINDX_BUCKET, col);
+
+   return 0;
+}
+EXPORT_SYMBOL(ocelot_mact_lookup);
+
 static void ocelot_mact_init(struct ocelot *ocelot)
 {
/* Configure the learning mode entries attributes:
diff --git a/drivers/net/ethernet/mscc/ocelot.h 
b/drivers/net/ethernet/mscc/ocelot.h
index abb407dff93c..44e39683a5a4 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -74,19 +74,6 @@ struct ocelot_dump_ctx {
int idx;
 };
 
-/* MAC table entry types.
- * ENTRYTYPE_NORMAL is subject to aging.
- * ENTRYTYPE_LOCKED is not subject to aging.
- * ENTRYTYPE_MACv4 is not subject to aging. For IPv4 multicast.
- * ENTRYTYPE_MACv6 is not subject to aging. For IPv6 multicast.
- */
-enum macaccess_entry_type {
-   ENTRYTYPE_NORMAL = 0,
-   ENTRYTYPE_LOCKED,
-   ENTRYTYPE_MACv4,
-   ENTRYTYPE_MACv6,
-};
-
 int ocelot_port_fdb_do_dump(const unsigned char *addr, u16 vid,
bool is_static, void *data);
 int ocelot_mact_learn(struct ocelot *ocelot, int port,
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 1e9db9577441..31da33fdb7ac 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -659,6 +659,28 @@ struct ocelot_policer {
u32 burst; /* bytes */
 };
 
+/* MAC table entry types.
+ * ENTRYTYPE_NORMAL is subject to aging.
+ * ENTRYTYPE_LOCKED is not subject to aging.
+ * ENTRYTYPE_MACv4 is not subject to aging. For IPv4 multicast.
+ * ENTRYTYPE_MACv6 is not subject to aging. For IPv6 multicast.
+ */
+enum macaccess_entry_type {
+   ENTRYTYPE_NORMAL = 0,
+   ENTRYTYPE_LOCKED,
+   ENTRYTYPE_MACv4,
+   ENTRYTYPE_MACv6,
+};
+
+struct ocelot_mact_entry {
+   u8 mac[ETH_ALEN];
+   u16 vid;
+   enum macaccess_entry_type type;
+};
+
+int ocelot_mact_lookup(struct ocelot *ocelot, const unsigned char 
mac[ETH_ALEN],
+  unsigned int vid, int *row, int *col);
+
 #define ocelot_read_ix(ocelot, reg, gi, ri) __ocelot_read_ix(ocelot, reg, 
reg##_GSZ * (gi) + reg##_RSZ * (ri))
 #define ocelot_read_gix(ocelot, reg, gi) __ocelot_read_ix(ocelot, reg, 
reg##_GSZ * (gi))
 #define ocelot_read_rix(ocelot, reg, ri) __ocelot_read_ix(ocelot, reg, 
reg##_RSZ * (ri))
-- 
2.17.1



[PATCH v1 net-next 2/5] net: mscc: ocelot: set vcap IS2 chain to goto PSFP chain

2020-10-20 Thread Xiaoliang Yang
VSC9959 supports Per-Stream Filtering and Policing(PSFP), which is
processing after VCAP blocks. We set this block on chain 3 and
set vcap IS2 chain to goto PSFP chain if hardware support.

An example set is:
> tc filter add dev swp0 ingress chain 21000 flower
skip_sw action goto chain 3

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/ethernet/mscc/ocelot_flower.c | 14 +-
 include/soc/mscc/ocelot.h | 10 ++
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c 
b/drivers/net/ethernet/mscc/ocelot_flower.c
index 729495a1a77e..89f35aecbda7 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -11,15 +11,14 @@
 /* Arbitrarily chosen constants for encoding the VCAP block and lookup number
  * into the chain number. This is UAPI.
  */
-#define VCAP_BLOCK 1
 #define VCAP_LOOKUP1000
 #define VCAP_IS1_NUM_LOOKUPS   3
 #define VCAP_IS2_NUM_LOOKUPS   2
 #define VCAP_IS2_NUM_PAG   256
 #define VCAP_IS1_CHAIN(lookup) \
-   (1 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP)
+   (OCELOT_INGRESS_IS1 * OCELOT_HW_BLOCK + (lookup) * VCAP_LOOKUP)
 #define VCAP_IS2_CHAIN(lookup, pag)\
-   (2 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP + (pag))
+   (OCELOT_INGRESS_IS2 * OCELOT_HW_BLOCK + (lookup) * VCAP_LOOKUP + (pag))
 
 static int ocelot_chain_to_block(int chain, bool ingress)
 {
@@ -84,7 +83,8 @@ static bool ocelot_is_goto_target_valid(int goto_target, int 
chain,
goto_target == VCAP_IS1_CHAIN(1) ||
goto_target == VCAP_IS1_CHAIN(2) ||
goto_target == VCAP_IS2_CHAIN(0, 0) ||
-   goto_target == VCAP_IS2_CHAIN(1, 0));
+   goto_target == VCAP_IS2_CHAIN(1, 0) ||
+   goto_target == OCELOT_PSFP_CHAIN);
 
if (chain == VCAP_IS1_CHAIN(0))
return (goto_target == VCAP_IS1_CHAIN(1));
@@ -111,7 +111,11 @@ static bool ocelot_is_goto_target_valid(int goto_target, 
int chain,
if (chain == VCAP_IS2_CHAIN(0, pag))
return (goto_target == VCAP_IS2_CHAIN(1, pag));
 
-   /* VCAP IS2 lookup 1 cannot jump anywhere */
+   /* VCAP IS2 lookup 1 can goto to PSFP block if hardware support */
+   for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
+   if (chain == VCAP_IS2_CHAIN(1, pag))
+   return (goto_target == OCELOT_PSFP_CHAIN);
+
return false;
 }
 
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 31da33fdb7ac..67e71d75fc97 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -556,6 +556,16 @@ enum ocelot_tag_prefix {
OCELOT_TAG_PREFIX_LONG,
 };
 
+enum ocelot_ingress_blocks {
+   OCELOT_INGRESS_DEFAULT  = 0,
+   OCELOT_INGRESS_IS1,
+   OCELOT_INGRESS_IS2,
+   OCELOT_INGRESS_PSFP,
+};
+
+#define OCELOT_HW_BLOCK1
+#define OCELOT_PSFP_CHAIN  (OCELOT_INGRESS_PSFP * OCELOT_HW_BLOCK)
+
 struct ocelot;
 
 struct ocelot_ops {
-- 
2.17.1



[PATCH v1 net-next 5/5] net: dsa: felix: add police action for tc flower offload

2020-10-20 Thread Xiaoliang Yang
This patch add police action to set flow meter table which is defined
in IEEE802.1Qci. Flow metering is two rates two buckets and three color
marker to policing the frames, we only enable one rate one bucket in
this patch.

Flow metering shares a same policer pool with VCAP policers, it calls
ocelot_vcap_policer_add() and ocelot_vcap_policer_del() to set flow
meter table.

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix_flower.c | 32 +++
 1 file changed, 32 insertions(+)

diff --git a/drivers/net/dsa/ocelot/felix_flower.c 
b/drivers/net/dsa/ocelot/felix_flower.c
index 71894dcc0af2..d58a2357bab1 100644
--- a/drivers/net/dsa/ocelot/felix_flower.c
+++ b/drivers/net/dsa/ocelot/felix_flower.c
@@ -363,6 +363,8 @@ static void felix_list_stream_filter_del(struct ocelot 
*ocelot, u32 index)
if (tmp->index == index) {
if (tmp->sg_valid)
felix_list_gate_del(ocelot, tmp->sgid);
+   if (tmp->fm_valid)
+   ocelot_vcap_policer_del(ocelot, tmp->fmid);
 
z = refcount_dec_and_test(>refcount);
if (z) {
@@ -466,6 +468,8 @@ static int felix_psfp_set(struct ocelot *ocelot,
if (ret) {
if (sfi->sg_valid)
felix_list_gate_del(ocelot, sfi->sgid);
+   if (sfi->fm_valid)
+   ocelot_vcap_policer_del(ocelot, sfi->fmid);
return ret;
}
 
@@ -559,7 +563,9 @@ int felix_flower_stream_replace(struct ocelot *ocelot, int 
port,
struct felix_streamid stream = {0};
struct felix_stream_gate_conf *sgi;
const struct flow_action_entry *a;
+   struct ocelot_policer pol;
int ret, size, i;
+   u64 rate, burst;
u32 index;
 
ret = felix_flower_parse_key(f, );
@@ -595,6 +601,32 @@ int felix_flower_stream_replace(struct ocelot *ocelot, int 
port,
stream.sfid_valid = 1;
kfree(sgi);
break;
+   case FLOW_ACTION_POLICE:
+   if (f->common.chain_index != OCELOT_PSFP_CHAIN) {
+   NL_SET_ERR_MSG_MOD(extack,
+  "Police action only be 
offloaded to PSFP chain");
+   return -EOPNOTSUPP;
+   }
+
+   index = a->police.index + FELIX_POLICER_PSFP_BASE;
+   if (index > FELIX_POLICER_PSFP_MAX)
+   return -EINVAL;
+
+   rate = a->police.rate_bytes_ps;
+   burst = rate * PSCHED_NS2TICKS(a->police.burst);
+   pol = (struct ocelot_policer) {
+   .burst = div_u64(burst, PSCHED_TICKS_PER_SEC),
+   .rate = div_u64(rate, 1000) * 8,
+   };
+   ret = ocelot_vcap_policer_add(ocelot, index, );
+   if (ret)
+   return ret;
+
+   sfi.fm_valid = 1;
+   sfi.fmid = index;
+   sfi.maxsdu = a->police.mtu;
+   stream.sfid_valid = 1;
+   break;
default:
return -EOPNOTSUPP;
}
-- 
2.17.1



[PATCH v1 net-next 0/5] net: dsa: felix: psfp support on

2020-10-20 Thread Xiaoliang Yang
This patch series add gate and police action for tc flower offload to
support Per-Stream Filtering and Policing(PSFP), which is defined in
IEEE802.1Qci.

There is also a TC flower offload to set up VCAPs on ocelot driver.
Because VCAPs use chain 1-21255, we set chain 3 to offload to
gate and police action to run PSFP module.

example:
> tc qdisc add dev swp0 clsact
> tc filter add dev swp0 ingress chain 0 pref 49152 flower \
skip_sw action goto chain 3
> tc filter add dev swp0 ingress chain 3 protocol 802.1Q \
flower skip_sw dst_mac  42:01:3E:72:2F:6B vlan_id 1 \
action gate index 1 base-time 0 \
sched-entry OPEN 6000 3 -1 \
action police index 1 rate 10Mbit burst 1

Xiaoliang Yang (5):
  net: mscc: ocelot: add and export MAC table lookup operations
  net: mscc: ocelot: set vcap IS2 chain to goto PSFP chain
  net: dsa: felix: add gate action offload based on tc flower
  net: mscc: ocelot: use index to set vcap policer
  net: dsa: felix: add police action for tc flower offload

 drivers/net/dsa/ocelot/Makefile   |   3 +-
 drivers/net/dsa/ocelot/felix.c|  25 +
 drivers/net/dsa/ocelot/felix.h|  18 +
 drivers/net/dsa/ocelot/felix_flower.c | 683 ++
 drivers/net/dsa/ocelot/felix_vsc9959.c|  14 +-
 drivers/net/ethernet/mscc/ocelot.c|  33 +-
 drivers/net/ethernet/mscc/ocelot.h|  13 -
 drivers/net/ethernet/mscc/ocelot_flower.c |  19 +-
 drivers/net/ethernet/mscc/ocelot_vcap.c   | 107 ++--
 include/soc/mscc/ocelot.h |  43 +-
 include/soc/mscc/ocelot_ana.h |  10 +
 11 files changed, 903 insertions(+), 65 deletions(-)
 create mode 100644 drivers/net/dsa/ocelot/felix_flower.c

-- 
2.17.1



[RFC, net-next 1/3] net: dsa: ethtool preempt ops support on slave ports

2020-10-19 Thread Xiaoliang Yang
Preempt_set and preempt_get are new functions of ethtool ops, which
is to configure frame preemption according to 802.1qbu and 802.3br.
Add them on slave ports of DSA framework, so that DSA devices can
support to configure frame preemption by using ethtool.

Signed-off-by: Xiaoliang Yang 
---
 include/net/dsa.h | 12 
 net/dsa/slave.c   | 26 ++
 2 files changed, 38 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 35429a140dfa..85b196ade511 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -499,6 +499,18 @@ struct dsa_switch_ops {
int (*get_ts_info)(struct dsa_switch *ds, int port,
   struct ethtool_ts_info *ts);
 
+   /*
+* ethtool --set-frame-preemption
+*/
+   int (*set_preempt)(struct dsa_switch *ds, int port,
+  struct ethtool_fp *fpcmd);
+
+   /*
+* ethtool --show-frame-preemption
+*/
+   int (*get_preempt)(struct dsa_switch *ds, int port,
+  struct ethtool_fp *fpcmd);
+
/*
 * Suspend and resume
 */
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index e7c1d62fde99..f51a1575266c 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1281,6 +1281,30 @@ static int dsa_slave_get_ts_info(struct net_device *dev,
return ds->ops->get_ts_info(ds, p->dp->index, ts);
 }
 
+static int dsa_slave_set_preempt(struct net_device *dev,
+struct ethtool_fp *fpcmd)
+{
+   struct dsa_slave_priv *p = netdev_priv(dev);
+   struct dsa_switch *ds = p->dp->ds;
+
+   if (!ds->ops->set_preempt)
+   return -EOPNOTSUPP;
+
+   return ds->ops->set_preempt(ds, p->dp->index, fpcmd);
+}
+
+static int dsa_slave_get_preempt(struct net_device *dev,
+struct ethtool_fp *fpcmd)
+{
+   struct dsa_slave_priv *p = netdev_priv(dev);
+   struct dsa_switch *ds = p->dp->ds;
+
+   if (!ds->ops->get_preempt)
+   return -EOPNOTSUPP;
+
+   return ds->ops->get_preempt(ds, p->dp->index, fpcmd);
+}
+
 static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
 u16 vid)
 {
@@ -1571,6 +1595,8 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_rxnfc  = dsa_slave_get_rxnfc,
.set_rxnfc  = dsa_slave_set_rxnfc,
.get_ts_info= dsa_slave_get_ts_info,
+   .set_preempt= dsa_slave_set_preempt,
+   .get_preempt= dsa_slave_get_preempt,
 };
 
 /* legacy way, bypassing the bridge */
-- 
2.18.4



[RFC, net-next 3/3] net: dsa: felix: tc-taprio preempt set support

2020-10-19 Thread Xiaoliang Yang
After using ethtool to enable and configure frame preemption on
vsc9959, use tc-taprio preempt set to mark the preempt queues and
express queueus.

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix_vsc9959.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index c0e41d499639..f2b9a5ee1ff5 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -1310,6 +1310,20 @@ static int vsc9959_qos_port_cbs_set(struct dsa_switch 
*ds, int port,
return 0;
 }
 
+static int vsc9959_port_preempt_queues(struct ocelot *ocelot, int port,
+  struct tc_preempt_qopt_offload *qopt)
+{
+   u8 p_queues = qopt->preemptible_queues;
+
+   ocelot_rmw_rix(ocelot,
+  QSYS_PREEMPTION_CFG_P_QUEUES(p_queues),
+  QSYS_PREEMPTION_CFG_P_QUEUES_M,
+  QSYS_PREEMPTION_CFG,
+  port);
+
+   return 0;
+}
+
 static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,
 enum tc_setup_type type,
 void *type_data)
@@ -1321,6 +1335,8 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, 
int port,
return vsc9959_qos_port_tas_set(ocelot, port, type_data);
case TC_SETUP_QDISC_CBS:
return vsc9959_qos_port_cbs_set(ds, port, type_data);
+   case TC_SETUP_PREEMPT:
+   return vsc9959_port_preempt_queues(ocelot, port, type_data);
default:
return -EOPNOTSUPP;
}
-- 
2.18.4



[RFC, net-next 2/3] net: dsa: felix: add preempt queues set support for vsc9959

2020-10-19 Thread Xiaoliang Yang
VSC9959 support preempt queues according to 802.1qbu and 802.3br. This
patch add ethtool preempt set to configure preemption.

In user space, it can be set like this:
ethtool --set-frame-preemption swp0 enable min-frag-size 0

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix.c | 26 ++
 drivers/net/dsa/ocelot/felix.h |  4 +++
 drivers/net/dsa/ocelot/felix_vsc9959.c | 49 ++
 include/soc/mscc/ocelot.h  | 11 ++
 include/soc/mscc/ocelot_dev.h  | 23 
 5 files changed, 113 insertions(+)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index f791860d495f..e08effbeb6bf 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -350,6 +350,30 @@ static int felix_get_ts_info(struct dsa_switch *ds, int 
port,
return ocelot_get_ts_info(ocelot, port, info);
 }
 
+static int felix_set_preempt(struct dsa_switch *ds, int port,
+struct ethtool_fp *fpcmd)
+{
+   struct ocelot *ocelot = ds->priv;
+   struct felix *felix = ocelot_to_felix(ocelot);
+
+   if (felix->info->port_set_preempt)
+   return felix->info->port_set_preempt(ocelot, port, fpcmd);
+
+   return -EOPNOTSUPP;
+}
+
+static int felix_get_preempt(struct dsa_switch *ds, int port,
+struct ethtool_fp *fpcmd)
+{
+   struct ocelot *ocelot = ds->priv;
+   struct felix *felix = ocelot_to_felix(ocelot);
+
+   if (felix->info->port_get_preempt)
+   return felix->info->port_get_preempt(ocelot, port, fpcmd);
+
+   return -EOPNOTSUPP;
+}
+
 static int felix_parse_ports_node(struct felix *felix,
  struct device_node *ports_node,
  phy_interface_t *port_phy_modes)
@@ -777,6 +801,8 @@ const struct dsa_switch_ops felix_switch_ops = {
.get_ethtool_stats  = felix_get_ethtool_stats,
.get_sset_count = felix_get_sset_count,
.get_ts_info= felix_get_ts_info,
+   .set_preempt= felix_set_preempt,
+   .get_preempt= felix_get_preempt,
.phylink_validate   = felix_phylink_validate,
.phylink_mac_config = felix_phylink_mac_config,
.phylink_mac_link_down  = felix_phylink_mac_link_down,
diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index 4c717324ac2f..e0c93d4a351d 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -37,6 +37,10 @@ struct felix_info {
void(*port_sched_speed_set)(struct ocelot *ocelot, int port,
u32 speed);
void(*xmit_template_populate)(struct ocelot *ocelot, int port);
+   int (*port_set_preempt)(struct ocelot *ocelot, int port,
+   struct ethtool_fp *fpcmd);
+   int (*port_get_preempt)(struct ocelot *ocelot, int port,
+   struct ethtool_fp *fpcmd);
 };
 
 extern const struct dsa_switch_ops felix_switch_ops;
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 3e925b8d5306..c0e41d499639 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -340,6 +341,10 @@ static const u32 vsc9959_dev_gmii_regmap[] = {
REG(DEV_MAC_FC_MAC_LOW_CFG, 0x3c),
REG(DEV_MAC_FC_MAC_HIGH_CFG,0x40),
REG(DEV_MAC_STICKY, 0x44),
+   REG(DEV_MM_ENABLE_CONFIG,   0x48),
+   REG(DEV_MM_VERIF_CONFIG,0x4c),
+   REG(DEV_MM_STATUS,  0x50),
+
REG_RESERVED(PCS1G_CFG),
REG_RESERVED(PCS1G_MODE_CFG),
REG_RESERVED(PCS1G_SD_CFG),
@@ -1321,6 +1326,48 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, 
int port,
}
 }
 
+static int vsc9959_port_set_preempt(struct ocelot *ocelot, int port,
+   struct ethtool_fp *fpcmd)
+{
+   struct ocelot_port *ocelot_port = ocelot->ports[port];
+   int mm_fragsize = fpcmd->min_frag_size_mult;
+
+   if (mm_fragsize > 3)
+   return -EINVAL;
+
+   ocelot_port_rmwl(ocelot_port,
+(fpcmd->enabled ?
+ (DEV_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA |
+  DEV_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA) : 0),
+DEV_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA |
+DEV_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA,
+DEV_MM_ENABLE_CONFIG);
+
+   ocelot_rmw_rix(ocelot,
+  QSYS_PREEMPTION_CFG_MM_ADD_FRAG_SIZE(mm_fragsize),
+  

[RFC, net-next 0/3] net: dsa: felix: frame preemption support

2020-10-19 Thread Xiaoliang Yang
VSC9959 supports frame preemption according to 802.1qbu and 802.3br.
This patch series use ethtool to enable and configure frame preemption,
then use tc-taprio preempt set to mark the preempt queues and express
queueus.

This series depends on series: "ethtool: Add support for frame preemption"
link: 
http://patchwork.ozlabs.org/project/netdev/patch/20201012235642.1384318-2-vinicius.go...@intel.com/

Xiaoliang Yang (3):
  net: dsa: ethtool preempt ops support on slave ports
  net: dsa: felix: add preempt queues set support for vsc9959
  net: dsa: felix: tc-taprio preempt set support

 drivers/net/dsa/ocelot/felix.c | 26 +++
 drivers/net/dsa/ocelot/felix.h |  4 ++
 drivers/net/dsa/ocelot/felix_vsc9959.c | 65 ++
 include/net/dsa.h  | 12 +
 include/soc/mscc/ocelot.h  | 11 +
 include/soc/mscc/ocelot_dev.h  | 23 +
 net/dsa/slave.c| 26 +++
 7 files changed, 167 insertions(+)

-- 
2.18.4



[PATCH v2 net] net: mscc: ocelot: fix fields offset in SG_CONFIG_REG_3

2020-09-24 Thread Xiaoliang Yang
INIT_IPS and GATE_STATE fields have a wrong offset in SG_CONFIG_REG_3.
This register is used by stream gate control of PSFP, and it has not
been used before, because PSFP is not implemented in ocelot driver.

Signed-off-by: Xiaoliang Yang 
---
 include/soc/mscc/ocelot_ana.h | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/soc/mscc/ocelot_ana.h b/include/soc/mscc/ocelot_ana.h
index 841c6ec22b64..1669481d9779 100644
--- a/include/soc/mscc/ocelot_ana.h
+++ b/include/soc/mscc/ocelot_ana.h
@@ -252,10 +252,10 @@
 #define ANA_SG_CONFIG_REG_3_LIST_LENGTH_M GENMASK(18, 16)
 #define ANA_SG_CONFIG_REG_3_LIST_LENGTH_X(x)  (((x) & GENMASK(18, 
16)) >> 16)
 #define ANA_SG_CONFIG_REG_3_GATE_ENABLE   BIT(20)
-#define ANA_SG_CONFIG_REG_3_INIT_IPS(x)   (((x) << 24) & 
GENMASK(27, 24))
-#define ANA_SG_CONFIG_REG_3_INIT_IPS_MGENMASK(27, 24)
-#define ANA_SG_CONFIG_REG_3_INIT_IPS_X(x) (((x) & GENMASK(27, 
24)) >> 24)
-#define ANA_SG_CONFIG_REG_3_INIT_GATE_STATE   BIT(28)
+#define ANA_SG_CONFIG_REG_3_INIT_IPS(x)   (((x) << 21) & 
GENMASK(24, 21))
+#define ANA_SG_CONFIG_REG_3_INIT_IPS_MGENMASK(24, 21)
+#define ANA_SG_CONFIG_REG_3_INIT_IPS_X(x) (((x) & GENMASK(24, 
21)) >> 21)
+#define ANA_SG_CONFIG_REG_3_INIT_GATE_STATE   BIT(25)
 
 #define ANA_SG_GCL_GS_CONFIG_RSZ  0x4
 
-- 
2.17.1



RE: [EXT] Re: [net] net: mscc: ocelot: fix fields offset in SG_CONFIG_REG_3

2020-09-24 Thread Xiaoliang Yang
Hi Alexandre,

On 24/09/2020 15:08:21+0800, Alexandre Belloni wrote:
> 
> Hi,
> 
> On 24/09/2020 10:11:13+0800, Xiaoliang Yang wrote:
> > INIT_IPS and GATE_ENABLE fields have a wrong offset in SG_CONFIG_REG_3.
> 
> You are changing GATE_STATE, not GATE_ENABLE
Oh, sorry, it should be GATE_STATE field.

> 
> > This register is used by stream gate control of PSFP, and it has not
> > been used before, because PSFP is not implemented in ocelot driver.
> >
> > Signed-off-by: Xiaoliang Yang 
> > ---
> >  include/soc/mscc/ocelot_ana.h | 8 
> >  1 file changed, 4 insertions(+), 4 deletions(-)
> >
> > diff --git a/include/soc/mscc/ocelot_ana.h
> > b/include/soc/mscc/ocelot_ana.h index 841c6ec22b64..1669481d9779
> > 100644
> > --- a/include/soc/mscc/ocelot_ana.h
> > +++ b/include/soc/mscc/ocelot_ana.h
> > @@ -252,10 +252,10 @@
> >  #define ANA_SG_CONFIG_REG_3_LIST_LENGTH_M
> GENMASK(18, 16)
> >  #define ANA_SG_CONFIG_REG_3_LIST_LENGTH_X(x)  (((x)
> & GENMASK(18, 16)) >> 16)
> >  #define ANA_SG_CONFIG_REG_3_GATE_ENABLE
> BIT(20)
> > -#define ANA_SG_CONFIG_REG_3_INIT_IPS(x)   (((x) <<
> 24) & GENMASK(27, 24))
> > -#define ANA_SG_CONFIG_REG_3_INIT_IPS_M
> GENMASK(27, 24)
> > -#define ANA_SG_CONFIG_REG_3_INIT_IPS_X(x) (((x) &
> GENMASK(27, 24)) >> 24)
> > -#define ANA_SG_CONFIG_REG_3_INIT_GATE_STATE
> BIT(28)
> > +#define ANA_SG_CONFIG_REG_3_INIT_IPS(x)   (((x) <<
> 21) & GENMASK(24, 21))
> > +#define ANA_SG_CONFIG_REG_3_INIT_IPS_M
> GENMASK(24, 21)
> > +#define ANA_SG_CONFIG_REG_3_INIT_IPS_X(x) (((x) &
> GENMASK(24, 21)) >> 21)
> > +#define ANA_SG_CONFIG_REG_3_INIT_GATE_STATE
> BIT(25)
> >
> 
> VSC7514 doesn't have the stream gate registers ans this was generated
> automatically from the cml file for felix. Did that change?
> 
> Seeing that bits in this register are not packed, I would believe your change 
> is
> correct.
Yes, this register is in VSC9959, we need it in PSFP gate control function for 
felix in future. I have tested on VSC9959, the bit offsets are not correct.

Thanks,
Xiaoliang Yang


[net] net: mscc: ocelot: fix fields offset in SG_CONFIG_REG_3

2020-09-23 Thread Xiaoliang Yang
INIT_IPS and GATE_ENABLE fields have a wrong offset in SG_CONFIG_REG_3.
This register is used by stream gate control of PSFP, and it has not
been used before, because PSFP is not implemented in ocelot driver.

Signed-off-by: Xiaoliang Yang 
---
 include/soc/mscc/ocelot_ana.h | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/soc/mscc/ocelot_ana.h b/include/soc/mscc/ocelot_ana.h
index 841c6ec22b64..1669481d9779 100644
--- a/include/soc/mscc/ocelot_ana.h
+++ b/include/soc/mscc/ocelot_ana.h
@@ -252,10 +252,10 @@
 #define ANA_SG_CONFIG_REG_3_LIST_LENGTH_M GENMASK(18, 16)
 #define ANA_SG_CONFIG_REG_3_LIST_LENGTH_X(x)  (((x) & GENMASK(18, 
16)) >> 16)
 #define ANA_SG_CONFIG_REG_3_GATE_ENABLE   BIT(20)
-#define ANA_SG_CONFIG_REG_3_INIT_IPS(x)   (((x) << 24) & 
GENMASK(27, 24))
-#define ANA_SG_CONFIG_REG_3_INIT_IPS_MGENMASK(27, 24)
-#define ANA_SG_CONFIG_REG_3_INIT_IPS_X(x) (((x) & GENMASK(27, 
24)) >> 24)
-#define ANA_SG_CONFIG_REG_3_INIT_GATE_STATE   BIT(28)
+#define ANA_SG_CONFIG_REG_3_INIT_IPS(x)   (((x) << 21) & 
GENMASK(24, 21))
+#define ANA_SG_CONFIG_REG_3_INIT_IPS_MGENMASK(24, 21)
+#define ANA_SG_CONFIG_REG_3_INIT_IPS_X(x) (((x) & GENMASK(24, 
21)) >> 21)
+#define ANA_SG_CONFIG_REG_3_INIT_GATE_STATE   BIT(25)
 
 #define ANA_SG_GCL_GS_CONFIG_RSZ  0x4
 
-- 
2.17.1



RE: [net-next] net: dsa: felix: convert TAS link speed based on phylink speed

2020-09-23 Thread Xiaoliang Yang


On Tue, Sep 22, 2020 at 19:37, Vladimir Oltean wrote:
> 
> Hi Xiaoliang,
> 
> On Tue, Sep 22, 2020 at 06:43:02PM +0800, Xiaoliang Yang wrote:
> > state->speed holds a value of 10, 100, 1000 or 2500, but
> > QSYS_TAG_CONFIG_LINK_SPEED expects a value of 0, 1, 2, 3. So convert
> > the speed to a proper value.
> >
> > Fixes: de143c0e274b ("net: dsa: felix: Configure Time-Aware Scheduler
> > via taprio offload")
> >
> > Signed-off-by: Xiaoliang Yang 
> > ---
> 
> Reviewed-by: Vladimir Oltean 
> 
> But next time keep in mind the following:
> 
> - The Fixes: tag should never wrap on multiple lines, even if it exceeds
>   80 characters.
> - Patches that fix a problem in net-next only should go to David's
>   net-next tree. Patches that fix a problem on Linus Torvalds' tree
>   should go to David's "net" tree. This one should go to "net", not to
>   "net-next".
> - All tags (Fixes, Signed-off-by, etc) should be grouped together with
>   no empty lines between them.
> 
> Actually due to the first issue I mentioned, could you please resend this?
> 
> Thanks,
> -Vladimir

I modify the commit and resend this patch to "net tree", please reject this one.

Thanks,
Xiaoliang Yang


[net] net: dsa: felix: convert TAS link speed based on phylink speed

2020-09-23 Thread Xiaoliang Yang
state->speed holds a value of 10, 100, 1000 or 2500, but
QSYS_TAG_CONFIG_LINK_SPEED expects a value of 0, 1, 2, 3. So convert the
speed to a proper value.

Fixes: de143c0e274b ("net: dsa: felix: Configure Time-Aware Scheduler via 
taprio offload")
Signed-off-by: Xiaoliang Yang 
Reviewed-by: Vladimir Oltean 
---
 drivers/net/dsa/ocelot/felix_vsc9959.c | 22 +-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 6855c94256f8..36db631a55e6 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -1284,8 +1284,28 @@ void vsc9959_mdio_bus_free(struct ocelot *ocelot)
 static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
u32 speed)
 {
+   u8 tas_speed;
+
+   switch (speed) {
+   case SPEED_10:
+   tas_speed = OCELOT_SPEED_10;
+   break;
+   case SPEED_100:
+   tas_speed = OCELOT_SPEED_100;
+   break;
+   case SPEED_1000:
+   tas_speed = OCELOT_SPEED_1000;
+   break;
+   case SPEED_2500:
+   tas_speed = OCELOT_SPEED_2500;
+   break;
+   default:
+   tas_speed = OCELOT_SPEED_1000;
+   break;
+   }
+
ocelot_rmw_rix(ocelot,
-  QSYS_TAG_CONFIG_LINK_SPEED(speed),
+  QSYS_TAG_CONFIG_LINK_SPEED(tas_speed),
   QSYS_TAG_CONFIG_LINK_SPEED_M,
   QSYS_TAG_CONFIG, port);
 }
-- 
2.17.1



[net-next] net: dsa: felix: convert TAS link speed based on phylink speed

2020-09-22 Thread Xiaoliang Yang
state->speed holds a value of 10, 100, 1000 or 2500, but
QSYS_TAG_CONFIG_LINK_SPEED expects a value of 0, 1, 2, 3. So convert the
speed to a proper value.

Fixes: de143c0e274b ("net: dsa: felix: Configure Time-Aware Scheduler via
taprio offload")

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix_vsc9959.c | 22 +-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 79ddc4ba27a3..f584eababd0a 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -973,8 +973,28 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot)
 static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
u32 speed)
 {
+   u8 tas_speed;
+
+   switch (speed) {
+   case SPEED_10:
+   tas_speed = OCELOT_SPEED_10;
+   break;
+   case SPEED_100:
+   tas_speed = OCELOT_SPEED_100;
+   break;
+   case SPEED_1000:
+   tas_speed = OCELOT_SPEED_1000;
+   break;
+   case SPEED_2500:
+   tas_speed = OCELOT_SPEED_2500;
+   break;
+   default:
+   tas_speed = OCELOT_SPEED_1000;
+   break;
+   }
+
ocelot_rmw_rix(ocelot,
-  QSYS_TAG_CONFIG_LINK_SPEED(speed),
+  QSYS_TAG_CONFIG_LINK_SPEED(tas_speed),
   QSYS_TAG_CONFIG_LINK_SPEED_M,
   QSYS_TAG_CONFIG, port);
 }
-- 
2.17.1



RE: [EXT] Re: [PATCH v2 net-next 03/10] net: mscc: ocelot: allocated rules to different hardware VCAP TCAMs by chain index

2020-07-20 Thread Xiaoliang Yang

18.07.2020 3:10, Allan wrote:
>
> Okay - I will need to look deeper into to this to really understand the 
> consequences of mixing different types of filters. As far as Joergens example 
> goes, "matchall" is really the same as a flower without any matches.
>
> Long story short, to me the most important step here is that we come up with 
> a design where we can expose the 3 lookups in IS1 as separate chains, and 
> that we have something which behaves the same in HW and SW.
>
> Once we have that, we can add templates, shared blocks, shared actions etc. 
> in the future.
> 
> I know I have not been very active on this thread for the past couple of 
> days, but I'm certainly interesting in continue working/reviewing this.
> I will be OOO for the next 3 weeks, with very limited options for 
> reviewing/commenting on this, but after that I'm back again.
>
>/Allan
>

So chain template is used to configure key type on IS1, we can set one key type 
for each of the three lookups. In order to support all key types, we need to 
add half keys, full keys and quard keys support. If there is no template set, 
using a default "S1_7TUPLE" key type, which can cover most keys.

In general, using a default key type for each of the three lookups, and limited 
one action on one lookup chain, these can support three parallel lookup on IS1. 
Add PAG support as two lookups on IS2, then templates and shared blocks can be 
supported after that.

Thanks,
Xiaoliang


RE: [EXT] Re: [PATCH v2 net-next 03/10] net: mscc: ocelot: allocated rules to different hardware VCAP TCAMs by chain index

2020-07-16 Thread Xiaoliang Yang
Hi Joergen,


-Original Message-
From: Joergen Andreasen  
Sent: 2020年7月16日 16:51

> >> >> Chain 0:   The default chain - today this is in IS2. If we 
> >> >> proceed
> >> >> with this as is - then this will change.
> >> >> Chain 1-:  These are offloaded by "basic" classification.
> >> >> Chain 1-1: These are offloaded in IS1
> >> >> Chain 1: Lookup-0 in IS1, and here we could 
> >> >> limit the
> >> >>  action to do QoS related stuff 
> >> >> (priority
> >> >>  update)
> >> >> Chain 11000: Lookup-1 in IS1, here we could do VLAN
> >> >>  stuff
> >> >> Chain 12000: Lookup-2 in IS1, here we could apply 
> >> >> the
> >> >>  "PAG" which is essentially a GOTO.
> >> >>
> >> >> Chain 2-2: These are offloaded in IS2
> >> >> Chain 2-20255: Lookup-0 in IS2, where CHAIN-ID -
> >> >>2 is the PAG value.
> >> >> Chain 21000-21000: Lookup-1 in IS2.
> >> >>
> >> >> All these chains should be optional - users should only need to 
> >> >> configure the chains they need. To make this work, we need to 
> >> >> configure both the desired actions (could be priority update) and the 
> >> >> goto action.
> >> >> Remember in HW, all packets goes through this process, while in 
> >> >> SW they only follow the "goto" path.
> >> >>
>>
>> I agree with this chain assignment, following is an example to set rules:
>>
>> 1. Set a matchall rule for each chain, the last chain do not need goto chain 
>> action.
>> # tc filter add dev swp0 chain 0 flower skip_sw action goto chain 
>> 1 # tc filter add dev swp0 chain 1 flower skip_sw action goto 
>> chain 21000 In driver, use these rules to register the chain.
>>
>> 2. Set normal rules.
>> # tc filter add dev swp0 chain 1 protocol 802.1Q parent : 
>> flower skip_sw vlan_id 1 vlan_prio 1 action skbedit priority 1 action 
>> goto chain 21000 # tc filter add dev swp0 chain 21000 protocol 802.1Q 
>> parent : flower skip_sw vlan_id 1 vlan_prio 1 action drop
>>
>> In driver, we check if the chain ID has been registered, and goto chain is 
>> the same as first matchall rule, if is not, then return error. Each rule 
>> need has goto action except last chain.
>>
>> I also have check about chain template, it can not set an action template 
>> for each chain, so I think it's no use for our case. If this way to set 
>> rules is OK, I will update the patch to do as this.
>>
>> Thanks,
>> Xiaoliang Yang
>

> I agree that you cannot set an action template for each chain but you can set 
> a match template which for example can be used for setting up which IS1 key 
> to generate for the device/port.
> The template ensures that you cannot add an illegal match.
> I have attached a snippet from a testcase I wrote in order to test these 
> ideas.
> Note that not all actions are valid for the hardware.
>
> SMAC   = "00:00:00:11:11:11"
> DMAC   = "00:00:00:dd:dd:dd"
> VID1   = 0x10
> VID2   = 0x20
> PCP1   = 3
> PCP2   = 5
> DEI= 1
> SIP= "10.10.0.1"
> DIP= "10.10.0.2"
>
> IS1_L0 = 1 # IS1 lookup 0
> IS1_L1 = 11000 # IS1 lookup 1
> IS1_L2 = 12000 # IS1 lookup 2
>
> IS2_L0 = 2 # IS2 lookup 0 # IS2 2 - 20255 -> pag 0-255
> IS2_L0_P1  = 20001 # IS2 lookup 0 pag 1
> IS2_L0_P2  = 20002 # IS2 lookup 0 pag 2
>
> IS2_L1 = 21000 # IS2 lookup 1
>
> $skip = "skip_hw" # or "skip_sw"
>
> test "Chain templates and goto" do
> t_i "'prio #' sets the sequence of filters. Lowest number = highest 
> priority = checked first. 0..0x"
> t_i "'handle #' is a reference to the filter. Use this is if you need to 
> reference the filter later. 0..0x"
> t_i "'chain #' is the chain to use. Chain 0 is the default. Different 
> chains can have different templates. 0..0x"
> $ts.dut.run "tc qdisc add dev #{$dp[0]} clsact"
>
> t_i "Add templates"

RE: [EXT] Re: [PATCH v2 net-next 03/10] net: mscc: ocelot: allocated rules to different hardware VCAP TCAMs by chain index

2020-07-16 Thread Xiaoliang Yang
Hi Allan,

On 11.06.2002 2:18, Allan W. Nielsen  wrote:
>> >> Here is my initial suggestion for an alternative chain-schema:
>> >>
>> >> Chain 0:   The default chain - today this is in IS2. If we proceed
>> >> with this as is - then this will change.
>> >> Chain 1-:  These are offloaded by "basic" classification.
>> >> Chain 1-1: These are offloaded in IS1
>> >> Chain 1: Lookup-0 in IS1, and here we could limit 
>> >> the
>> >>  action to do QoS related stuff (priority
>> >>  update)
>> >> Chain 11000: Lookup-1 in IS1, here we could do VLAN
>> >>  stuff
>> >> Chain 12000: Lookup-2 in IS1, here we could apply the
>> >>  "PAG" which is essentially a GOTO.
>> >>
>> >> Chain 2-2: These are offloaded in IS2
>> >> Chain 2-20255: Lookup-0 in IS2, where CHAIN-ID -
>> >>2 is the PAG value.
>> >> Chain 21000-21000: Lookup-1 in IS2.
>> >>
>> >> All these chains should be optional - users should only need to 
>> >> configure the chains they need. To make this work, we need to 
>> >> configure both the desired actions (could be priority update) and the 
>> >> goto action.
>> >> Remember in HW, all packets goes through this process, while in SW 
>> >> they only follow the "goto" path.
>> >>

I agree with this chain assignment, following is an example to set rules:

1. Set a matchall rule for each chain, the last chain do not need goto chain 
action.
# tc filter add dev swp0 chain 0 flower skip_sw action goto chain 1
# tc filter add dev swp0 chain 1 flower skip_sw action goto chain 21000
In driver, use these rules to register the chain.

2. Set normal rules.
# tc filter add dev swp0 chain 1 protocol 802.1Q parent : flower 
skip_sw vlan_id 1 vlan_prio 1 action skbedit priority 1 action goto chain 21000
# tc filter add dev swp0 chain 21000 protocol 802.1Q parent : flower 
skip_sw vlan_id 1 vlan_prio 1 action drop

In driver, we check if the chain ID has been registered, and goto chain is the 
same as first matchall rule, if is not, then return error. Each rule need has 
goto action except last chain.

I also have check about chain template, it can not set an action template for 
each chain, so I think it's no use for our case. If this way to set rules is 
OK, I will update the patch to do as this.

Thanks,
Xiaoliang Yang



RE: [EXT] Re: [PATCH v2 net-next 00/10] net: ocelot: VCAP IS1 and ES0 support

2020-06-02 Thread Xiaoliang Yang
Hi Vladimir,

On Tus, 2 Jun 2020 at 16:04,
> First of all, net-next has just closed yesterday and will be closed for the 
> following 2 weeks:
> https://eur01.safelinks.protection.outlook.com/?url=http:%2F%2Fvger.kernel.org%2F~davem%2Fnet-next.htmldata=02%7C01%
>  
> 7Cxiaoliang.yang_1%40nxp.com%7C2fad4495dabc4f4ca5fd08d806cb70af%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637266818117666386sdata=ziVybWb4HzYXanehF5KwNv5RJL%2BZz6NeFvrZWg657B8%3Dreserved=0
>
> Secondly, could you give an example of how different chains could express the 
> fact that rules are executed in parallel between the IS1,
> IS2 and ES0 TCAMs?
>

Different TCAMs are not running in parallel, they have flow order: 
IS1->IS2->ES0. Using goto chain to express the flow order. 
For example:
tc qdisc add dev swp0 ingress
tc filter add dev swp0 chain 0 protocol 802.1Q parent : flower 
skip_sw vlan_id 1 vlan_prio 1 action vlan modify id 2 priority 2 action goto 
chain 1
tc filter add dev swp0 chain 1 protocol 802.1Q parent : flower 
skip_sw vlan_id 2 vlan_prio 2 action drop
In this example, package with (vid=1,pcp=1) vlan tag will be modified to 
(vid=2,pcp=2) vlan tag on IS1, then will be dropped on IS2.

If there is no rule match on IS1, it will still lookup on IS2. We can set a 
rule on chain 0 to express this:
tc filter add dev swp0 chain 0 parent : flower skip_sw action goto 
chain 1

In addition, VSC9959 chip has PSFP and "Sequence Generation recovery" modules 
are running after IS2, the flow order like this: IS1->IS2->PSFP-> "Sequence 
Generation recovery" ->ES0, we can also add chains like this to express these 
two modules in future.

BTW, where should I sent patches to due to net-next closed?

Thanks,
Xiaoliang Yang


[PATCH v2 net-next 03/10] net: mscc: ocelot: allocated rules to different hardware VCAP TCAMs by chain index

2020-06-01 Thread Xiaoliang Yang
There are three hardware TCAMs for ocelot chips: IS1, IS2 and ES0. Each
one supports different actions. The hardware flow order is: IS1->IS2->ES0.

This patch add three blocks to store rules according to chain index.
chain 0 is offloaded to IS1, chain 1 is offloaded to IS2, and egress chain
0 is offloaded to ES0.

Using action goto chain to express flow order as follows:
tc filter add dev swp0 chain 0 parent : flower skip_sw \
action goto chain 1

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/ethernet/mscc/ocelot_ace.c| 51 +++
 drivers/net/ethernet/mscc/ocelot_ace.h|  7 ++--
 drivers/net/ethernet/mscc/ocelot_flower.c | 46 +---
 include/soc/mscc/ocelot.h |  2 +-
 include/soc/mscc/ocelot_vcap.h|  4 +-
 5 files changed, 81 insertions(+), 29 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c 
b/drivers/net/ethernet/mscc/ocelot_ace.c
index 748c618db7d8..b76593b40097 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.c
+++ b/drivers/net/ethernet/mscc/ocelot_ace.c
@@ -341,6 +341,8 @@ static void is2_action_set(struct ocelot *ocelot, struct 
vcap_data *data,
vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_QU_NUM, 0);
vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_COPY_ENA, 0);
break;
+   default:
+   break;
}
 }
 
@@ -644,9 +646,9 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
 }
 
 static void vcap_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule,
-  int ix)
+  int ix, int block_id)
 {
-   const struct vcap_props *vcap = >vcap[VCAP_IS2];
+   const struct vcap_props *vcap = >vcap[block_id];
struct vcap_data data;
int row, count;
u32 cnt;
@@ -663,6 +665,19 @@ static void vcap_entry_get(struct ocelot *ocelot, struct 
ocelot_ace_rule *rule,
rule->stats.pkts = cnt;
 }
 
+static void vcap_entry_set(struct ocelot *ocelot, int ix,
+  struct ocelot_ace_rule *ace,
+  int block_id)
+{
+   switch (block_id) {
+   case VCAP_IS2:
+   is2_entry_set(ocelot, ix, ace);
+   break;
+   default:
+   break;
+   }
+}
+
 static void ocelot_ace_rule_add(struct ocelot *ocelot,
struct ocelot_acl_block *block,
struct ocelot_ace_rule *rule)
@@ -790,7 +805,7 @@ static bool ocelot_ace_is_problematic_non_mac_etype(struct 
ocelot_ace_rule *ace)
 static bool ocelot_exclusive_mac_etype_ace_rules(struct ocelot *ocelot,
 struct ocelot_ace_rule *ace)
 {
-   struct ocelot_acl_block *block = >acl_block;
+   struct ocelot_acl_block *block = >acl_block[VCAP_IS2];
struct ocelot_ace_rule *tmp;
unsigned long port;
int i;
@@ -824,15 +839,16 @@ static bool ocelot_exclusive_mac_etype_ace_rules(struct 
ocelot *ocelot,
return true;
 }
 
-int ocelot_ace_rule_offload_add(struct ocelot *ocelot,
+int ocelot_ace_rule_offload_add(struct ocelot *ocelot, int block_id,
struct ocelot_ace_rule *rule,
struct netlink_ext_ack *extack)
 {
-   struct ocelot_acl_block *block = >acl_block;
+   struct ocelot_acl_block *block = >acl_block[block_id];
struct ocelot_ace_rule *ace;
int i, index;
 
-   if (!ocelot_exclusive_mac_etype_ace_rules(ocelot, rule)) {
+   if (block_id == VCAP_IS2 &&
+   !ocelot_exclusive_mac_etype_ace_rules(ocelot, rule)) {
NL_SET_ERR_MSG_MOD(extack,
   "Cannot mix MAC_ETYPE with non-MAC_ETYPE 
rules");
return -EBUSY;
@@ -847,11 +863,11 @@ int ocelot_ace_rule_offload_add(struct ocelot *ocelot,
/* Move down the rules to make place for the new rule */
for (i = block->count - 1; i > index; i--) {
ace = ocelot_ace_rule_get_rule_index(block, i);
-   is2_entry_set(ocelot, i, ace);
+   vcap_entry_set(ocelot, i, ace, block_id);
}
 
/* Now insert the new rule */
-   is2_entry_set(ocelot, index, rule);
+   vcap_entry_set(ocelot, index, rule, block_id);
return 0;
 }
 
@@ -902,10 +918,10 @@ static void ocelot_ace_rule_del(struct ocelot *ocelot,
block->count--;
 }
 
-int ocelot_ace_rule_offload_del(struct ocelot *ocelot,
+int ocelot_ace_rule_offload_del(struct ocelot *ocelot, int block_id,
struct ocelot_ace_rule *rule)
 {
-   struct ocelot_acl_block *block = >acl_block;
+   struct ocelot_acl_block *block = >acl_block[block_id];
struct ocelot_ace_rule del_ace;
struct ocelot_ace_rule *ace;
int i, index;
@@ -921,29 +937,29 @@ int ocelot_ace_rule_offload_del(s

[PATCH v2 net-next 04/10] net: mscc: ocelot: change vcap to be compatible with full and quad entry

2020-06-01 Thread Xiaoliang Yang
When calculating vcap data offset, the function only supports half key
entry. This patch modify vcap_data_offset_get function to calculate a
correct data offset when setting VCAP Type-Group to VCAP_TG_FULL or
VCAP_TG_QUARTER.

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/ethernet/mscc/ocelot_ace.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c 
b/drivers/net/ethernet/mscc/ocelot_ace.c
index b76593b40097..8c384b0771bb 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.c
+++ b/drivers/net/ethernet/mscc/ocelot_ace.c
@@ -175,8 +175,8 @@ static void vcap_data_offset_get(const struct vcap_props 
*vcap,
u32 i, col, offset, count, cnt, base;
u32 width = vcap->tg_width;
 
-   count = (data->tg_sw == VCAP_TG_HALF ? 2 : 4);
-   col = (ix % 2);
+   count = (1 << (data->tg_sw - 1));
+   col = (ix % count);
cnt = (vcap->sw_count / count);
base = (vcap->sw_count - col * cnt - cnt);
data->tg_value = 0;
-- 
2.17.1



[PATCH v2 net-next 10/10] net: dsa: tag_ocelot: use VLAN information from tagging header when available

2020-06-01 Thread Xiaoliang Yang
From: Vladimir Oltean 

When the Extraction Frame Header contains a valid classified VLAN, use
that instead of the VLAN header present in the packet.

Signed-off-by: Vladimir Oltean 
---
 net/dsa/tag_ocelot.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/net/dsa/tag_ocelot.c b/net/dsa/tag_ocelot.c
index b0c98ee4e13b..253188b0e56b 100644
--- a/net/dsa/tag_ocelot.c
+++ b/net/dsa/tag_ocelot.c
@@ -181,9 +181,16 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
  struct net_device *netdev,
  struct packet_type *pt)
 {
+   struct dsa_port *cpu_dp = netdev->dsa_ptr;
+   struct dsa_switch *ds = cpu_dp->ds;
+   struct ocelot *ocelot = ds->priv;
+   struct ocelot_port *ocelot_port;
u64 src_port, qos_class;
u8 *start = skb->data;
+   struct ethhdr *hdr;
u8 *extraction;
+   u64 vlan_tci;
+   u16 vid;
 
/* Revert skb->data by the amount consumed by the DSA master,
 * so it points to the beginning of the frame.
@@ -211,6 +218,7 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
 
packing(extraction, _port,  46, 43, OCELOT_TAG_LEN, UNPACK, 0);
packing(extraction, _class, 19, 17, OCELOT_TAG_LEN, UNPACK, 0);
+   packing(extraction, _tci,  15,  0, OCELOT_TAG_LEN, UNPACK, 0);
 
skb->dev = dsa_master_find_slave(netdev, 0, src_port);
if (!skb->dev)
@@ -225,6 +233,27 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
skb->offload_fwd_mark = 1;
skb->priority = qos_class;
 
+   /* The VID from the extraction header contains the classified VLAN. But
+* if VLAN awareness is off and no retagging is done via VCAP IS1, that
+* classified VID will always be the pvid of the src_port.
+* port. We want Linux to see the classified VID, but only if the switch
+* intended to send the packet as untagged, i.e. if the VID is different
+* than the CPU port's untagged (native) VID.
+*/
+   vid = vlan_tci & VLAN_VID_MASK;
+   hdr = eth_hdr(skb);
+   ocelot_port = ocelot->ports[src_port];
+   if (hdr->h_proto == htons(ETH_P_8021Q) && vid != ocelot_port->pvid) {
+   u16 dummy_vlan_tci;
+
+   skb_push_rcsum(skb, ETH_HLEN);
+   __skb_vlan_pop(skb, _vlan_tci);
+   skb_pull_rcsum(skb, ETH_HLEN);
+   skb_reset_network_header(skb);
+   skb_reset_transport_header(skb);
+   __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
+   }
+
return skb;
 }
 
-- 
2.17.1



[PATCH v2 net-next 05/10] net: mscc: ocelot: VCAP IS1 support

2020-06-01 Thread Xiaoliang Yang
VCAP IS1 is a VCAP module which can filter MAC, IP, VLAN, protocol, and
TCP/UDP ports keys, and do Qos classified and VLAN retag actions.

This patch added VCAP IS1 support in ocelot ace driver, which can supports
vlan modify and skbedit priority action of tc filter.
Usage:
tc qdisc add dev swp0 ingress
tc filter add dev swp0 protocol 802.1Q parent : flower \
skip_sw vlan_id 1 vlan_prio 1 action vlan modify id 2 priority 2

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix_vsc9959.c| 102 +++
 drivers/net/ethernet/mscc/ocelot.c|   7 +
 drivers/net/ethernet/mscc/ocelot_ace.c| 198 +-
 drivers/net/ethernet/mscc/ocelot_ace.h|  11 ++
 drivers/net/ethernet/mscc/ocelot_flower.c |  11 ++
 drivers/net/ethernet/mscc/ocelot_regs.c   |   1 +
 include/soc/mscc/ocelot.h |   1 +
 include/soc/mscc/ocelot_vcap.h|  91 ++
 8 files changed, 421 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index ef3bf875e64c..f08a5f1c61a5 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -16,6 +16,8 @@
 #define VSC9959_VCAP_IS2_CNT   1024
 #define VSC9959_VCAP_IS2_ENTRY_WIDTH   376
 #define VSC9959_VCAP_PORT_CNT  6
+#define VSC9959_VCAP_IS1_CNT   256
+#define VSC9959_VCAP_IS1_ENTRY_WIDTH   376
 
 /* TODO: should find a better place for these */
 #define USXGMII_BMCR_RESET BIT(15)
@@ -337,6 +339,7 @@ static const u32 *vsc9959_regmap[] = {
[QSYS]  = vsc9959_qsys_regmap,
[REW]   = vsc9959_rew_regmap,
[SYS]   = vsc9959_sys_regmap,
+   [S1]= vsc9959_vcap_regmap,
[S2]= vsc9959_vcap_regmap,
[PTP]   = vsc9959_ptp_regmap,
[GCB]   = vsc9959_gcb_regmap,
@@ -369,6 +372,11 @@ static const struct resource vsc9959_target_io_res[] = {
.end= 0x001,
.name   = "sys",
},
+   [S1] = {
+   .start  = 0x005,
+   .end= 0x00503ff,
+   .name   = "s1",
+   },
[S2] = {
.start  = 0x006,
.end= 0x00603ff,
@@ -559,6 +567,80 @@ static const struct ocelot_stat_layout 
vsc9959_stats_layout[] = {
{ .offset = 0x111,  .name = "drop_green_prio_7", },
 };
 
+struct vcap_field vsc9959_vcap_is1_keys[] = {
+   [VCAP_IS1_HK_TYPE]  = {  0,   1},
+   [VCAP_IS1_HK_LOOKUP]= {  1,   2},
+   [VCAP_IS1_HK_IGR_PORT_MASK] = {  3,   7},
+   [VCAP_IS1_HK_RSV]   = { 10,   9},
+   [VCAP_IS1_HK_OAM_Y1731] = { 19,   1},
+   [VCAP_IS1_HK_L2_MC] = { 20,   1},
+   [VCAP_IS1_HK_L2_BC] = { 21,   1},
+   [VCAP_IS1_HK_IP_MC] = { 22,   1},
+   [VCAP_IS1_HK_VLAN_TAGGED]   = { 23,   1},
+   [VCAP_IS1_HK_VLAN_DBL_TAGGED]   = { 24,   1},
+   [VCAP_IS1_HK_TPID]  = { 25,   1},
+   [VCAP_IS1_HK_VID]   = { 26,  12},
+   [VCAP_IS1_HK_DEI]   = { 38,   1},
+   [VCAP_IS1_HK_PCP]   = { 39,   3},
+   /* Specific Fields for IS1 Half Key S1_NORMAL */
+   [VCAP_IS1_HK_L2_SMAC]   = { 42,  48},
+   [VCAP_IS1_HK_ETYPE_LEN] = { 90,   1},
+   [VCAP_IS1_HK_ETYPE] = { 91,  16},
+   [VCAP_IS1_HK_IP_SNAP]   = {107,   1},
+   [VCAP_IS1_HK_IP4]   = {108,   1},
+   /* Layer-3 Information */
+   [VCAP_IS1_HK_L3_FRAGMENT]   = {109,   1},
+   [VCAP_IS1_HK_L3_FRAG_OFS_GT0]   = {110,   1},
+   [VCAP_IS1_HK_L3_OPTIONS]= {111,   1},
+   [VCAP_IS1_HK_L3_DSCP]   = {112,   6},
+   [VCAP_IS1_HK_L3_IP4_SIP]= {118,  32},
+   /* Layer-4 Information */
+   [VCAP_IS1_HK_TCP_UDP]   = {150,   1},
+   [VCAP_IS1_HK_TCP]   = {151,   1},
+   [VCAP_IS1_HK_L4_SPORT]  = {152,  16},
+   [VCAP_IS1_HK_L4_RNG]= {168,   8},
+   /* Specific Fields for IS1 Half Key S1_5TUPLE_IP4 */
+   [VCAP_IS1_HK_IP4_INNER_TPID]= { 42,   1},
+   [VCAP_IS1_HK_IP4_INNER_VID] = { 43,  12},
+   [VCAP_IS1_HK_IP4_INNER_DEI] = { 55,   1},
+   [VCAP_IS1_HK_IP4_INNER_PCP] = { 56,   3},
+   [VCAP_IS1_HK_IP4_IP4]   = { 59,   1},
+   [VCAP_IS1_HK_IP4_L3_FRAGMENT]   = { 60,   1},
+   [VCAP_IS1_HK_IP4_L3_FRAG_OFS_GT0]   = { 61,   1},
+   [VCAP_IS1_HK_IP4_L3_OPTIONS]= { 62,   1},
+   [VCAP_IS1_HK_IP4_L3_DSCP]   = { 63,   6},
+

[PATCH v2 net-next 09/10] net: dsa: felix: correct VCAP IS2 keys offset

2020-06-01 Thread Xiaoliang Yang
Some of IS2 IP4_TCP_UDP keys are not correct, like L4_DPORT, L4_SPORT
and other L4 keys. It causes the issue that VCAP IS2 could not filter
a right dst/src port for TCP/UDP packages.

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix_vsc9959.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index fceba87509ba..539f3c062b50 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -730,17 +730,17 @@ struct vcap_field vsc9959_vcap_is2_keys[] = {
[VCAP_IS2_HK_DIP_EQ_SIP]= {118,   1},
/* IP4_TCP_UDP (TYPE=100) */
[VCAP_IS2_HK_TCP]   = {119,   1},
-   [VCAP_IS2_HK_L4_SPORT]  = {120,  16},
-   [VCAP_IS2_HK_L4_DPORT]  = {136,  16},
+   [VCAP_IS2_HK_L4_DPORT]  = {120,  16},
+   [VCAP_IS2_HK_L4_SPORT]  = {136,  16},
[VCAP_IS2_HK_L4_RNG]= {152,   8},
[VCAP_IS2_HK_L4_SPORT_EQ_DPORT] = {160,   1},
[VCAP_IS2_HK_L4_SEQUENCE_EQ0]   = {161,   1},
-   [VCAP_IS2_HK_L4_URG]= {162,   1},
-   [VCAP_IS2_HK_L4_ACK]= {163,   1},
-   [VCAP_IS2_HK_L4_PSH]= {164,   1},
-   [VCAP_IS2_HK_L4_RST]= {165,   1},
-   [VCAP_IS2_HK_L4_SYN]= {166,   1},
-   [VCAP_IS2_HK_L4_FIN]= {167,   1},
+   [VCAP_IS2_HK_L4_FIN]= {162,   1},
+   [VCAP_IS2_HK_L4_SYN]= {163,   1},
+   [VCAP_IS2_HK_L4_RST]= {164,   1},
+   [VCAP_IS2_HK_L4_PSH]= {165,   1},
+   [VCAP_IS2_HK_L4_ACK]= {166,   1},
+   [VCAP_IS2_HK_L4_URG]= {167,   1},
[VCAP_IS2_HK_L4_1588_DOM]   = {168,   8},
[VCAP_IS2_HK_L4_1588_VER]   = {176,   4},
/* IP4_OTHER (TYPE=101) */
-- 
2.17.1



[PATCH v2 net-next 08/10] net: ocelot: return error if rule is not found

2020-06-01 Thread Xiaoliang Yang
Return error if rule is not found in rule list to avoid Kernel panic.

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/ethernet/mscc/ocelot_ace.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c 
b/drivers/net/ethernet/mscc/ocelot_ace.c
index bf2b7a03c832..2ba2859fa2cd 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.c
+++ b/drivers/net/ethernet/mscc/ocelot_ace.c
@@ -982,9 +982,9 @@ static int ocelot_ace_rule_get_index_id(struct 
ocelot_acl_block *block,
list_for_each_entry(tmp, >rules, list) {
++index;
if (rule->id == tmp->id)
-   break;
+   return index;
}
-   return index;
+   return -ENOENT;
 }
 
 static struct ocelot_ace_rule*
@@ -1197,6 +1197,8 @@ int ocelot_ace_rule_offload_del(struct ocelot *ocelot, 
int block_id,
 
/* Gets index of the rule */
index = ocelot_ace_rule_get_index_id(block, rule);
+   if (index < 0)
+   return -ENOENT;
 
/* Delete rule */
ocelot_ace_rule_del(ocelot, block, rule);
@@ -1221,6 +1223,9 @@ int ocelot_ace_rule_stats_update(struct ocelot *ocelot, 
int block_id,
int index;
 
index = ocelot_ace_rule_get_index_id(block, rule);
+   if (index < 0)
+   return -ENOENT;
+
vcap_entry_get(ocelot, rule, index, block_id);
 
/* After we get the result we need to clear the counters */
-- 
2.17.1



[PATCH v2 net-next 07/10] net: mscc: ocelot: multiple actions support

2020-06-01 Thread Xiaoliang Yang
Support multiple actions for each flower rule, multiple actions can only
set on the same VCAP, and all actions can mix with action goto chain.
Action drop, trap, and police on VCAP IS2 could not be mixed.

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/ethernet/mscc/ocelot_ace.c| 15 +--
 drivers/net/ethernet/mscc/ocelot_ace.h|  8 +++-
 drivers/net/ethernet/mscc/ocelot_flower.c | 14 +-
 3 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c 
b/drivers/net/ethernet/mscc/ocelot_ace.c
index 76d679b8d15e..bf2b7a03c832 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.c
+++ b/drivers/net/ethernet/mscc/ocelot_ace.c
@@ -651,20 +651,23 @@ static void is1_action_set(struct ocelot *ocelot, struct 
vcap_data *data,
const struct vcap_props *vcap = >vcap[VCAP_IS1];
 
switch (ace->action) {
+   case OCELOT_ACL_ACTION_PRIORITY:
case OCELOT_ACL_ACTION_VLAN_MODIFY:
-   vcap_action_set(vcap, data, VCAP_IS1_ACT_VID_REPLACE_ENA, 1);
+   vcap_action_set(vcap, data, VCAP_IS1_ACT_VID_REPLACE_ENA,
+   ace->vlan_modify.ena);
vcap_action_set(vcap, data, VCAP_IS1_ACT_VID_ADD_VAL,
ace->vlan_modify.vid);
-   vcap_action_set(vcap, data, VCAP_IS1_ACT_PCP_DEI_ENA, 1);
+   vcap_action_set(vcap, data, VCAP_IS1_ACT_PCP_DEI_ENA,
+   ace->vlan_modify.ena);
vcap_action_set(vcap, data, VCAP_IS1_ACT_PCP_VAL,
ace->vlan_modify.pcp);
vcap_action_set(vcap, data, VCAP_IS1_ACT_DEI_VAL,
ace->vlan_modify.dei);
-   break;
-   case OCELOT_ACL_ACTION_PRIORITY:
-   vcap_action_set(vcap, data, VCAP_IS1_ACT_QOS_ENA, 1);
+
+   vcap_action_set(vcap, data, VCAP_IS1_ACT_QOS_ENA,
+   ace->qos_modify.ena);
vcap_action_set(vcap, data, VCAP_IS1_ACT_QOS_VAL,
-   ace->qos_val);
+   ace->qos_modify.qos_val);
break;
default:
break;
diff --git a/drivers/net/ethernet/mscc/ocelot_ace.h 
b/drivers/net/ethernet/mscc/ocelot_ace.h
index 70fe45d747fb..02fa81b3fe92 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.h
+++ b/drivers/net/ethernet/mscc/ocelot_ace.h
@@ -97,6 +97,12 @@ struct ocelot_ace_action_vlan {
u16 vid;
u8 pcp;
u8 dei;
+   u8 ena;
+};
+
+struct ocelot_ace_action_qos {
+   u8 qos_val;
+   u8 ena;
 };
 
 struct ocelot_ace_frame_etype {
@@ -212,6 +218,7 @@ struct ocelot_ace_rule {
enum ocelot_vcap_bit dmac_bc;
struct ocelot_ace_vlan vlan;
struct ocelot_ace_action_vlan vlan_modify;
+   struct ocelot_ace_action_qos qos_modify;
 
enum ocelot_ace_type type;
union {
@@ -225,7 +232,6 @@ struct ocelot_ace_rule {
} frame;
struct ocelot_policer pol;
u32 pol_ix;
-   u8 qos_val;
 };
 
 int ocelot_ace_rule_offload_add(struct ocelot *ocelot, int block_id,
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c 
b/drivers/net/ethernet/mscc/ocelot_flower.c
index d598e103c796..6ce37f152f12 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -32,9 +32,6 @@ static int ocelot_flower_parse_action(struct flow_cls_offload 
*f,
s64 burst;
u64 rate;
 
-   if (!flow_offload_has_one_action(>rule->action))
-   return -EOPNOTSUPP;
-
if (!flow_action_basic_hw_stats_check(>rule->action,
  f->common.extack))
return -EOPNOTSUPP;
@@ -42,14 +39,20 @@ static int ocelot_flower_parse_action(struct 
flow_cls_offload *f,
flow_action_for_each(i, a, >rule->action) {
switch (a->id) {
case FLOW_ACTION_DROP:
+   if (i)
+   return -EOPNOTSUPP;
ace->action = OCELOT_ACL_ACTION_DROP;
allowed_chain = 1;
break;
case FLOW_ACTION_TRAP:
+   if (i)
+   return -EOPNOTSUPP;
ace->action = OCELOT_ACL_ACTION_TRAP;
allowed_chain = 1;
break;
case FLOW_ACTION_POLICE:
+   if (i)
+   return -EOPNOTSUPP;
ace->action = OCELOT_ACL_ACTION_POLICE;
rate = a->police.rate_bytes_ps;
ace->pol.rate = div_u64(rate, 1000) * 8;
@@ -62,18 +65,19 @@ static int ocelot_flower_parse_action(struct 
flow_cls_offload *f,
 

[PATCH v2 net-next 06/10] net: mscc: ocelot: VCAP ES0 support

2020-06-01 Thread Xiaoliang Yang
VCAP ES0 is an egress VCAP working on all outgoing frames.
This patch added ES0 driver to support vlan push action of tc filter.
Usage:
tc filter add dev swp1 egress protocol 802.1Q flower skip_sw
vlan_id 1 vlan_prio 1 action vlan push id 2 priority 2

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix_vsc9959.c| 59 ++
 drivers/net/ethernet/mscc/ocelot.c|  4 ++
 drivers/net/ethernet/mscc/ocelot_ace.c| 74 ++-
 drivers/net/ethernet/mscc/ocelot_ace.h|  2 +
 drivers/net/ethernet/mscc/ocelot_flower.c | 29 ++---
 include/soc/mscc/ocelot.h |  1 +
 include/soc/mscc/ocelot_vcap.h| 42 +
 7 files changed, 203 insertions(+), 8 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index f08a5f1c61a5..fceba87509ba 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -18,6 +18,7 @@
 #define VSC9959_VCAP_PORT_CNT  6
 #define VSC9959_VCAP_IS1_CNT   256
 #define VSC9959_VCAP_IS1_ENTRY_WIDTH   376
+#define VSC9959_VCAP_ES0_CNT1024
 
 /* TODO: should find a better place for these */
 #define USXGMII_BMCR_RESET BIT(15)
@@ -339,6 +340,7 @@ static const u32 *vsc9959_regmap[] = {
[QSYS]  = vsc9959_qsys_regmap,
[REW]   = vsc9959_rew_regmap,
[SYS]   = vsc9959_sys_regmap,
+   [S0]= vsc9959_vcap_regmap,
[S1]= vsc9959_vcap_regmap,
[S2]= vsc9959_vcap_regmap,
[PTP]   = vsc9959_ptp_regmap,
@@ -372,6 +374,11 @@ static const struct resource vsc9959_target_io_res[] = {
.end= 0x001,
.name   = "sys",
},
+   [S0] = {
+   .start  = 0x004,
+   .end= 0x00403ff,
+   .name   = "s0",
+   },
[S1] = {
.start  = 0x005,
.end= 0x00503ff,
@@ -567,6 +574,38 @@ static const struct ocelot_stat_layout 
vsc9959_stats_layout[] = {
{ .offset = 0x111,  .name = "drop_green_prio_7", },
 };
 
+struct vcap_field vsc9959_vcap_es0_keys[] = {
+   [VCAP_ES0_EGR_PORT] = {  0,   3},
+   [VCAP_ES0_IGR_PORT] = {  3,   3},
+   [VCAP_ES0_RSV]  = {  6,   2},
+   [VCAP_ES0_L2_MC]= {  8,   1},
+   [VCAP_ES0_L2_BC]= {  9,   1},
+   [VCAP_ES0_VID]  = { 10,  12},
+   [VCAP_ES0_DP]   = { 22,   1},
+   [VCAP_ES0_PCP]  = { 23,   3},
+};
+
+struct vcap_field vsc9959_vcap_es0_actions[] = {
+   [VCAP_ES0_ACT_PUSH_OUTER_TAG]   = {  0,  2},
+   [VCAP_ES0_ACT_PUSH_INNER_TAG]   = {  2,  1},
+   [VCAP_ES0_ACT_TAG_A_TPID_SEL]   = {  3,  2},
+   [VCAP_ES0_ACT_TAG_A_VID_SEL]= {  5,  1},
+   [VCAP_ES0_ACT_TAG_A_PCP_SEL]= {  6,  2},
+   [VCAP_ES0_ACT_TAG_A_DEI_SEL]= {  8,  2},
+   [VCAP_ES0_ACT_TAG_B_TPID_SEL]   = { 10,  2},
+   [VCAP_ES0_ACT_TAG_B_VID_SEL]= { 12,  1},
+   [VCAP_ES0_ACT_TAG_B_PCP_SEL]= { 13,  2},
+   [VCAP_ES0_ACT_TAG_B_DEI_SEL]= { 15,  2},
+   [VCAP_ES0_ACT_VID_A_VAL]= { 17, 12},
+   [VCAP_ES0_ACT_PCP_A_VAL]= { 29,  3},
+   [VCAP_ES0_ACT_DEI_A_VAL]= { 32,  1},
+   [VCAP_ES0_ACT_VID_B_VAL]= { 33, 12},
+   [VCAP_ES0_ACT_PCP_B_VAL]= { 45,  3},
+   [VCAP_ES0_ACT_DEI_B_VAL]= { 48,  1},
+   [VCAP_ES0_ACT_RSV]  = { 49, 23},
+   [VCAP_ES0_ACT_HIT_STICKY]   = { 72,  1},
+};
+
 struct vcap_field vsc9959_vcap_is1_keys[] = {
[VCAP_IS1_HK_TYPE]  = {  0,   1},
[VCAP_IS1_HK_LOOKUP]= {  1,   2},
@@ -740,6 +779,26 @@ struct vcap_field vsc9959_vcap_is2_actions[] = {
 };
 
 static const struct vcap_props vsc9959_vcap_props[] = {
+   [VCAP_ES0] = {
+   .tg_width = 1,
+   .sw_count = 1,
+   .entry_count = VSC9959_VCAP_ES0_CNT,
+   .entry_width = 29,
+   .action_count = VSC9959_VCAP_ES0_CNT + 6,
+   .action_width = 72,
+   .action_type_width = 0,
+   .action_table = {
+   [ES0_ACTION_TYPE_NORMAL] = {
+   .width = 72,
+   .count = 1
+   },
+   },
+   .counter_words = 1,
+   .counter_width = 1,
+   .target = S0,
+   .keys = vsc9959_vcap_es0_keys,
+   .actions = vsc9959_vcap_es0_actions,
+   },
[VCAP_IS1] = {
.tg_width = 2,
 

[PATCH v2 net-next 02/10] net: mscc: ocelot: generalize existing code for VCAP

2020-06-01 Thread Xiaoliang Yang
From: Vladimir Oltean 

The Ocelot driver only supports VCAP IS2, the security enforcement block
which implements Access Control List actions (trap, drop, police).

In preparation of VCAP IS1 support, generalize the existing code to work
with any VCAP. In that direction, move all VCAP instantiation-specific
data to struct vcap_props, and pass that as an argument to each function
that does the key and action packing. Only the high-level functions need
to have access to ocelot->vcap[VCAP_IS2].

Signed-off-by: Vladimir Oltean 
Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix.c|   2 -
 drivers/net/dsa/ocelot/felix.h|   2 -
 drivers/net/dsa/ocelot/felix_vsc9959.c|  25 +-
 drivers/net/ethernet/mscc/ocelot_ace.c| 400 --
 drivers/net/ethernet/mscc/ocelot_board.c  |   5 +-
 drivers/net/ethernet/mscc/ocelot_flower.c |   1 +
 drivers/net/ethernet/mscc/ocelot_regs.c   |  20 +-
 drivers/net/ethernet/mscc/ocelot_s2.h |  64 
 include/soc/mscc/ocelot.h |  21 +-
 include/soc/mscc/ocelot_vcap.h|  62 
 10 files changed, 313 insertions(+), 289 deletions(-)
 delete mode 100644 drivers/net/ethernet/mscc/ocelot_s2.h

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index 66648986e6e3..4508d6063fd9 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -432,8 +432,6 @@ static int felix_init_structs(struct felix *felix, int 
num_phys_ports)
ocelot->num_stats   = felix->info->num_stats;
ocelot->shared_queue_sz = felix->info->shared_queue_sz;
ocelot->num_mact_rows   = felix->info->num_mact_rows;
-   ocelot->vcap_is2_keys   = felix->info->vcap_is2_keys;
-   ocelot->vcap_is2_actions= felix->info->vcap_is2_actions;
ocelot->vcap= felix->info->vcap;
ocelot->ops = felix->info->ops;
 
diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index a891736ca006..b1b6ecfa5a55 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -21,8 +21,6 @@ struct felix_info {
unsigned intnum_stats;
int num_ports;
int num_tx_queues;
-   struct vcap_field   *vcap_is2_keys;
-   struct vcap_field   *vcap_is2_actions;
const struct vcap_props *vcap;
int switch_pci_bar;
int imdio_pci_bar;
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 1dd9e348152d..ef3bf875e64c 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -156,14 +156,16 @@ static const u32 vsc9959_qs_regmap[] = {
REG_RESERVED(QS_INH_DBG),
 };
 
-static const u32 vsc9959_s2_regmap[] = {
-   REG(S2_CORE_UPDATE_CTRL,0x00),
-   REG(S2_CORE_MV_CFG, 0x04),
-   REG(S2_CACHE_ENTRY_DAT, 0x08),
-   REG(S2_CACHE_MASK_DAT,  0x000108),
-   REG(S2_CACHE_ACTION_DAT,0x000208),
-   REG(S2_CACHE_CNT_DAT,   0x000308),
-   REG(S2_CACHE_TG_DAT,0x000388),
+static const u32 vsc9959_vcap_regmap[] = {
+   /* VCAP_CORE_CFG */
+   REG(VCAP_CORE_UPDATE_CTRL,  0x00),
+   REG(VCAP_CORE_MV_CFG,   0x04),
+   /* VCAP_CORE_CACHE */
+   REG(VCAP_CACHE_ENTRY_DAT,   0x08),
+   REG(VCAP_CACHE_MASK_DAT,0x000108),
+   REG(VCAP_CACHE_ACTION_DAT,  0x000208),
+   REG(VCAP_CACHE_CNT_DAT, 0x000308),
+   REG(VCAP_CACHE_TG_DAT,  0x000388),
 };
 
 static const u32 vsc9959_qsys_regmap[] = {
@@ -335,7 +337,7 @@ static const u32 *vsc9959_regmap[] = {
[QSYS]  = vsc9959_qsys_regmap,
[REW]   = vsc9959_rew_regmap,
[SYS]   = vsc9959_sys_regmap,
-   [S2]= vsc9959_s2_regmap,
+   [S2]= vsc9959_vcap_regmap,
[PTP]   = vsc9959_ptp_regmap,
[GCB]   = vsc9959_gcb_regmap,
 };
@@ -677,6 +679,9 @@ static const struct vcap_props vsc9959_vcap_props[] = {
},
.counter_words = 4,
.counter_width = 32,
+   .target = S2,
+   .keys = vsc9959_vcap_is2_keys,
+   .actions = vsc9959_vcap_is2_actions,
},
 };
 
@@ -1401,8 +1406,6 @@ struct felix_info felix_info_vsc9959 = {
.ops= _ops,
.stats_layout   = vsc9959_stats_layout,
.num_stats  = ARRAY_SIZE(vsc9959_stats_layout),
-   .vcap_is2_keys  = vsc9959_vcap_is2_keys,
-   .vcap_is2_actions   = vsc9959_vcap_is2_actions,
.vca

[PATCH v2 net-next 01/10] net: mscc: ocelot: introduce a new ocelot_target_{read,write} API

2020-06-01 Thread Xiaoliang Yang
From: Vladimir Oltean 

There are some targets (register blocks) in the Ocelot switch that are
instantiated more than once. For example, the VCAP IS1, IS2 and ES0
blocks all share the same register layout for interacting with the cache
for the TCAM and the action RAM.

For the VCAPs, the procedure for servicing them is actually common. We
just need an API specifying which VCAP we are talking to, and we do that
via these raw ocelot_target_read and ocelot_target_write accessors.

In plain ocelot_read, the target is encoded into the register enum
itself:

u16 target = reg >> TARGET_OFFSET;

For the VCAPs, the registers are currently defined like this:

enum ocelot_reg {
[...]
S2_CORE_UPDATE_CTRL = S2 << TARGET_OFFSET,
S2_CORE_MV_CFG,
S2_CACHE_ENTRY_DAT,
S2_CACHE_MASK_DAT,
S2_CACHE_ACTION_DAT,
S2_CACHE_CNT_DAT,
S2_CACHE_TG_DAT,
[...]
};

which is precisely what we want to avoid, because we'd have to duplicate
the same register map for S1 and for S0, and then figure out how to pass
VCAP instance-specific registers to the ocelot_read calls (basically
another lookup table that undoes the effect of shifting with
TARGET_OFFSET).

So for some targets, propose a more raw API, similar to what is
currently done with ocelot_port_readl and ocelot_port_writel. Those
targets can only be accessed with ocelot_target_{read,write} and not
with ocelot_{read,write} after the conversion, which is fine.

The VCAP registers are not actually modified to use this new API as of
this patch. They will be modified in the next one.

Signed-off-by: Vladimir Oltean 
---
 drivers/net/ethernet/mscc/ocelot_io.c | 17 +
 include/soc/mscc/ocelot.h | 14 ++
 2 files changed, 31 insertions(+)

diff --git a/drivers/net/ethernet/mscc/ocelot_io.c 
b/drivers/net/ethernet/mscc/ocelot_io.c
index b229b1cb68ef..9b52d82f5399 100644
--- a/drivers/net/ethernet/mscc/ocelot_io.c
+++ b/drivers/net/ethernet/mscc/ocelot_io.c
@@ -59,6 +59,23 @@ void ocelot_port_writel(struct ocelot_port *port, u32 val, 
u32 reg)
 }
 EXPORT_SYMBOL(ocelot_port_writel);
 
+u32 __ocelot_target_read_ix(struct ocelot *ocelot, enum ocelot_target target,
+   u32 reg, u32 offset)
+{
+   u32 val;
+
+   regmap_read(ocelot->targets[target],
+   ocelot->map[target][reg] + offset, );
+   return val;
+}
+
+void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target,
+ u32 val, u32 reg, u32 offset)
+{
+   regmap_write(ocelot->targets[target],
+ocelot->map[target][reg] + offset, val);
+}
+
 int ocelot_regfields_init(struct ocelot *ocelot,
  const struct reg_field *const regfields)
 {
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 4953e9994df3..2ac08f3b8f68 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -578,6 +578,16 @@ struct ocelot_policer {
 #define ocelot_rmw_rix(ocelot, val, m, reg, ri) __ocelot_rmw_ix(ocelot, val, 
m, reg, reg##_RSZ * (ri))
 #define ocelot_rmw(ocelot, val, m, reg) __ocelot_rmw_ix(ocelot, val, m, reg, 0)
 
+#define ocelot_target_read_ix(ocelot, target, reg, gi, ri) 
__ocelot_target_read_ix(ocelot, target, reg, reg##_GSZ * (gi) + reg##_RSZ * 
(ri))
+#define ocelot_target_read_gix(ocelot, target, reg, gi) 
__ocelot_target_read_ix(ocelot, target, reg, reg##_GSZ * (gi))
+#define ocelot_target_read_rix(ocelot, target, reg, ri) 
__ocelot_target_read_ix(ocelot, target, reg, reg##_RSZ * (ri))
+#define ocelot_target_read(ocelot, target, reg) 
__ocelot_target_read_ix(ocelot, target, reg, 0)
+
+#define ocelot_target_write_ix(ocelot, target, val, reg, gi, ri) 
__ocelot_target_write_ix(ocelot, target, val, reg, reg##_GSZ * (gi) + reg##_RSZ 
* (ri))
+#define ocelot_target_write_gix(ocelot, target, val, reg, gi) 
__ocelot_target_write_ix(ocelot, target, val, reg, reg##_GSZ * (gi))
+#define ocelot_target_write_rix(ocelot, target, val, reg, ri) 
__ocelot_target_write_ix(ocelot, target, val, reg, reg##_RSZ * (ri))
+#define ocelot_target_write(ocelot, target, val, reg) 
__ocelot_target_write_ix(ocelot, target, val, reg, 0)
+
 /* I/O */
 u32 ocelot_port_readl(struct ocelot_port *port, u32 reg);
 void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg);
@@ -585,6 +595,10 @@ u32 __ocelot_read_ix(struct ocelot *ocelot, u32 reg, u32 
offset);
 void __ocelot_write_ix(struct ocelot *ocelot, u32 val, u32 reg, u32 offset);
 void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask, u32 reg,
 u32 offset);
+u32 __ocelot_target_read_ix(struct ocelot *ocelot, enum ocelot_target target,
+   u32 reg, u32 offset);
+void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target,
+ u32 val, u32 reg, u32 offset);
 
 /* Hardware 

[PATCH v2 net-next 00/10] net: ocelot: VCAP IS1 and ES0 support

2020-06-01 Thread Xiaoliang Yang
This series patches adds support for VCAP IS1 and ES0 module, each VCAP
correspond to a flow chain to offload.

VCAP IS1 supports FLOW_ACTION_VLAN_MANGLE action to filter MAC, IP,
VLAN, protocol, and TCP/UDP ports keys and retag vlian tag,
FLOW_ACTION_PRIORITY action to classify packages to different Qos in hw.

VCAP ES0 supports FLOW_ACTION_VLAN_PUSH action to filter vlan keys
and push a specific vlan tag to frames.

Changes since v1->v2:
 - Use different chain to assign rules to different hardware VCAP, and
   use action goto chain to express flow order.
 - Add FLOW_ACTION_PRIORITY to add Qos classification on VCAP IS1.
 - Multiple actions support.
 - Fix some code issues.

Vladimir Oltean (3):
  net: mscc: ocelot: introduce a new ocelot_target_{read,write} API
  net: mscc: ocelot: generalize existing code for VCAP
  net: dsa: tag_ocelot: use VLAN information from tagging header when
available

Xiaoliang Yang (7):
  net: mscc: ocelot: allocated rules to different hardware VCAP TCAMs by
chain index
  net: mscc: ocelot: change vcap to be compatible with full and quad
entry
  net: mscc: ocelot: VCAP IS1 support
  net: mscc: ocelot: VCAP ES0 support
  net: mscc: ocelot: multiple actions support
  net: ocelot: return error if rule is not found
  net: dsa: felix: correct VCAP IS2 keys offset

 drivers/net/dsa/ocelot/felix.c|   2 -
 drivers/net/dsa/ocelot/felix.h|   2 -
 drivers/net/dsa/ocelot/felix_vsc9959.c| 202 +-
 drivers/net/ethernet/mscc/ocelot.c|  11 +
 drivers/net/ethernet/mscc/ocelot_ace.c| 729 --
 drivers/net/ethernet/mscc/ocelot_ace.h|  26 +-
 drivers/net/ethernet/mscc/ocelot_board.c  |   5 +-
 drivers/net/ethernet/mscc/ocelot_flower.c |  95 ++-
 drivers/net/ethernet/mscc/ocelot_io.c |  17 +
 drivers/net/ethernet/mscc/ocelot_regs.c   |  21 +-
 drivers/net/ethernet/mscc/ocelot_s2.h |  64 --
 include/soc/mscc/ocelot.h |  39 +-
 include/soc/mscc/ocelot_vcap.h| 199 +-
 net/dsa/tag_ocelot.c  |  29 +
 14 files changed, 1105 insertions(+), 336 deletions(-)
 delete mode 100644 drivers/net/ethernet/mscc/ocelot_s2.h

-- 
2.17.1



[PATCH v2 net-next 1/3] net: dsa: felix: qos classified based on pcp

2020-05-12 Thread Xiaoliang Yang
Set the default QoS Classification based on PCP and DEI of vlan tag,
after that, frames can be Classified to different Qos based on PCP tag.
If there is no vlan tag or vlan ignored, use port default Qos.

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index a2dfd73f8a1a..58d6b0f454e5 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -289,6 +289,27 @@ static void felix_phylink_mac_link_up(struct dsa_switch 
*ds, int port,
 QSYS_SWITCH_PORT_MODE, port);
 }
 
+static void felix_port_qos_map_init(struct ocelot *ocelot, int port)
+{
+   int i;
+
+   ocelot_rmw_gix(ocelot,
+  ANA_PORT_QOS_CFG_QOS_PCP_ENA,
+  ANA_PORT_QOS_CFG_QOS_PCP_ENA,
+  ANA_PORT_QOS_CFG,
+  port);
+
+   for (i = 0; i < FELIX_NUM_TC * 2; i++) {
+   ocelot_rmw_ix(ocelot,
+ (ANA_PORT_PCP_DEI_MAP_DP_PCP_DEI_VAL & i) |
+ ANA_PORT_PCP_DEI_MAP_QOS_PCP_DEI_VAL(i),
+ ANA_PORT_PCP_DEI_MAP_DP_PCP_DEI_VAL |
+ ANA_PORT_PCP_DEI_MAP_QOS_PCP_DEI_VAL_M,
+ ANA_PORT_PCP_DEI_MAP,
+ port, i);
+   }
+}
+
 static void felix_get_strings(struct dsa_switch *ds, int port,
  u32 stringset, u8 *data)
 {
@@ -547,6 +568,11 @@ static int felix_setup(struct dsa_switch *ds)
ocelot_configure_cpu(ocelot, port,
 OCELOT_TAG_PREFIX_NONE,
 OCELOT_TAG_PREFIX_LONG);
+
+   /* Set the default QoS Classification based on PCP and DEI
+* bits of vlan tag.
+*/
+   felix_port_qos_map_init(ocelot, port);
}
 
/* Include the CPU port module in the forwarding mask for unknown
-- 
2.17.1



[PATCH v2 net-next 2/3] net: dsa: felix: Configure Time-Aware Scheduler via taprio offload

2020-05-12 Thread Xiaoliang Yang
Ocelot VSC9959 switch supports time-based egress shaping in hardware
according to IEEE 802.1Qbv. This patch add support for TAS configuration
on egress port of VSC9959 switch.

Felix driver is an instance of Ocelot family, with a DSA front-end. The
patch uses tc taprio hardware offload to setup TAS set function on felix
driver.

Signed-off-by: Xiaoliang Yang 
Reviewed-by: Vladimir Oltean 
---
 drivers/net/dsa/ocelot/felix.c |  19 
 drivers/net/dsa/ocelot/felix.h |   5 +
 drivers/net/dsa/ocelot/felix_vsc9959.c | 140 +
 3 files changed, 164 insertions(+)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index 58d6b0f454e5..d2b114c96952 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -237,6 +237,10 @@ static void felix_phylink_mac_config(struct dsa_switch 
*ds, int port,
 
if (felix->info->pcs_init)
felix->info->pcs_init(ocelot, port, link_an_mode, state);
+
+   if (felix->info->port_sched_speed_set)
+   felix->info->port_sched_speed_set(ocelot, port,
+ state->speed);
 }
 
 static void felix_phylink_mac_an_restart(struct dsa_switch *ds, int port)
@@ -730,6 +734,19 @@ static void felix_port_policer_del(struct dsa_switch *ds, 
int port)
ocelot_port_policer_del(ocelot, port);
 }
 
+static int felix_port_setup_tc(struct dsa_switch *ds, int port,
+  enum tc_setup_type type,
+  void *type_data)
+{
+   struct ocelot *ocelot = ds->priv;
+   struct felix *felix = ocelot_to_felix(ocelot);
+
+   if (felix->info->port_setup_tc)
+   return felix->info->port_setup_tc(ds, port, type, type_data);
+   else
+   return -EOPNOTSUPP;
+}
+
 static const struct dsa_switch_ops felix_switch_ops = {
.get_tag_protocol   = felix_get_tag_protocol,
.setup  = felix_setup,
@@ -768,6 +785,7 @@ static const struct dsa_switch_ops felix_switch_ops = {
.cls_flower_add = felix_cls_flower_add,
.cls_flower_del = felix_cls_flower_del,
.cls_flower_stats   = felix_cls_flower_stats,
+   .port_setup_tc  = felix_port_setup_tc,
 };
 
 static struct felix_info *felix_instance_tbl[] = {
@@ -856,6 +874,7 @@ static int felix_pci_probe(struct pci_dev *pdev,
 
ds->dev = >dev;
ds->num_ports = felix->info->num_ports;
+   ds->num_tx_queues = felix->info->num_tx_queues;
ds->ops = _switch_ops;
ds->priv = ocelot;
felix->ds = ds;
diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index b94386fa8d63..352f7b940af7 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -20,6 +20,7 @@ struct felix_info {
const struct ocelot_stat_layout *stats_layout;
unsigned intnum_stats;
int num_ports;
+   int num_tx_queues;
struct vcap_field   *vcap_is2_keys;
struct vcap_field   *vcap_is2_actions;
const struct vcap_props *vcap;
@@ -35,6 +36,10 @@ struct felix_info {
  struct phylink_link_state *state);
int (*prevalidate_phy_mode)(struct ocelot *ocelot, int port,
phy_interface_t phy_mode);
+   int (*port_setup_tc)(struct dsa_switch *ds, int port,
+enum tc_setup_type type, void *type_data);
+   void(*port_sched_speed_set)(struct ocelot *ocelot, int port,
+   u32 speed);
 };
 
 extern struct felix_info   felix_info_vsc9959;
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 1c56568d5aca..efdcc547e0c9 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -3,9 +3,12 @@
  * Copyright 2018-2019 NXP Semiconductors
  */
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include "felix.h"
@@ -27,6 +30,8 @@
 #define USXGMII_LPA_DUPLEX(lpa)(((lpa) & GENMASK(12, 12)) >> 
12)
 #define USXGMII_LPA_SPEED(lpa) (((lpa) & GENMASK(11, 9)) >> 9)
 
+#define VSC9959_TAS_GCL_ENTRY_MAX  63
+
 enum usxgmii_speed {
USXGMII_SPEED_10= 0,
USXGMII_SPEED_100   = 1,
@@ -1209,6 +1214,138 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot)
mdiobus_unregister(felix->imdio);
 }
 
+static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
+   u32 speed)
+{
+   ocelot_rmw_rix(ocelot,
+  QSYS_TAG_CONFIG_LINK_SPE

[PATCH v2 net-next 3/3] net: dsa: felix: add support Credit Based Shaper(CBS) for hardware offload

2020-05-12 Thread Xiaoliang Yang
VSC9959 hardware support the Credit Based Shaper(CBS) which part
of the IEEE-802.1Qav. This patch support sch_cbs set for VSC9959.

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix_vsc9959.c | 50 +-
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index efdcc547e0c9..df4498c0e864 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -207,7 +207,7 @@ static const u32 vsc9959_qsys_regmap[] = {
REG(QSYS_QMAXSDU_CFG_6, 0x00f62c),
REG(QSYS_QMAXSDU_CFG_7, 0x00f648),
REG(QSYS_PREEMPTION_CFG,0x00f664),
-   REG_RESERVED(QSYS_CIR_CFG),
+   REG(QSYS_CIR_CFG,   0x00),
REG(QSYS_EIR_CFG,   0x04),
REG(QSYS_SE_CFG,0x08),
REG(QSYS_SE_DWRR_CFG,   0x0c),
@@ -1332,6 +1332,52 @@ static int vsc9959_qos_port_tas_set(struct ocelot 
*ocelot, int port,
return ret;
 }
 
+static int vsc9959_qos_port_cbs_set(struct dsa_switch *ds, int port,
+   struct tc_cbs_qopt_offload *cbs_qopt)
+{
+   struct ocelot *ocelot = ds->priv;
+   int port_ix = port * 8 + cbs_qopt->queue;
+   u32 rate, burst;
+
+   if (cbs_qopt->queue >= ds->num_tx_queues)
+   return -EINVAL;
+
+   if (!cbs_qopt->enable) {
+   ocelot_write_gix(ocelot, QSYS_CIR_CFG_CIR_RATE(0) |
+QSYS_CIR_CFG_CIR_BURST(0),
+QSYS_CIR_CFG, port_ix);
+
+   ocelot_rmw_gix(ocelot, 0, QSYS_SE_CFG_SE_AVB_ENA,
+  QSYS_SE_CFG, port_ix);
+
+   return 0;
+   }
+
+   /* Rate unit is 100 kbps */
+   rate = DIV_ROUND_UP(cbs_qopt->idleslope, 100);
+   /* Avoid using zero rate */
+   rate = clamp_t(u32, rate, 1, GENMASK(14, 0));
+   /* Burst unit is 4kB */
+   burst = DIV_ROUND_UP(cbs_qopt->hicredit, 4096);
+   /* Avoid using zero burst size */
+   burst = clamp_t(u32, rate, 1, GENMASK(5, 0));
+   ocelot_write_gix(ocelot,
+QSYS_CIR_CFG_CIR_RATE(rate) |
+QSYS_CIR_CFG_CIR_BURST(burst),
+QSYS_CIR_CFG,
+port_ix);
+
+   ocelot_rmw_gix(ocelot,
+  QSYS_SE_CFG_SE_FRM_MODE(0) |
+  QSYS_SE_CFG_SE_AVB_ENA,
+  QSYS_SE_CFG_SE_AVB_ENA |
+  QSYS_SE_CFG_SE_FRM_MODE_M,
+  QSYS_SE_CFG,
+  port_ix);
+
+   return 0;
+}
+
 static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,
 enum tc_setup_type type,
 void *type_data)
@@ -1341,6 +1387,8 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, 
int port,
switch (type) {
case TC_SETUP_QDISC_TAPRIO:
return vsc9959_qos_port_tas_set(ocelot, port, type_data);
+   case TC_SETUP_QDISC_CBS:
+   return vsc9959_qos_port_cbs_set(ds, port, type_data);
default:
return -EOPNOTSUPP;
}
-- 
2.17.1



[PATCH v2 net-next 0/3] net: dsa: felix: tc taprio and CBS offload support

2020-05-12 Thread Xiaoliang Yang
This patch series support tc taprio and CBS hardware offload according
to IEEE 802.1Qbv and IEEE-802.1Qav on VSC9959.

v1->v2 changes:
 - Move port_qos_map_init() function to be common felix codes.
 - Keep const for dsa_switch_ops structs, add felix_port_setup_tc
   function to call port_setup_tc of felix.info.
 - fix code style for cbs_set, rename variables.

Xiaoliang Yang (3):
  net: dsa: felix: qos classified based on pcp
  net: dsa: felix: Configure Time-Aware Scheduler via taprio offload
  net: dsa: felix: add support Credit Based Shaper(CBS) for hardware
offload

 drivers/net/dsa/ocelot/felix.c |  45 ++
 drivers/net/dsa/ocelot/felix.h |   5 +
 drivers/net/dsa/ocelot/felix_vsc9959.c | 190 -
 3 files changed, 239 insertions(+), 1 deletion(-)

-- 
2.17.1



RE: [EXT] Re: [PATCH v1 net-next 3/3] net: dsa: felix: add support Credit Based Shaper(CBS) for hardware offload

2020-05-12 Thread Xiaoliang Yang
Hi Vinicius,


On Tue, 12 May 2020 9:42:23 Vinicius Costa Gomes wrote:
> > +
> > + /* Rate unit is 100 kbps */
> > + cir = DIV_ROUND_UP(cbs_qopt->idleslope, 100);
> > + cir = (cir ? cir : 1);
> > + cir = min_t(u32, GENMASK(14, 0), cir);
>
> Please rename 'cir' to "rate" or "idleslope".
>
> Also consider using clamp_t here and below (I just found out about it).
>
> > + /* Burst unit is 4kB */
> > + cbs = DIV_ROUND_UP(cbs_qopt->hicredit, 4096);
> > + /* Avoid using zero burst size */
> > + cbs = (cbs ? cbs : 1);
> > + cbs = min_t(u32, GENMASK(5, 0), cbs);
> 
> And please(!) rename 'cbs' to "burst" or "hicredit". Re-using the name "cbs" 
> with a completely different meaning here is confusing.
> 
I will update this, using clamp_t seems more concise in the codes.

Regards,
Xiaoliang


RE: [EXT] Re: [PATCH v1 net-next 3/3] net: dsa: felix: add support Credit Based Shaper(CBS) for hardware offload

2020-05-12 Thread Xiaoliang Yang
Hi Jakub,

On Mon, 11 May 2020 22:34:32 Jakub Kicinski  wrote:
> > +int vsc9959_qos_port_cbs_set(struct dsa_switch *ds, int port,
> > +  struct tc_cbs_qopt_offload *cbs_qopt)
>
> static

I will update this in v2, thanks.

Regards,
Xiaoliang Yang


RE: [EXT] Re: [PATCH v1 net-next 1/3] net: dsa: felix: qos classified based on pcp

2020-05-12 Thread Xiaoliang Yang
Hi Vladimir,

On Mon, 11 May 2020 at 08:19, Vladimir Oltean  wrote:
> 
> The new skbedit priority offload action looks interesting to me.
> But it also raises the question of what to do in the default case where such 
> rules are not installed. I think it is ok to support a
> 1-to-1 VLAN PCP to TC mapping by default? This should also be needed for 
> features such as Priority Flow Control.

skbedit priority offload seems only support port based prority set now, I 
haven't found how to set a priority for each port and QoS. So I set a 1-to-1 
VLAN PCP to TC mapping by default.

> Xiaoliang, just a small comment in case you need to resend.
> The felix->info structure is intended to hold SoC-specific data that 
> is likely to differ between chips (like for example if vsc7511 support 
> ever appears in felix). But I see ANA:PORT:QOS_CFG and 
> ANA:PORT:QOS_PCP_DEI_MAP_CFG are common registers, so are there any 
> specific reasons why you put this in felix_vsc9959 and not in the 
> common ocelot code?

All right, I have checked they are common registers, I will move 
port_qos_map_init() function to felix.c.

> > +   for (i = 0; i < FELIX_NUM_TC * 2; i++) {
> > +   ocelot_rmw_ix(ocelot,
> > + (ANA_PORT_PCP_DEI_MAP_DP_PCP_DEI_VAL & 
> > + i) |
> > +
> > ANA_PORT_PCP_DEI_MAP_QOS_PCP_DEI_VAL(i),
> > + ANA_PORT_PCP_DEI_MAP_DP_PCP_DEI_VAL |
> > + ANA_PORT_PCP_DEI_MAP_QOS_PCP_DEI_VAL_M,
> > + ANA_PORT_PCP_DEI_MAP,
> > + port, i);
> 
> ANA_PORT_PCP_DEI_MAP_DP_PCP_DEI_VAL is 1 bit. Are you sure this should be % i 
> and not % 2?

Because in QOS_PCP_DEI_MAP_CFG register, BIT(3) is DP value, BIT(2, 0) is QOS 
value. QoS class=QOS_PCP_DEI_MAP_CFG[i].QOS_PC
P_DEI_VAL, i=8*DEI + PCP, so DP value need to be set BIT(3)

Regards,
Xiaoliang Yang


[PATCH v1 net-next 0/3] net: dsa: felix: tc taprio and CBS offload support

2020-05-10 Thread Xiaoliang Yang
This patch series support tc taprio and CBS hardware offload according
to IEEE 802.1Qbv and IEEE-802.1Qav on VSC9959.

Xiaoliang Yang (3):
  net: dsa: felix: qos classified based on pcp
  net: dsa: felix: Configure Time-Aware Scheduler via taprio offload
  net: dsa: felix: add support Credit Based Shaper(CBS) for hardware
offload

 drivers/net/dsa/ocelot/felix.c |  16 +-
 drivers/net/dsa/ocelot/felix.h |   6 +
 drivers/net/dsa/ocelot/felix_vsc9959.c | 215 -
 3 files changed, 235 insertions(+), 2 deletions(-)

-- 
2.17.1



[PATCH v1 net-next 2/3] net: dsa: felix: Configure Time-Aware Scheduler via taprio offload

2020-05-10 Thread Xiaoliang Yang
Ocelot VSC9959 switch supports time-based egress shaping in hardware
according to IEEE 802.1Qbv. This patch add support for TAS configuration
on egress port of VSC9959 switch.

Felix driver is an instance of Ocelot family, with a DSA front-end. The
patch uses tc taprio hardware offload to setup TAS set function on felix
driver.

Signed-off-by: Xiaoliang Yang 
Reviewed-by: Vladimir Oltean 
---
 drivers/net/dsa/ocelot/felix.c |  10 +-
 drivers/net/dsa/ocelot/felix.h |   5 +
 drivers/net/dsa/ocelot/felix_vsc9959.c | 140 +
 3 files changed, 154 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index 0afdc6fc3f57..edd693d59b8e 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -237,6 +237,10 @@ static void felix_phylink_mac_config(struct dsa_switch 
*ds, int port,
 
if (felix->info->pcs_init)
felix->info->pcs_init(ocelot, port, link_an_mode, state);
+
+   if (felix->info->port_sched_speed_set)
+   felix->info->port_sched_speed_set(ocelot, port,
+ state->speed);
 }
 
 static void felix_phylink_mac_an_restart(struct dsa_switch *ds, int port)
@@ -710,7 +714,7 @@ static void felix_port_policer_del(struct dsa_switch *ds, 
int port)
ocelot_port_policer_del(ocelot, port);
 }
 
-static const struct dsa_switch_ops felix_switch_ops = {
+static struct dsa_switch_ops felix_switch_ops = {
.get_tag_protocol   = felix_get_tag_protocol,
.setup  = felix_setup,
.teardown   = felix_teardown,
@@ -827,6 +831,9 @@ static int felix_pci_probe(struct pci_dev *pdev,
 
ocelot->ptp = 1;
 
+   if (felix->info->port_setup_tc)
+   felix_switch_ops.port_setup_tc = felix->info->port_setup_tc;
+
ds = kzalloc(sizeof(struct dsa_switch), GFP_KERNEL);
if (!ds) {
err = -ENOMEM;
@@ -836,6 +843,7 @@ static int felix_pci_probe(struct pci_dev *pdev,
 
ds->dev = >dev;
ds->num_ports = felix->info->num_ports;
+   ds->num_tx_queues = felix->info->num_tx_queues;
ds->ops = _switch_ops;
ds->priv = ocelot;
felix->ds = ds;
diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index 0d4ec34309c7..24b13526fcf2 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -20,6 +20,7 @@ struct felix_info {
const struct ocelot_stat_layout *stats_layout;
unsigned intnum_stats;
int num_ports;
+   int num_tx_queues;
struct vcap_field   *vcap_is2_keys;
struct vcap_field   *vcap_is2_actions;
const struct vcap_props *vcap;
@@ -36,6 +37,10 @@ struct felix_info {
int (*prevalidate_phy_mode)(struct ocelot *ocelot, int port,
phy_interface_t phy_mode);
void(*port_qos_map_init)(struct ocelot *ocelot, int port);
+   int (*port_setup_tc)(struct dsa_switch *ds, int port,
+enum tc_setup_type type, void *type_data);
+   void(*port_sched_speed_set)(struct ocelot *ocelot, int port,
+   u32 speed);
 };
 
 extern struct felix_info   felix_info_vsc9959;
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 5c931fb3e4cd..ccbd875c7a47 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -3,10 +3,13 @@
  * Copyright 2018-2019 NXP Semiconductors
  */
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include "felix.h"
@@ -28,6 +31,8 @@
 #define USXGMII_LPA_DUPLEX(lpa)(((lpa) & GENMASK(12, 12)) >> 
12)
 #define USXGMII_LPA_SPEED(lpa) (((lpa) & GENMASK(11, 9)) >> 9)
 
+#define VSC9959_TAS_GCL_ENTRY_MAX  63
+
 enum usxgmii_speed {
USXGMII_SPEED_10= 0,
USXGMII_SPEED_100   = 1,
@@ -1231,6 +1236,138 @@ static void vsc9959_port_qos_map_init(struct ocelot 
*ocelot, int port)
}
 }
 
+static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
+   u32 speed)
+{
+   ocelot_rmw_rix(ocelot,
+  QSYS_TAG_CONFIG_LINK_SPEED(speed),
+  QSYS_TAG_CONFIG_LINK_SPEED_M,
+  QSYS_TAG_CONFIG, port);
+}
+
+static void vsc9959_new_base_time(struct ocelot *ocelot, ktime_t base_time,
+ u64 cycle_time,
+ struct timespec64 *new_base_ts)
+{
+   struct timespec64 ts;
+   ktime_t new_b

[PATCH v1 net-next 3/3] net: dsa: felix: add support Credit Based Shaper(CBS) for hardware offload

2020-05-10 Thread Xiaoliang Yang
VSC9959 hardware support the Credit Based Shaper(CBS) which part
of the IEEE-802.1Qav. This patch support sch_cbs set for VSC9959.

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix_vsc9959.c | 52 +-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index ccbd875c7a47..d8d1657ee8ba 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -208,7 +208,7 @@ static const u32 vsc9959_qsys_regmap[] = {
REG(QSYS_QMAXSDU_CFG_6, 0x00f62c),
REG(QSYS_QMAXSDU_CFG_7, 0x00f648),
REG(QSYS_PREEMPTION_CFG,0x00f664),
-   REG_RESERVED(QSYS_CIR_CFG),
+   REG(QSYS_CIR_CFG,   0x00),
REG(QSYS_EIR_CFG,   0x04),
REG(QSYS_SE_CFG,0x08),
REG(QSYS_SE_DWRR_CFG,   0x0c),
@@ -1354,6 +1354,54 @@ static int vsc9959_qos_port_tas_set(struct ocelot 
*ocelot, int port,
return ret;
 }
 
+int vsc9959_qos_port_cbs_set(struct dsa_switch *ds, int port,
+struct tc_cbs_qopt_offload *cbs_qopt)
+{
+   struct ocelot *ocelot = ds->priv;
+   int port_ix = port * 8 + cbs_qopt->queue;
+   u32 cbs = 0;
+   u32 cir = 0;
+
+   if (cbs_qopt->queue >= ds->num_tx_queues)
+   return -EINVAL;
+
+   if (!cbs_qopt->enable) {
+   ocelot_write_gix(ocelot, QSYS_CIR_CFG_CIR_RATE(0) |
+QSYS_CIR_CFG_CIR_BURST(0),
+QSYS_CIR_CFG, port_ix);
+
+   ocelot_rmw_gix(ocelot, 0, QSYS_SE_CFG_SE_AVB_ENA,
+  QSYS_SE_CFG, port_ix);
+
+   return 0;
+   }
+
+   /* Rate unit is 100 kbps */
+   cir = DIV_ROUND_UP(cbs_qopt->idleslope, 100);
+   cir = (cir ? cir : 1);
+   cir = min_t(u32, GENMASK(14, 0), cir);
+   /* Burst unit is 4kB */
+   cbs = DIV_ROUND_UP(cbs_qopt->hicredit, 4096);
+   /* Avoid using zero burst size */
+   cbs = (cbs ? cbs : 1);
+   cbs = min_t(u32, GENMASK(5, 0), cbs);
+   ocelot_write_gix(ocelot,
+QSYS_CIR_CFG_CIR_RATE(cir) |
+QSYS_CIR_CFG_CIR_BURST(cbs),
+QSYS_CIR_CFG,
+port_ix);
+
+   ocelot_rmw_gix(ocelot,
+  QSYS_SE_CFG_SE_FRM_MODE(0) |
+  QSYS_SE_CFG_SE_AVB_ENA,
+  QSYS_SE_CFG_SE_AVB_ENA |
+  QSYS_SE_CFG_SE_FRM_MODE_M,
+  QSYS_SE_CFG,
+  port_ix);
+
+   return 0;
+}
+
 static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,
 enum tc_setup_type type,
 void *type_data)
@@ -1363,6 +1411,8 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, 
int port,
switch (type) {
case TC_SETUP_QDISC_TAPRIO:
return vsc9959_qos_port_tas_set(ocelot, port, type_data);
+   case TC_SETUP_QDISC_CBS:
+   return vsc9959_qos_port_cbs_set(ds, port, type_data);
default:
return -EOPNOTSUPP;
}
-- 
2.17.1



[PATCH v1 net-next 1/3] net: dsa: felix: qos classified based on pcp

2020-05-10 Thread Xiaoliang Yang
Set the default QoS Classification based on PCP and DEI of vlan tag,
after that, frames can be Classified to different Qos based on PCP tag.
If there is no vlan tag or vlan ignored, use port default Qos.

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix.c |  6 ++
 drivers/net/dsa/ocelot/felix.h |  1 +
 drivers/net/dsa/ocelot/felix_vsc9959.c | 23 +++
 3 files changed, 30 insertions(+)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index a2dfd73f8a1a..0afdc6fc3f57 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -547,6 +547,12 @@ static int felix_setup(struct dsa_switch *ds)
ocelot_configure_cpu(ocelot, port,
 OCELOT_TAG_PREFIX_NONE,
 OCELOT_TAG_PREFIX_LONG);
+
+   /* Set the default QoS Classification based on PCP and DEI
+* bits of vlan tag.
+*/
+   if (felix->info->port_qos_map_init)
+   felix->info->port_qos_map_init(ocelot, port);
}
 
/* Include the CPU port module in the forwarding mask for unknown
diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index b94386fa8d63..0d4ec34309c7 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -35,6 +35,7 @@ struct felix_info {
  struct phylink_link_state *state);
int (*prevalidate_phy_mode)(struct ocelot *ocelot, int port,
phy_interface_t phy_mode);
+   void(*port_qos_map_init)(struct ocelot *ocelot, int port);
 };
 
 extern struct felix_info   felix_info_vsc9959;
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 1c56568d5aca..5c931fb3e4cd 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -4,6 +4,7 @@
  */
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1209,6 +1210,27 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot)
mdiobus_unregister(felix->imdio);
 }
 
+static void vsc9959_port_qos_map_init(struct ocelot *ocelot, int port)
+{
+   int i;
+
+   ocelot_rmw_gix(ocelot,
+  ANA_PORT_QOS_CFG_QOS_PCP_ENA,
+  ANA_PORT_QOS_CFG_QOS_PCP_ENA,
+  ANA_PORT_QOS_CFG,
+  port);
+
+   for (i = 0; i < FELIX_NUM_TC * 2; i++) {
+   ocelot_rmw_ix(ocelot,
+ (ANA_PORT_PCP_DEI_MAP_DP_PCP_DEI_VAL & i) |
+ ANA_PORT_PCP_DEI_MAP_QOS_PCP_DEI_VAL(i),
+ ANA_PORT_PCP_DEI_MAP_DP_PCP_DEI_VAL |
+ ANA_PORT_PCP_DEI_MAP_QOS_PCP_DEI_VAL_M,
+ ANA_PORT_PCP_DEI_MAP,
+ port, i);
+   }
+}
+
 struct felix_info felix_info_vsc9959 = {
.target_io_res  = vsc9959_target_io_res,
.port_io_res= vsc9959_port_io_res,
@@ -1232,4 +1254,5 @@ struct felix_info felix_info_vsc9959 = {
.pcs_an_restart = vsc9959_pcs_an_restart,
.pcs_link_state = vsc9959_pcs_link_state,
.prevalidate_phy_mode   = vsc9959_prevalidate_phy_mode,
+   .port_qos_map_init  = vsc9959_port_qos_map_init,
 };
-- 
2.17.1



RE: [EXT] Re: [PATCH v1 net-next 4/6] net: mscc: ocelot: VCAP IS1 support

2020-05-07 Thread Xiaoliang Yang
Hi Allan,


> Hi Vladimir,
> 
> On 06.05.2020 13:53, Vladimir Oltean wrote:
[snip]
> >At the moment, the driver does not support more than 1 action. We might 
> >need to change that, but we can still install more filters with the 
> >same key and still be fine (see more below). When there is more than 1 
> >action, the IS1 stuff will be combined into a single rule programmed 
> >into IS1, and the IS2 stuff will be combined into a single new rule 
> >with the same keys installed into VCAP IS2. Would that not work?
> >
> >> The SW model have these two rules in the same table, and can stop 
> >> process at the first match. SW will do the action of the first frame 
> >> matching.
> >>
> >
> >Actually I think this is an incorrect assumption - software stops at 
> >the first action only if told to do so. Let me copy-paste a text from a 
> >different email thread.
> 
> I'm still not able to see how this proposal will give us the same behavioral 
> in SW and in HW.
> 
> A simple example:
> 
> tc qdisc add dev enp0s3 ingress
> tc filter add dev enp0s3 protocol 802.1Q parent : \
>  prio 10 flower vlan_id 5 action vlan modify id 10 tc filter add dev 
> enp0s3 protocol 802.1Q parent : \
>  prio 20 flower src_mac 00:00:00:00:00:08 action drop
> 
> We can then inject a frame with VID 5 and smac ::08:
> $ ef tx tap0 eth smac 00:00:00:00:00:08 ctag vid 5
> 
> We can then check the filter and see that it only hit the first rule:
> 
> $ tc -s filter show dev enp0s3 ingress
> filter protocol 802.1Q pref 10 flower chain 0 filter protocol 802.1Q pref 10 
> flower chain 0 handle 0x1
>vlan_id 5
>not_in_hw
>  action order 1: vlan  modify id 10 protocol 802.1Q priority 0 pipe
>   index 1 ref 1 bind 1 installed 19 sec used 6 sec
>  Action statistics:
>  Sent 42 bytes 1 pkt (dropped 0, overlimits 0 requeues 0)
>  backlog 0b 0p requeues 0
>
> filter protocol 802.1Q pref 20 flower chain 0 filter protocol 802.1Q pref 20 
> flower chain 0 handle 0x1
>   src_mac 00:00:00:00:00:08
>   not_in_hw
> action order 1: gact action drop
>  random type none pass val 0
>  index 1 ref 1 bind 1 installed 11 sec used 11 sec
> Action statistics:
> Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> backlog 0b 0p requeues 0
>
> If this was done with the proposed HW offload, then both rules would have 
> been hit and we would have a different behavioral.
>
> This can be fixed by adding the "continue" action to the first rule:

> tc filter add dev enp0s3 protocol 802.1Q parent : \
>  prio 10 flower vlan_id 5 action vlan modify id 10 continue tc filter add 
> dev enp0s3 protocol 802.1Q parent : \
>  prio 20 flower src_mac 00:00:00:00:00:08 action drop
>
> But that would again break if we add 2 rules manipulating the VLAN (as the HW 
> does not continue with in a single TCAM).
>
> My point is: I do not think we can hide the fact that this is done in 
> independent TCAMs in the silicon.
> 
> I think it is possible to do this with the chain feature (even though it is 
> not a perfect match), but it would require more analysis.
> 
> /Allan

Do you mean it's better to set vlan modify filters in a different chain, and 
write the filter entries with a same chain in the same VCAP TCAM?
For example:
tc filter add dev enp0s3 protocol 802.1Q chain 11 parent : prio 10 
flower skip_sw vlan_id 5 action vlan modify id 10
tc filter add dev enp0s3 protocol 802.1Q chain 22 parent : prio 20 
flower skip_sw src_mac 00:00:00:00:00:08 action drop
for this usage, we only need to ensure a chain corresponding to a VCAP in 
ocelot ace driver. I'm not sure is my understanding right?

regards,
Xiaoliang


[PATCH v1 net-next 4/6] net: mscc: ocelot: VCAP IS1 support

2020-05-06 Thread Xiaoliang Yang
VCAP IS1 is a VCAP module which can filter MAC, IP, VLAN, protocol, and
TCP/UDP ports keys, and do Qos and VLAN retag actions.
This patch added VCAP IS1 support in ocelot ace driver, which can supports
vlan modify action of tc filter.
Usage:
tc qdisc add dev swp0 ingress
tc filter add dev swp0 protocol 802.1Q parent : flower \
skip_sw vlan_id 1 vlan_prio 1 action vlan modify id 2 priority 2

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix_vsc9959.c| 102 +++
 drivers/net/ethernet/mscc/ocelot.c|   7 +
 drivers/net/ethernet/mscc/ocelot_ace.c| 198 +-
 drivers/net/ethernet/mscc/ocelot_ace.h|   9 +
 drivers/net/ethernet/mscc/ocelot_flower.c |   6 +
 drivers/net/ethernet/mscc/ocelot_regs.c   |   1 +
 include/soc/mscc/ocelot.h |   1 +
 include/soc/mscc/ocelot_vcap.h|  93 +-
 8 files changed, 415 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 3b37c5f41fca..1f5edabf5fd2 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -13,6 +13,8 @@
 #define VSC9959_VCAP_IS2_CNT   1024
 #define VSC9959_VCAP_IS2_ENTRY_WIDTH   376
 #define VSC9959_VCAP_PORT_CNT  6
+#define VSC9959_VCAP_IS1_CNT   256
+#define VSC9959_VCAP_IS1_ENTRY_WIDTH   376
 
 /* TODO: should find a better place for these */
 #define USXGMII_BMCR_RESET BIT(15)
@@ -332,6 +334,7 @@ static const u32 *vsc9959_regmap[] = {
[QSYS]  = vsc9959_qsys_regmap,
[REW]   = vsc9959_rew_regmap,
[SYS]   = vsc9959_sys_regmap,
+   [S1]= vsc9959_vcap_regmap,
[S2]= vsc9959_vcap_regmap,
[PTP]   = vsc9959_ptp_regmap,
[GCB]   = vsc9959_gcb_regmap,
@@ -366,6 +369,11 @@ static struct resource vsc9959_target_io_res[] = {
.end= 0x001,
.name   = "sys",
},
+   [S1] = {
+   .start  = 0x005,
+   .end= 0x00503ff,
+   .name   = "s1",
+   },
[S2] = {
.start  = 0x006,
.end= 0x00603ff,
@@ -556,6 +564,80 @@ static const struct ocelot_stat_layout 
vsc9959_stats_layout[] = {
{ .offset = 0x111,  .name = "drop_green_prio_7", },
 };
 
+struct vcap_field vsc9959_vcap_is1_keys[] = {
+   [VCAP_IS1_HK_TYPE]  = {  0,   1},
+   [VCAP_IS1_HK_LOOKUP]= {  1,   2},
+   [VCAP_IS1_HK_IGR_PORT_MASK] = {  3,   7},
+   [VCAP_IS1_HK_RSV]   = { 10,   9},
+   [VCAP_IS1_HK_OAM_Y1731] = { 19,   1},
+   [VCAP_IS1_HK_L2_MC] = { 20,   1},
+   [VCAP_IS1_HK_L2_BC] = { 21,   1},
+   [VCAP_IS1_HK_IP_MC] = { 22,   1},
+   [VCAP_IS1_HK_VLAN_TAGGED]   = { 23,   1},
+   [VCAP_IS1_HK_VLAN_DBL_TAGGED]   = { 24,   1},
+   [VCAP_IS1_HK_TPID]  = { 25,   1},
+   [VCAP_IS1_HK_VID]   = { 26,  12},
+   [VCAP_IS1_HK_DEI]   = { 38,   1},
+   [VCAP_IS1_HK_PCP]   = { 39,   3},
+   /* Specific Fields for IS1 Half Key S1_NORMAL */
+   [VCAP_IS1_HK_L2_SMAC]   = { 42,  48},
+   [VCAP_IS1_HK_ETYPE_LEN] = { 90,   1},
+   [VCAP_IS1_HK_ETYPE] = { 91,  16},
+   [VCAP_IS1_HK_IP_SNAP]   = {107,   1},
+   [VCAP_IS1_HK_IP4]   = {108,   1},
+   /* Layer-3 Information */
+   [VCAP_IS1_HK_L3_FRAGMENT]   = {109,   1},
+   [VCAP_IS1_HK_L3_FRAG_OFS_GT0]   = {110,   1},
+   [VCAP_IS1_HK_L3_OPTIONS]= {111,   1},
+   [VCAP_IS1_HK_L3_DSCP]   = {112,   6},
+   [VCAP_IS1_HK_L3_IP4_SIP]= {118,  32},
+   /* Layer-4 Information */
+   [VCAP_IS1_HK_TCP_UDP]   = {150,   1},
+   [VCAP_IS1_HK_TCP]   = {151,   1},
+   [VCAP_IS1_HK_L4_SPORT]  = {152,  16},
+   [VCAP_IS1_HK_L4_RNG]= {168,   8},
+   /* Specific Fields for IS1 Half Key S1_5TUPLE_IP4 */
+   [VCAP_IS1_HK_IP4_INNER_TPID]= { 42,   1},
+   [VCAP_IS1_HK_IP4_INNER_VID] = { 43,  12},
+   [VCAP_IS1_HK_IP4_INNER_DEI] = { 55,   1},
+   [VCAP_IS1_HK_IP4_INNER_PCP] = { 56,   3},
+   [VCAP_IS1_HK_IP4_IP4]   = { 59,   1},
+   [VCAP_IS1_HK_IP4_L3_FRAGMENT]   = { 60,   1},
+   [VCAP_IS1_HK_IP4_L3_FRAG_OFS_GT0]   = { 61,   1},
+   [VCAP_IS1_HK_IP4_L3_OPTIONS]= { 62,   1},
+   [VCAP_IS1_HK_IP4_L3_DSCP]   = { 63,   6},
+   [VCAP_IS1_HK_IP4_L3_I

[PATCH v1 net-next 5/6] net: mscc: ocelot: VCAP ES0 support

2020-05-06 Thread Xiaoliang Yang
VCAP ES0 is an egress VCAP working on all outgoing frames.
This patch added ES0 driver to support vlan push action of tc filter.
Usage:
tc filter add dev swp1 egress protocol 802.1Q flower skip_sw
vlan_id 1 vlan_prio 1 action vlan push id 2 priority 2

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix_vsc9959.c| 59 ++
 drivers/net/ethernet/mscc/ocelot.c|  3 +
 drivers/net/ethernet/mscc/ocelot_ace.c| 73 ++-
 drivers/net/ethernet/mscc/ocelot_ace.h|  2 +
 drivers/net/ethernet/mscc/ocelot_flower.c | 23 ++-
 include/soc/mscc/ocelot.h |  1 +
 include/soc/mscc/ocelot_vcap.h| 44 +-
 7 files changed, 200 insertions(+), 5 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 1f5edabf5fd2..ee3b1b2974a0 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -15,6 +15,7 @@
 #define VSC9959_VCAP_PORT_CNT  6
 #define VSC9959_VCAP_IS1_CNT   256
 #define VSC9959_VCAP_IS1_ENTRY_WIDTH   376
+#define VSC9959_VCAP_ES0_CNT1024
 
 /* TODO: should find a better place for these */
 #define USXGMII_BMCR_RESET BIT(15)
@@ -334,6 +335,7 @@ static const u32 *vsc9959_regmap[] = {
[QSYS]  = vsc9959_qsys_regmap,
[REW]   = vsc9959_rew_regmap,
[SYS]   = vsc9959_sys_regmap,
+   [S0]= vsc9959_vcap_regmap,
[S1]= vsc9959_vcap_regmap,
[S2]= vsc9959_vcap_regmap,
[PTP]   = vsc9959_ptp_regmap,
@@ -369,6 +371,11 @@ static struct resource vsc9959_target_io_res[] = {
.end= 0x001,
.name   = "sys",
},
+   [S0] = {
+   .start  = 0x004,
+   .end= 0x00403ff,
+   .name   = "s0",
+   },
[S1] = {
.start  = 0x005,
.end= 0x00503ff,
@@ -564,6 +571,38 @@ static const struct ocelot_stat_layout 
vsc9959_stats_layout[] = {
{ .offset = 0x111,  .name = "drop_green_prio_7", },
 };
 
+struct vcap_field vsc9959_vcap_es0_keys[] = {
+   [VCAP_ES0_EGR_PORT] = {  0,   3},
+   [VCAP_ES0_IGR_PORT] = {  3,   3},
+   [VCAP_ES0_RSV]  = {  6,   2},
+   [VCAP_ES0_L2_MC]= {  8,   1},
+   [VCAP_ES0_L2_BC]= {  9,   1},
+   [VCAP_ES0_VID]  = { 10,  12},
+   [VCAP_ES0_DP]   = { 22,   1},
+   [VCAP_ES0_PCP]  = { 23,   3},
+};
+
+struct vcap_field vsc9959_vcap_es0_actions[] = {
+   [VCAP_ES0_ACT_PUSH_OUTER_TAG]   = {  0,  2},
+   [VCAP_ES0_ACT_PUSH_INNER_TAG]   = {  2,  1},
+   [VCAP_ES0_ACT_TAG_A_TPID_SEL]   = {  3,  2},
+   [VCAP_ES0_ACT_TAG_A_VID_SEL]= {  5,  1},
+   [VCAP_ES0_ACT_TAG_A_PCP_SEL]= {  6,  2},
+   [VCAP_ES0_ACT_TAG_A_DEI_SEL]= {  8,  2},
+   [VCAP_ES0_ACT_TAG_B_TPID_SEL]   = { 10,  2},
+   [VCAP_ES0_ACT_TAG_B_VID_SEL]= { 12,  1},
+   [VCAP_ES0_ACT_TAG_B_PCP_SEL]= { 13,  2},
+   [VCAP_ES0_ACT_TAG_B_DEI_SEL]= { 15,  2},
+   [VCAP_ES0_ACT_VID_A_VAL]= { 17, 12},
+   [VCAP_ES0_ACT_PCP_A_VAL]= { 29,  3},
+   [VCAP_ES0_ACT_DEI_A_VAL]= { 32,  1},
+   [VCAP_ES0_ACT_VID_B_VAL]= { 33, 12},
+   [VCAP_ES0_ACT_PCP_B_VAL]= { 45,  3},
+   [VCAP_ES0_ACT_DEI_B_VAL]= { 48,  1},
+   [VCAP_ES0_ACT_RSV]  = { 49, 23},
+   [VCAP_ES0_ACT_HIT_STICKY]   = { 72,  1},
+};
+
 struct vcap_field vsc9959_vcap_is1_keys[] = {
[VCAP_IS1_HK_TYPE]  = {  0,   1},
[VCAP_IS1_HK_LOOKUP]= {  1,   2},
@@ -737,6 +776,26 @@ struct vcap_field vsc9959_vcap_is2_actions[] = {
 };
 
 static const struct vcap_props vsc9959_vcap_props[] = {
+   [VCAP_ES0] = {
+   .tg_width = 1,
+   .sw_count = 1,
+   .entry_count = VSC9959_VCAP_ES0_CNT,
+   .entry_width = 29,
+   .action_count = VSC9959_VCAP_ES0_CNT + 6,
+   .action_width = 72,
+   .action_type_width = 0,
+   .action_table = {
+   [ES0_ACTION_TYPE_NORMAL] = {
+   .width = 72,
+   .count = 1
+   },
+   },
+   .counter_words = 1,
+   .counter_width = 1,
+   .target = S0,
+   .keys = vsc9959_vcap_es0_keys,
+   .actions = vsc9959_vcap_es0_actions,
+   },
[VCAP_IS1] = {
.tg_width = 2,
   

[PATCH v1 net-next 6/6] net: dsa: tag_ocelot: use VLAN information from tagging header when available

2020-05-06 Thread Xiaoliang Yang
From: Vladimir Oltean 

When the Extraction Frame Header contains a valid classified VLAN, use
that instead of the VLAN header present in the packet.

Signed-off-by: Vladimir Oltean 
---
 net/dsa/tag_ocelot.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/net/dsa/tag_ocelot.c b/net/dsa/tag_ocelot.c
index 59de1315100f..8c93a78bda5b 100644
--- a/net/dsa/tag_ocelot.c
+++ b/net/dsa/tag_ocelot.c
@@ -181,9 +181,16 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
  struct net_device *netdev,
  struct packet_type *pt)
 {
+   struct dsa_port *cpu_dp = netdev->dsa_ptr;
+   struct dsa_switch *ds = cpu_dp->ds;
+   struct ocelot *ocelot = ds->priv;
+   struct ocelot_port *ocelot_port;
u64 src_port, qos_class;
u8 *start = skb->data;
+   struct ethhdr *hdr;
u8 *extraction;
+   u64 vlan_tci;
+   u16 vid;
 
/* Revert skb->data by the amount consumed by the DSA master,
 * so it points to the beginning of the frame.
@@ -211,6 +218,7 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
 
packing(extraction, _port,  46, 43, OCELOT_TAG_LEN, UNPACK, 0);
packing(extraction, _class, 19, 17, OCELOT_TAG_LEN, UNPACK, 0);
+   packing(extraction, _tci,  15,  0, OCELOT_TAG_LEN, UNPACK, 0);
 
skb->dev = dsa_master_find_slave(netdev, 0, src_port);
if (!skb->dev)
@@ -225,6 +233,27 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
skb->offload_fwd_mark = 1;
skb->priority = qos_class;
 
+   /* The VID from the extraction header contains the classified VLAN. But
+* if VLAN awareness is off and no retagging is done via VCAP IS1, that
+* classified VID will always be the pvid of the src_port.
+* port. We want Linux to see the classified VID, but only if the switch
+* intended to send the packet as untagged, i.e. if the VID is different
+* than the CPU port's untagged (native) VID.
+*/
+   vid = vlan_tci & VLAN_VID_MASK;
+   hdr = eth_hdr(skb);
+   ocelot_port = ocelot->ports[src_port];
+   if (hdr->h_proto == htons(ETH_P_8021Q) && vid != ocelot_port->pvid) {
+   u16 dummy_vlan_tci;
+
+   skb_push_rcsum(skb, ETH_HLEN);
+   __skb_vlan_pop(skb, _vlan_tci);
+   skb_pull_rcsum(skb, ETH_HLEN);
+   skb_reset_network_header(skb);
+   skb_reset_transport_header(skb);
+   __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
+   }
+
return skb;
 }
 
-- 
2.17.1



[PATCH v1 net-next 2/6] net: mscc: ocelot: generalize existing code for VCAP IS2

2020-05-06 Thread Xiaoliang Yang
From: Vladimir Oltean 

The Ocelot driver only supports VCAP IS2, the security enforcement block
which implements Access Control List actions (trap, drop, police).

In preparation of VCAP IS1 support, generalize the existing code to work
with any VCAP. In that direction, move all VCAP instantiation-specific
data to struct vcap_props, and pass that as an argument to each function
that does the key and action packing. Only the high-level functions need
to have access to ocelot->vcap[VCAP_IS2].

Signed-off-by: Vladimir Oltean 
Signed-off-by: Xiaoliang Yang 
---
 drivers/net/dsa/ocelot/felix.c|   2 -
 drivers/net/dsa/ocelot/felix.h|   2 -
 drivers/net/dsa/ocelot/felix_vsc9959.c|  25 +-
 drivers/net/ethernet/mscc/ocelot_ace.c| 458 --
 drivers/net/ethernet/mscc/ocelot_ace.h|   1 +
 drivers/net/ethernet/mscc/ocelot_board.c  |   5 +-
 drivers/net/ethernet/mscc/ocelot_flower.c |   4 +
 drivers/net/ethernet/mscc/ocelot_regs.c   |  20 +-
 drivers/net/ethernet/mscc/ocelot_s2.h |  64 ---
 include/soc/mscc/ocelot.h |  23 +-
 include/soc/mscc/ocelot_vcap.h|  63 +++
 11 files changed, 367 insertions(+), 300 deletions(-)
 delete mode 100644 drivers/net/ethernet/mscc/ocelot_s2.h

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index e5b6748f6654..f5de3d84804b 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -401,8 +401,6 @@ static int felix_init_structs(struct felix *felix, int 
num_phys_ports)
ocelot->stats_layout= felix->info->stats_layout;
ocelot->num_stats   = felix->info->num_stats;
ocelot->shared_queue_sz = felix->info->shared_queue_sz;
-   ocelot->vcap_is2_keys   = felix->info->vcap_is2_keys;
-   ocelot->vcap_is2_actions= felix->info->vcap_is2_actions;
ocelot->vcap= felix->info->vcap;
ocelot->ops = felix->info->ops;
 
diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index 2ad793c0e1df..ce723deb9b5f 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -19,8 +19,6 @@ struct felix_info {
const struct ocelot_stat_layout *stats_layout;
unsigned intnum_stats;
int num_ports;
-   struct vcap_field   *vcap_is2_keys;
-   struct vcap_field   *vcap_is2_actions;
const struct vcap_props *vcap;
int switch_pci_bar;
int imdio_pci_bar;
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c 
b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 4fe707ef54b8..3b37c5f41fca 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -151,14 +151,16 @@ static const u32 vsc9959_qs_regmap[] = {
REG_RESERVED(QS_INH_DBG),
 };
 
-static const u32 vsc9959_s2_regmap[] = {
-   REG(S2_CORE_UPDATE_CTRL,0x00),
-   REG(S2_CORE_MV_CFG, 0x04),
-   REG(S2_CACHE_ENTRY_DAT, 0x08),
-   REG(S2_CACHE_MASK_DAT,  0x000108),
-   REG(S2_CACHE_ACTION_DAT,0x000208),
-   REG(S2_CACHE_CNT_DAT,   0x000308),
-   REG(S2_CACHE_TG_DAT,0x000388),
+static const u32 vsc9959_vcap_regmap[] = {
+   /* VCAP_CORE_CFG */
+   REG(VCAP_CORE_UPDATE_CTRL,  0x00),
+   REG(VCAP_CORE_MV_CFG,   0x04),
+   /* VCAP_CORE_CACHE */
+   REG(VCAP_CACHE_ENTRY_DAT,   0x08),
+   REG(VCAP_CACHE_MASK_DAT,0x000108),
+   REG(VCAP_CACHE_ACTION_DAT,  0x000208),
+   REG(VCAP_CACHE_CNT_DAT, 0x000308),
+   REG(VCAP_CACHE_TG_DAT,  0x000388),
 };
 
 static const u32 vsc9959_qsys_regmap[] = {
@@ -330,7 +332,7 @@ static const u32 *vsc9959_regmap[] = {
[QSYS]  = vsc9959_qsys_regmap,
[REW]   = vsc9959_rew_regmap,
[SYS]   = vsc9959_sys_regmap,
-   [S2]= vsc9959_s2_regmap,
+   [S2]= vsc9959_vcap_regmap,
[PTP]   = vsc9959_ptp_regmap,
[GCB]   = vsc9959_gcb_regmap,
 };
@@ -674,6 +676,9 @@ static const struct vcap_props vsc9959_vcap_props[] = {
},
.counter_words = 4,
.counter_width = 32,
+   .target = S2,
+   .keys = vsc9959_vcap_is2_keys,
+   .actions = vsc9959_vcap_is2_actions,
},
 };
 
@@ -1218,8 +1223,6 @@ struct felix_info felix_info_vsc9959 = {
.ops= _ops,
.stats_layout   = vsc9959_stats_layout,
.num_stats  = ARRAY_SIZE(vsc9959_stats_layout),
-   .vcap_is2_keys  = vsc9959_vcap_is2_keys,
-  

[PATCH v1 net-next 0/6] net: ocelot: VCAP IS1 and ES0 support

2020-05-06 Thread Xiaoliang Yang
This series patches adds support for VCAP IS1 and ES0 module.

VCAP IS1 supports FLOW_ACTION_VLAN_MANGLE action to filter MAC, IP,
VLAN, protocol, and TCP/UDP ports keys and retag vlan tag.

VCAP ES0 supports FLOW_ACTION_VLAN_PUSH action to filter vlan keys
and push a specific vlan tag to frames.

Vladimir Oltean (3):
  net: mscc: ocelot: introduce a new ocelot_target_{read,write} API
  net: mscc: ocelot: generalize existing code for VCAP IS2
  net: dsa: tag_ocelot: use VLAN information from tagging header when
available

Xiaoliang Yang (3):
  net: mscc: ocelot: change vcap to be compatible with full and quad
entry
  net: mscc: ocelot: VCAP IS1 support
  net: mscc: ocelot: VCAP ES0 support

 drivers/net/dsa/ocelot/felix.c|   2 -
 drivers/net/dsa/ocelot/felix.h|   2 -
 drivers/net/dsa/ocelot/felix_vsc9959.c| 186 +-
 drivers/net/ethernet/mscc/ocelot.c|  10 +
 drivers/net/ethernet/mscc/ocelot_ace.c| 727 --
 drivers/net/ethernet/mscc/ocelot_ace.h|  12 +
 drivers/net/ethernet/mscc/ocelot_board.c  |   5 +-
 drivers/net/ethernet/mscc/ocelot_flower.c |  33 +-
 drivers/net/ethernet/mscc/ocelot_io.c |  17 +
 drivers/net/ethernet/mscc/ocelot_regs.c   |  21 +-
 drivers/net/ethernet/mscc/ocelot_s2.h |  64 --
 include/soc/mscc/ocelot.h |  39 +-
 include/soc/mscc/ocelot_vcap.h| 200 +-
 net/dsa/tag_ocelot.c  |  29 +
 14 files changed, 1041 insertions(+), 306 deletions(-)
 delete mode 100644 drivers/net/ethernet/mscc/ocelot_s2.h

-- 
2.17.1



[PATCH v1 net-next 3/6] net: mscc: ocelot: change vcap to be compatible with full and quad entry

2020-05-06 Thread Xiaoliang Yang
When calculating vcap data offset, the function only supports half key
entry. This patch modify vcap_data_offset_get function to calculate a
correct data offset when setting VCAP Type-Group to VCAP_TG_FULL or
VCAP_TG_QUARTER.

Signed-off-by: Xiaoliang Yang 
---
 drivers/net/ethernet/mscc/ocelot_ace.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c 
b/drivers/net/ethernet/mscc/ocelot_ace.c
index 8a9c4515bb3b..29d61b89b73a 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.c
+++ b/drivers/net/ethernet/mscc/ocelot_ace.c
@@ -175,8 +175,8 @@ static void vcap_data_offset_get(const struct vcap_props 
*vcap,
u32 i, col, offset, count, cnt, base;
u32 width = vcap->tg_width;
 
-   count = (data->tg_sw == VCAP_TG_HALF ? 2 : 4);
-   col = (ix % 2);
+   count = (1 << (data->tg_sw - 1));
+   col = (ix % count);
cnt = (vcap->sw_count / count);
base = (vcap->sw_count - col * cnt - cnt);
data->tg_value = 0;
-- 
2.17.1



[PATCH v1 net-next 1/6] net: mscc: ocelot: introduce a new ocelot_target_{read,write} API

2020-05-06 Thread Xiaoliang Yang
From: Vladimir Oltean 

There are some targets (register blocks) in the Ocelot switch that are
instantiated more than once. For example, the VCAP IS1, IS2 and ES0
blocks all share the same register layout for interacting with the cache
for the TCAM and the action RAM.

For the VCAPs, the procedure for servicing them is actually common. We
just need an API specifying which VCAP we are talking to, and we do that
via these raw ocelot_target_read and ocelot_target_write accessors.

In plain ocelot_read, the target is encoded into the register enum
itself:

u16 target = reg >> TARGET_OFFSET;

For the VCAPs, the registers are currently defined like this:

enum ocelot_reg {
[...]
S2_CORE_UPDATE_CTRL = S2 << TARGET_OFFSET,
S2_CORE_MV_CFG,
S2_CACHE_ENTRY_DAT,
S2_CACHE_MASK_DAT,
S2_CACHE_ACTION_DAT,
S2_CACHE_CNT_DAT,
S2_CACHE_TG_DAT,
[...]
};

which is precisely what we want to avoid, because we'd have to duplicate
the same register map for S1 and for S0, and then figure out how to pass
VCAP instance-specific registers to the ocelot_read calls (basically
another lookup table that undoes the effect of shifting with
TARGET_OFFSET).

So for some targets, propose a more raw API, similar to what is
currently done with ocelot_port_readl and ocelot_port_writel. Those
targets can only be accessed with ocelot_target_{read,write} and not
with ocelot_{read,write} after the conversion, which is fine.

The VCAP registers are not actually modified to use this new API as of
this patch. They will be modified in the next one.

Signed-off-by: Vladimir Oltean 
---
 drivers/net/ethernet/mscc/ocelot_io.c | 17 +
 include/soc/mscc/ocelot.h | 14 ++
 2 files changed, 31 insertions(+)

diff --git a/drivers/net/ethernet/mscc/ocelot_io.c 
b/drivers/net/ethernet/mscc/ocelot_io.c
index b229b1cb68ef..9b52d82f5399 100644
--- a/drivers/net/ethernet/mscc/ocelot_io.c
+++ b/drivers/net/ethernet/mscc/ocelot_io.c
@@ -59,6 +59,23 @@ void ocelot_port_writel(struct ocelot_port *port, u32 val, 
u32 reg)
 }
 EXPORT_SYMBOL(ocelot_port_writel);
 
+u32 __ocelot_target_read_ix(struct ocelot *ocelot, enum ocelot_target target,
+   u32 reg, u32 offset)
+{
+   u32 val;
+
+   regmap_read(ocelot->targets[target],
+   ocelot->map[target][reg] + offset, );
+   return val;
+}
+
+void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target,
+ u32 val, u32 reg, u32 offset)
+{
+   regmap_write(ocelot->targets[target],
+ocelot->map[target][reg] + offset, val);
+}
+
 int ocelot_regfields_init(struct ocelot *ocelot,
  const struct reg_field *const regfields)
 {
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index a025fb798164..ec95615ffe88 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -577,6 +577,16 @@ struct ocelot_policer {
 #define ocelot_rmw_rix(ocelot, val, m, reg, ri) __ocelot_rmw_ix(ocelot, val, 
m, reg, reg##_RSZ * (ri))
 #define ocelot_rmw(ocelot, val, m, reg) __ocelot_rmw_ix(ocelot, val, m, reg, 0)
 
+#define ocelot_target_read_ix(ocelot, target, reg, gi, ri) 
__ocelot_target_read_ix(ocelot, target, reg, reg##_GSZ * (gi) + reg##_RSZ * 
(ri))
+#define ocelot_target_read_gix(ocelot, target, reg, gi) 
__ocelot_target_read_ix(ocelot, target, reg, reg##_GSZ * (gi))
+#define ocelot_target_read_rix(ocelot, target, reg, ri) 
__ocelot_target_read_ix(ocelot, target, reg, reg##_RSZ * (ri))
+#define ocelot_target_read(ocelot, target, reg) 
__ocelot_target_read_ix(ocelot, target, reg, 0)
+
+#define ocelot_target_write_ix(ocelot, target, val, reg, gi, ri) 
__ocelot_target_write_ix(ocelot, target, val, reg, reg##_GSZ * (gi) + reg##_RSZ 
* (ri))
+#define ocelot_target_write_gix(ocelot, target, val, reg, gi) 
__ocelot_target_write_ix(ocelot, target, val, reg, reg##_GSZ * (gi))
+#define ocelot_target_write_rix(ocelot, target, val, reg, ri) 
__ocelot_target_write_ix(ocelot, target, val, reg, reg##_RSZ * (ri))
+#define ocelot_target_write(ocelot, target, val, reg) 
__ocelot_target_write_ix(ocelot, target, val, reg, 0)
+
 /* I/O */
 u32 ocelot_port_readl(struct ocelot_port *port, u32 reg);
 void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg);
@@ -584,6 +594,10 @@ u32 __ocelot_read_ix(struct ocelot *ocelot, u32 reg, u32 
offset);
 void __ocelot_write_ix(struct ocelot *ocelot, u32 val, u32 reg, u32 offset);
 void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask, u32 reg,
 u32 offset);
+u32 __ocelot_target_read_ix(struct ocelot *ocelot, enum ocelot_target target,
+   u32 reg, u32 offset);
+void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target,
+ u32 val, u32 reg, u32 offset);
 
 /* Hardware