Skip to content

Commit

Permalink
Merge branch 'Wire-up-Ocelot-tc-flower-to-Felix-DSA'
Browse files Browse the repository at this point in the history
Vladimir Oltean says:

====================
Wire up Ocelot tc-flower to Felix DSA

This series is a proposal on how to wire up the tc-flower callbacks into
DSA. The example taken is the Microchip Felix switch, whose core
implementation is actually located in drivers/net/ethernet/mscc/.

The proposal is largely a compromise solution. The DSA middle layer
handles just enough to get to the interesting stuff (FLOW_CLS_REPLACE,
FLOW_CLS_DESTROY, FLOW_CLS_STATS), but also thin enough to let drivers
decide what filter keys and actions they support without worrying that
the DSA middle layer will grow exponentially. I am far from being an
expert, so I am asking reviewers to please voice your opinion if you
think it can be done differently, with better results.

The bulk of the work was actually refactoring the ocelot driver enough
to allow the VCAP (Versatile Content-Aware Processor) code for vsc7514
and the vsc9959 switch cores to live together.

Flow block offloads have not been tested yet, only filters attached to a
single port. It might be as simple as replacing ocelot_ace_rule_create
with something smarter, it might be more complicated, I haven't tried
yet.

I should point out that the tc-matchall filter offload is not
implemented in the same manner in current mainline. Florian has already
went all the way down into exposing actual per-action callbacks,
starting with port mirroring. Because currently only mirred is supported
by this DSA mid layer, everything else will return -EOPNOTSUPP. So even
though ocelot supports matchall (aka port-based) policers, we don't have
a call path to call into them.  Personally I think that this is not
going to scale for tc-matchall (there may be policers, traps, drops,
VLAN retagging, etc etc), and that we should consider whether further
matchall filter/action combinations should be just passed on to drivers
with no interpretation instead.
As for the existing mirroring callbacks in DSA, they can either be kept
as-is, or replaced with simple accessors to TC_CLSMATCHALL_REPLACE and
TC_CLSMATCHALL_DESTROY, just like for flower, and drivers which
currently implement the port mirroring callbacks will need to have some
extra "if" conditions now, in order for them to call their port
mirroring implementations.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 4, 2020
2 parents d658489 + 07d985e commit eae340f
Show file tree
Hide file tree
Showing 14 changed files with 983 additions and 917 deletions.
31 changes: 31 additions & 0 deletions drivers/net/dsa/ocelot/felix.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/* Copyright 2019 NXP Semiconductors
*/
#include <uapi/linux/if_bridge.h>
#include <soc/mscc/ocelot_vcap.h>
#include <soc/mscc/ocelot_qsys.h>
#include <soc/mscc/ocelot_sys.h>
#include <soc/mscc/ocelot_dev.h>
Expand Down Expand Up @@ -401,6 +402,9 @@ 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;

port_phy_modes = kcalloc(num_phys_ports, sizeof(phy_interface_t),
Expand Down Expand Up @@ -595,6 +599,30 @@ static bool felix_txtstamp(struct dsa_switch *ds, int port,
return false;
}

static int felix_cls_flower_add(struct dsa_switch *ds, int port,
struct flow_cls_offload *cls, bool ingress)
{
struct ocelot *ocelot = ds->priv;

return ocelot_cls_flower_replace(ocelot, port, cls, ingress);
}

static int felix_cls_flower_del(struct dsa_switch *ds, int port,
struct flow_cls_offload *cls, bool ingress)
{
struct ocelot *ocelot = ds->priv;

return ocelot_cls_flower_destroy(ocelot, port, cls, ingress);
}

static int felix_cls_flower_stats(struct dsa_switch *ds, int port,
struct flow_cls_offload *cls, bool ingress)
{
struct ocelot *ocelot = ds->priv;

return ocelot_cls_flower_stats(ocelot, port, cls, ingress);
}

static const struct dsa_switch_ops felix_switch_ops = {
.get_tag_protocol = felix_get_tag_protocol,
.setup = felix_setup,
Expand Down Expand Up @@ -626,6 +654,9 @@ static const struct dsa_switch_ops felix_switch_ops = {
.port_hwtstamp_set = felix_hwtstamp_set,
.port_rxtstamp = felix_rxtstamp,
.port_txtstamp = felix_txtstamp,
.cls_flower_add = felix_cls_flower_add,
.cls_flower_del = felix_cls_flower_del,
.cls_flower_stats = felix_cls_flower_stats,
};

static struct felix_info *felix_instance_tbl[] = {
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/dsa/ocelot/felix.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ struct felix_info {
const struct ocelot_stat_layout *stats_layout;
unsigned int num_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;
int (*mdio_bus_alloc)(struct ocelot *ocelot);
Expand Down
131 changes: 131 additions & 0 deletions drivers/net/dsa/ocelot/felix_vsc9959.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
* Copyright 2018-2019 NXP Semiconductors
*/
#include <linux/fsl/enetc_mdio.h>
#include <soc/mscc/ocelot_vcap.h>
#include <soc/mscc/ocelot_sys.h>
#include <soc/mscc/ocelot.h>
#include <linux/iopoll.h>
#include <linux/pci.h>
#include "felix.h"

#define VSC9959_VCAP_IS2_CNT 1024
#define VSC9959_VCAP_IS2_ENTRY_WIDTH 376
#define VSC9959_VCAP_PORT_CNT 6

/* TODO: should find a better place for these */
#define USXGMII_BMCR_RESET BIT(15)
#define USXGMII_BMCR_AN_EN BIT(12)
Expand Down Expand Up @@ -547,6 +552,129 @@ static const struct ocelot_stat_layout vsc9959_stats_layout[] = {
{ .offset = 0x111, .name = "drop_green_prio_7", },
};

struct vcap_field vsc9959_vcap_is2_keys[] = {
/* Common: 41 bits */
[VCAP_IS2_TYPE] = { 0, 4},
[VCAP_IS2_HK_FIRST] = { 4, 1},
[VCAP_IS2_HK_PAG] = { 5, 8},
[VCAP_IS2_HK_IGR_PORT_MASK] = { 13, 7},
[VCAP_IS2_HK_RSV2] = { 20, 1},
[VCAP_IS2_HK_HOST_MATCH] = { 21, 1},
[VCAP_IS2_HK_L2_MC] = { 22, 1},
[VCAP_IS2_HK_L2_BC] = { 23, 1},
[VCAP_IS2_HK_VLAN_TAGGED] = { 24, 1},
[VCAP_IS2_HK_VID] = { 25, 12},
[VCAP_IS2_HK_DEI] = { 37, 1},
[VCAP_IS2_HK_PCP] = { 38, 3},
/* MAC_ETYPE / MAC_LLC / MAC_SNAP / OAM common */
[VCAP_IS2_HK_L2_DMAC] = { 41, 48},
[VCAP_IS2_HK_L2_SMAC] = { 89, 48},
/* MAC_ETYPE (TYPE=000) */
[VCAP_IS2_HK_MAC_ETYPE_ETYPE] = {137, 16},
[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0] = {153, 16},
[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1] = {169, 8},
[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2] = {177, 3},
/* MAC_LLC (TYPE=001) */
[VCAP_IS2_HK_MAC_LLC_L2_LLC] = {137, 40},
/* MAC_SNAP (TYPE=010) */
[VCAP_IS2_HK_MAC_SNAP_L2_SNAP] = {137, 40},
/* MAC_ARP (TYPE=011) */
[VCAP_IS2_HK_MAC_ARP_SMAC] = { 41, 48},
[VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK] = { 89, 1},
[VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK] = { 90, 1},
[VCAP_IS2_HK_MAC_ARP_LEN_OK] = { 91, 1},
[VCAP_IS2_HK_MAC_ARP_TARGET_MATCH] = { 92, 1},
[VCAP_IS2_HK_MAC_ARP_SENDER_MATCH] = { 93, 1},
[VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN] = { 94, 1},
[VCAP_IS2_HK_MAC_ARP_OPCODE] = { 95, 2},
[VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP] = { 97, 32},
[VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP] = {129, 32},
[VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP] = {161, 1},
/* IP4_TCP_UDP / IP4_OTHER common */
[VCAP_IS2_HK_IP4] = { 41, 1},
[VCAP_IS2_HK_L3_FRAGMENT] = { 42, 1},
[VCAP_IS2_HK_L3_FRAG_OFS_GT0] = { 43, 1},
[VCAP_IS2_HK_L3_OPTIONS] = { 44, 1},
[VCAP_IS2_HK_IP4_L3_TTL_GT0] = { 45, 1},
[VCAP_IS2_HK_L3_TOS] = { 46, 8},
[VCAP_IS2_HK_L3_IP4_DIP] = { 54, 32},
[VCAP_IS2_HK_L3_IP4_SIP] = { 86, 32},
[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_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_1588_DOM] = {168, 8},
[VCAP_IS2_HK_L4_1588_VER] = {176, 4},
/* IP4_OTHER (TYPE=101) */
[VCAP_IS2_HK_IP4_L3_PROTO] = {119, 8},
[VCAP_IS2_HK_L3_PAYLOAD] = {127, 56},
/* IP6_STD (TYPE=110) */
[VCAP_IS2_HK_IP6_L3_TTL_GT0] = { 41, 1},
[VCAP_IS2_HK_L3_IP6_SIP] = { 42, 128},
[VCAP_IS2_HK_IP6_L3_PROTO] = {170, 8},
/* OAM (TYPE=111) */
[VCAP_IS2_HK_OAM_MEL_FLAGS] = {137, 7},
[VCAP_IS2_HK_OAM_VER] = {144, 5},
[VCAP_IS2_HK_OAM_OPCODE] = {149, 8},
[VCAP_IS2_HK_OAM_FLAGS] = {157, 8},
[VCAP_IS2_HK_OAM_MEPID] = {165, 16},
[VCAP_IS2_HK_OAM_CCM_CNTS_EQ0] = {181, 1},
[VCAP_IS2_HK_OAM_IS_Y1731] = {182, 1},
};

struct vcap_field vsc9959_vcap_is2_actions[] = {
[VCAP_IS2_ACT_HIT_ME_ONCE] = { 0, 1},
[VCAP_IS2_ACT_CPU_COPY_ENA] = { 1, 1},
[VCAP_IS2_ACT_CPU_QU_NUM] = { 2, 3},
[VCAP_IS2_ACT_MASK_MODE] = { 5, 2},
[VCAP_IS2_ACT_MIRROR_ENA] = { 7, 1},
[VCAP_IS2_ACT_LRN_DIS] = { 8, 1},
[VCAP_IS2_ACT_POLICE_ENA] = { 9, 1},
[VCAP_IS2_ACT_POLICE_IDX] = { 10, 9},
[VCAP_IS2_ACT_POLICE_VCAP_ONLY] = { 19, 1},
[VCAP_IS2_ACT_PORT_MASK] = { 20, 11},
[VCAP_IS2_ACT_REW_OP] = { 31, 9},
[VCAP_IS2_ACT_SMAC_REPLACE_ENA] = { 40, 1},
[VCAP_IS2_ACT_RSV] = { 41, 2},
[VCAP_IS2_ACT_ACL_ID] = { 43, 6},
[VCAP_IS2_ACT_HIT_CNT] = { 49, 32},
};

static const struct vcap_props vsc9959_vcap_props[] = {
[VCAP_IS2] = {
.tg_width = 2,
.sw_count = 4,
.entry_count = VSC9959_VCAP_IS2_CNT,
.entry_width = VSC9959_VCAP_IS2_ENTRY_WIDTH,
.action_count = VSC9959_VCAP_IS2_CNT +
VSC9959_VCAP_PORT_CNT + 2,
.action_width = 89,
.action_type_width = 1,
.action_table = {
[IS2_ACTION_TYPE_NORMAL] = {
.width = 44,
.count = 2
},
[IS2_ACTION_TYPE_SMAC_SIP] = {
.width = 6,
.count = 4
},
},
.counter_words = 4,
.counter_width = 32,
},
};

#define VSC9959_INIT_TIMEOUT 50000
#define VSC9959_GCB_RST_SLEEP 100
#define VSC9959_SYS_RAMINIT_SLEEP 80
Expand Down Expand Up @@ -1088,6 +1216,9 @@ struct felix_info felix_info_vsc9959 = {
.ops = &vsc9959_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,
.vcap = vsc9959_vcap_props,
.shared_queue_sz = 128 * 1024,
.num_ports = 6,
.switch_pci_bar = 4,
Expand Down
20 changes: 17 additions & 3 deletions drivers/net/ethernet/mscc/ocelot.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,23 @@ void ocelot_adjust_link(struct ocelot *ocelot, int port,
ocelot_port_writel(ocelot_port, DEV_MAC_MODE_CFG_FDX_ENA |
mode, DEV_MAC_MODE_CFG);

if (ocelot->ops->pcs_init)
ocelot->ops->pcs_init(ocelot, port);
/* Disable HDX fast control */
ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS,
DEV_PORT_MISC);

/* SGMII only for now */
ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA,
PCS1G_MODE_CFG);
ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG);

/* Enable PCS */
ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG);

/* No aneg on SGMII */
ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG);

/* No loopback */
ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG);

/* Enable MAC module */
ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA |
Expand Down Expand Up @@ -2493,7 +2508,6 @@ void ocelot_deinit(struct ocelot *ocelot)
cancel_delayed_work(&ocelot->stats_work);
destroy_workqueue(ocelot->stats_queue);
mutex_destroy(&ocelot->stats_lock);
ocelot_ace_deinit();
if (ocelot->ptp_clock)
ptp_clock_unregister(ocelot->ptp_clock);

Expand Down
Loading

0 comments on commit eae340f

Please sign in to comment.