Commit a3a4de05 authored by David S. Miller's avatar David S. Miller

Merge branch 'net-dsa-bcm_sf2-CFP-support'

Florian Fainelli says:

====================
net: dsa: bcm_sf2: CFP support

This patch series adds support for the Broadcom Compact Field Processor (CFP)
which is a classification and matching engine built into most Broadcom switches.

We support that using ethtool::rxnfc because it allows all known uses cases from
the users I support to work, and more importantly, it allows the selection of a
target rule index, which is later used by e.g: offloading hardware, this is an
essential feature that I could not find being supported with cls_* for instance.

Thanks!

Changes in v3:

- rebased against latest net-next/master after Vivien's changes

Changes in v2:

- fixed modular builds reported by kbuild test robot
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 40be0dda 7318166c
obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
obj-$(CONFIG_NET_DSA_BCM_SF2) += bcm_sf2.o
bcm_sf2-objs += bcm_sf2_cfp.o
obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o
obj-y += b53/
......
......@@ -229,6 +229,7 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
{
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
s8 cpu_port = ds->dst[ds->index].cpu_port;
unsigned int i;
u32 reg;
/* Clear the memory power down */
......@@ -240,6 +241,14 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
if (priv->brcm_tag_mask & BIT(port))
bcm_sf2_brcm_hdr_setup(priv, port);
/* Configure Traffic Class to QoS mapping, allow each priority to map
* to a different queue number
*/
reg = core_readl(priv, CORE_PORT_TC2_QOS_MAP_PORT(port));
for (i = 0; i < 8; i++)
reg |= i << (PRT_TO_QID_SHIFT * i);
core_writel(priv, reg, CORE_PORT_TC2_QOS_MAP_PORT(port));
/* Clear the Rx and Tx disable bits and set to no spanning tree */
core_writel(priv, 0, CORE_G_PCTL_PORT(port));
......@@ -1036,6 +1045,8 @@ static const struct dsa_switch_ops bcm_sf2_ops = {
.port_fdb_dump = b53_fdb_dump,
.port_fdb_add = b53_fdb_add,
.port_fdb_del = b53_fdb_del,
.get_rxnfc = bcm_sf2_get_rxnfc,
.set_rxnfc = bcm_sf2_set_rxnfc,
};
struct bcm_sf2_of_data {
......@@ -1159,6 +1170,12 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
spin_lock_init(&priv->indir_lock);
mutex_init(&priv->stats_mutex);
mutex_init(&priv->cfp.lock);
/* CFP rule #0 cannot be used for specific classifications, flag it as
* permanently used
*/
set_bit(0, priv->cfp.used);
bcm_sf2_identify_ports(priv, dn->child);
......@@ -1188,6 +1205,12 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
return ret;
}
ret = bcm_sf2_cfp_rst(priv);
if (ret) {
pr_err("failed to reset CFP\n");
goto out_mdio;
}
/* Disable all interrupts and request them */
bcm_sf2_intr_disable(priv);
......
......@@ -52,6 +52,13 @@ struct bcm_sf2_port_status {
struct ethtool_eee eee;
};
struct bcm_sf2_cfp_priv {
/* Mutex protecting concurrent accesses to the CFP registers */
struct mutex lock;
DECLARE_BITMAP(used, CFP_NUM_RULES);
unsigned int rules_cnt;
};
struct bcm_sf2_priv {
/* Base registers, keep those in order with BCM_SF2_REGS_NAME */
void __iomem *core;
......@@ -103,6 +110,9 @@ struct bcm_sf2_priv {
/* Bitmask of ports needing BRCM tags */
unsigned int brcm_tag_mask;
/* CFP rules context */
struct bcm_sf2_cfp_priv cfp;
};
static inline struct bcm_sf2_priv *bcm_sf2_to_priv(struct dsa_switch *ds)
......@@ -197,4 +207,11 @@ SF2_IO_MACRO(acb);
SWITCH_INTR_L2(0);
SWITCH_INTR_L2(1);
/* RXNFC */
int bcm_sf2_get_rxnfc(struct dsa_switch *ds, int port,
struct ethtool_rxnfc *nfc, u32 *rule_locs);
int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port,
struct ethtool_rxnfc *nfc);
int bcm_sf2_cfp_rst(struct bcm_sf2_priv *priv);
#endif /* __BCM_SF2_H */
This diff is collapsed.
......@@ -238,6 +238,10 @@ enum bcm_sf2_reg_offs {
#define P_TXQ_PSM_VDD(x) (P_TXQ_PSM_VDD_MASK << \
((x) * P_TXQ_PSM_VDD_SHIFT))
#define CORE_PORT_TC2_QOS_MAP_PORT(x) (0xc1c0 + ((x) * 0x10))
#define PRT_TO_QID_MASK 0x3
#define PRT_TO_QID_SHIFT 3
#define CORE_PORT_VLAN_CTL_PORT(x) (0xc400 + ((x) * 0x8))
#define PORT_VLAN_CTRL_MASK 0x1ff
......@@ -251,4 +255,150 @@ enum bcm_sf2_reg_offs {
#define CORE_EEE_EN_CTRL 0x24800
#define CORE_EEE_LPI_INDICATE 0x24810
#define CORE_CFP_ACC 0x28000
#define OP_STR_DONE (1 << 0)
#define OP_SEL_SHIFT 1
#define OP_SEL_READ (1 << OP_SEL_SHIFT)
#define OP_SEL_WRITE (2 << OP_SEL_SHIFT)
#define OP_SEL_SEARCH (4 << OP_SEL_SHIFT)
#define OP_SEL_MASK (7 << OP_SEL_SHIFT)
#define CFP_RAM_CLEAR (1 << 4)
#define RAM_SEL_SHIFT 10
#define TCAM_SEL (1 << RAM_SEL_SHIFT)
#define ACT_POL_RAM (2 << RAM_SEL_SHIFT)
#define RATE_METER_RAM (4 << RAM_SEL_SHIFT)
#define GREEN_STAT_RAM (8 << RAM_SEL_SHIFT)
#define YELLOW_STAT_RAM (16 << RAM_SEL_SHIFT)
#define RED_STAT_RAM (24 << RAM_SEL_SHIFT)
#define RAM_SEL_MASK (0x1f << RAM_SEL_SHIFT)
#define TCAM_RESET (1 << 15)
#define XCESS_ADDR_SHIFT 16
#define XCESS_ADDR_MASK 0xff
#define SEARCH_STS (1 << 27)
#define RD_STS_SHIFT 28
#define RD_STS_TCAM (1 << RD_STS_SHIFT)
#define RD_STS_ACT_POL_RAM (2 << RD_STS_SHIFT)
#define RD_STS_RATE_METER_RAM (4 << RD_STS_SHIFT)
#define RD_STS_STAT_RAM (8 << RD_STS_SHIFT)
#define CORE_CFP_RATE_METER_GLOBAL_CTL 0x28010
#define CORE_CFP_DATA_PORT_0 0x28040
#define CORE_CFP_DATA_PORT(x) (CORE_CFP_DATA_PORT_0 + \
(x) * 0x10)
/* UDF_DATA7 */
#define L3_FRAMING_SHIFT 24
#define L3_FRAMING_MASK (0x3 << L3_FRAMING_SHIFT)
#define IPPROTO_SHIFT 8
#define IPPROTO_MASK (0xff << IPPROTO_SHIFT)
#define IP_FRAG (1 << 7)
/* UDF_DATA0 */
#define SLICE_VALID 3
#define SLICE_NUM_SHIFT 2
#define SLICE_NUM(x) ((x) << SLICE_NUM_SHIFT)
#define CORE_CFP_MASK_PORT_0 0x280c0
#define CORE_CFP_MASK_PORT(x) (CORE_CFP_MASK_PORT_0 + \
(x) * 0x10)
#define CORE_ACT_POL_DATA0 0x28140
#define VLAN_BYP (1 << 0)
#define EAP_BYP (1 << 1)
#define STP_BYP (1 << 2)
#define REASON_CODE_SHIFT 3
#define REASON_CODE_MASK 0x3f
#define LOOP_BK_EN (1 << 9)
#define NEW_TC_SHIFT 10
#define NEW_TC_MASK 0x7
#define CHANGE_TC (1 << 13)
#define DST_MAP_IB_SHIFT 14
#define DST_MAP_IB_MASK 0x1ff
#define CHANGE_FWRD_MAP_IB_SHIFT 24
#define CHANGE_FWRD_MAP_IB_MASK 0x3
#define CHANGE_FWRD_MAP_IB_NO_DEST (0 << CHANGE_FWRD_MAP_IB_SHIFT)
#define CHANGE_FWRD_MAP_IB_REM_ARL (1 << CHANGE_FWRD_MAP_IB_SHIFT)
#define CHANGE_FWRD_MAP_IB_REP_ARL (2 << CHANGE_FWRD_MAP_IB_SHIFT)
#define CHANGE_FWRD_MAP_IB_ADD_DST (3 << CHANGE_FWRD_MAP_IB_SHIFT)
#define NEW_DSCP_IB_SHIFT 26
#define NEW_DSCP_IB_MASK 0x3f
#define CORE_ACT_POL_DATA1 0x28150
#define CHANGE_DSCP_IB (1 << 0)
#define DST_MAP_OB_SHIFT 1
#define DST_MAP_OB_MASK 0x3ff
#define CHANGE_FWRD_MAP_OB_SHIT 11
#define CHANGE_FWRD_MAP_OB_MASK 0x3
#define NEW_DSCP_OB_SHIFT 13
#define NEW_DSCP_OB_MASK 0x3f
#define CHANGE_DSCP_OB (1 << 19)
#define CHAIN_ID_SHIFT 20
#define CHAIN_ID_MASK 0xff
#define CHANGE_COLOR (1 << 28)
#define NEW_COLOR_SHIFT 29
#define NEW_COLOR_MASK 0x3
#define NEW_COLOR_GREEN (0 << NEW_COLOR_SHIFT)
#define NEW_COLOR_YELLOW (1 << NEW_COLOR_SHIFT)
#define NEW_COLOR_RED (2 << NEW_COLOR_SHIFT)
#define RED_DEFAULT (1 << 31)
#define CORE_ACT_POL_DATA2 0x28160
#define MAC_LIMIT_BYPASS (1 << 0)
#define CHANGE_TC_O (1 << 1)
#define NEW_TC_O_SHIFT 2
#define NEW_TC_O_MASK 0x7
#define SPCP_RMK_DISABLE (1 << 5)
#define CPCP_RMK_DISABLE (1 << 6)
#define DEI_RMK_DISABLE (1 << 7)
#define CORE_RATE_METER0 0x28180
#define COLOR_MODE (1 << 0)
#define POLICER_ACTION (1 << 1)
#define COUPLING_FLAG (1 << 2)
#define POLICER_MODE_SHIFT 3
#define POLICER_MODE_MASK 0x3
#define POLICER_MODE_RFC2698 (0 << POLICER_MODE_SHIFT)
#define POLICER_MODE_RFC4115 (1 << POLICER_MODE_SHIFT)
#define POLICER_MODE_MEF (2 << POLICER_MODE_SHIFT)
#define POLICER_MODE_DISABLE (3 << POLICER_MODE_SHIFT)
#define CORE_RATE_METER1 0x28190
#define EIR_TK_BKT_MASK 0x7fffff
#define CORE_RATE_METER2 0x281a0
#define EIR_BKT_SIZE_MASK 0xfffff
#define CORE_RATE_METER3 0x281b0
#define EIR_REF_CNT_MASK 0x7ffff
#define CORE_RATE_METER4 0x281c0
#define CIR_TK_BKT_MASK 0x7fffff
#define CORE_RATE_METER5 0x281d0
#define CIR_BKT_SIZE_MASK 0xfffff
#define CORE_RATE_METER6 0x281e0
#define CIR_REF_CNT_MASK 0x7ffff
#define CORE_CFP_CTL_REG 0x28400
#define CFP_EN_MAP_MASK 0x1ff
/* IPv4 slices, 3 of them */
#define CORE_UDF_0_A_0_8_PORT_0 0x28440
#define CFG_UDF_OFFSET_MASK 0x1f
#define CFG_UDF_OFFSET_BASE_SHIFT 5
#define CFG_UDF_SOF (0 << CFG_UDF_OFFSET_BASE_SHIFT)
#define CFG_UDF_EOL2 (2 << CFG_UDF_OFFSET_BASE_SHIFT)
#define CFG_UDF_EOL3 (3 << CFG_UDF_OFFSET_BASE_SHIFT)
/* Number of slices for IPv4, IPv6 and non-IP */
#define UDF_NUM_SLICES 9
/* Spacing between different slices */
#define UDF_SLICE_OFFSET 0x40
#define CFP_NUM_RULES 256
#endif /* __BCM_SF2_REGS_H */
......@@ -377,6 +377,14 @@ struct dsa_switch_ops {
int (*port_mdb_dump)(struct dsa_switch *ds, int port,
struct switchdev_obj_port_mdb *mdb,
int (*cb)(struct switchdev_obj *obj));
/*
* RXNFC
*/
int (*get_rxnfc)(struct dsa_switch *ds, int port,
struct ethtool_rxnfc *nfc, u32 *rule_locs);
int (*set_rxnfc)(struct dsa_switch *ds, int port,
struct ethtool_rxnfc *nfc);
};
struct dsa_switch_driver {
......
......@@ -1002,6 +1002,30 @@ void dsa_cpu_port_ethtool_init(struct ethtool_ops *ops)
ops->get_strings = dsa_cpu_port_get_strings;
}
static int dsa_slave_get_rxnfc(struct net_device *dev,
struct ethtool_rxnfc *nfc, u32 *rule_locs)
{
struct dsa_slave_priv *p = netdev_priv(dev);
struct dsa_switch *ds = p->dp->ds;
if (!ds->ops->get_rxnfc)
return -EOPNOTSUPP;
return ds->ops->get_rxnfc(ds, p->dp->index, nfc, rule_locs);
}
static int dsa_slave_set_rxnfc(struct net_device *dev,
struct ethtool_rxnfc *nfc)
{
struct dsa_slave_priv *p = netdev_priv(dev);
struct dsa_switch *ds = p->dp->ds;
if (!ds->ops->set_rxnfc)
return -EOPNOTSUPP;
return ds->ops->set_rxnfc(ds, p->dp->index, nfc);
}
static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_drvinfo = dsa_slave_get_drvinfo,
.get_regs_len = dsa_slave_get_regs_len,
......@@ -1020,6 +1044,8 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_eee = dsa_slave_get_eee,
.get_link_ksettings = dsa_slave_get_link_ksettings,
.set_link_ksettings = dsa_slave_set_link_ksettings,
.get_rxnfc = dsa_slave_get_rxnfc,
.set_rxnfc = dsa_slave_set_rxnfc,
};
static const struct net_device_ops dsa_slave_netdev_ops = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment