Commit 13d61c3a authored by David S. Miller's avatar David S. Miller

Merge branch 'mv88e6xxx-rework-ATU-support'

Vivien Didelot says:

====================
net: dsa: mv88e6xxx: rework ATU support

The purpose of this patch series is to rework the code related to the
Address Translation Unit (ATU), and bring support for it to the 88E6390
family of switch chips.

All Global (1) ATU related code have been reworked and moved to its own
file. Some port related bits used for ATU configuration (such as the
Learn2All and MessagePort feature) have also been taken care of.

The ports' mode and egress flooding mode have been refactored to fix the
egress of frames with unknown unicast or multicast destination address,
and write all these bits regardless the port mode (Normal, DSA, etc.)

Finally remove the eth_addr_greater which was only used by mv88e6xxx.

Changes in v2:
  - add Reviewed-by tags
  - split mv88e6xxx_g1_atu_set_age_time and mv88e6xxx_atu_setup addition
  - remove DSA_TAG_PROTO_TRAILER check
  - split Message Port and Learn2All addition
  - remove unused MV88E6XXX_FLAG_G1_ATU_FID flag
  - add dsa_is_normal_port helper
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 0f230ca9 0c68f666
obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o
mv88e6xxx-objs := chip.o mv88e6xxx-objs := chip.o
mv88e6xxx-objs += global1.o mv88e6xxx-objs += global1.o
mv88e6xxx-objs += global1_atu.o
mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2.o mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2.o
mv88e6xxx-objs += port.o mv88e6xxx-objs += port.o
This diff is collapsed.
...@@ -38,4 +38,15 @@ int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port); ...@@ -38,4 +38,15 @@ int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port);
int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port); int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port);
int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
int mv88e6xxx_g1_atu_set_learn2all(struct mv88e6xxx_chip *chip, bool learn2all);
int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip *chip,
unsigned int msecs);
int mv88e6xxx_g1_atu_getnext(struct mv88e6xxx_chip *chip, u16 fid,
struct mv88e6xxx_atu_entry *entry);
int mv88e6xxx_g1_atu_loadpurge(struct mv88e6xxx_chip *chip, u16 fid,
struct mv88e6xxx_atu_entry *entry);
int mv88e6xxx_g1_atu_flush(struct mv88e6xxx_chip *chip, u16 fid, bool all);
int mv88e6xxx_g1_atu_remove(struct mv88e6xxx_chip *chip, u16 fid, int port,
bool all);
#endif /* _MV88E6XXX_GLOBAL1_H */ #endif /* _MV88E6XXX_GLOBAL1_H */
/*
* Marvell 88E6xxx Address Translation Unit (ATU) support
*
* Copyright (c) 2008 Marvell Semiconductor
* Copyright (c) 2017 Savoir-faire Linux, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include "mv88e6xxx.h"
#include "global1.h"
/* Offset 0x01: ATU FID Register */
static int mv88e6xxx_g1_atu_fid_write(struct mv88e6xxx_chip *chip, u16 fid)
{
return mv88e6xxx_g1_write(chip, GLOBAL_ATU_FID, fid & 0xfff);
}
/* Offset 0x0A: ATU Control Register */
int mv88e6xxx_g1_atu_set_learn2all(struct mv88e6xxx_chip *chip, bool learn2all)
{
u16 val;
int err;
err = mv88e6xxx_g1_read(chip, GLOBAL_ATU_CONTROL, &val);
if (err)
return err;
if (learn2all)
val |= GLOBAL_ATU_CONTROL_LEARN2ALL;
else
val &= ~GLOBAL_ATU_CONTROL_LEARN2ALL;
return mv88e6xxx_g1_write(chip, GLOBAL_ATU_CONTROL, val);
}
int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip *chip,
unsigned int msecs)
{
const unsigned int coeff = chip->info->age_time_coeff;
const unsigned int min = 0x01 * coeff;
const unsigned int max = 0xff * coeff;
u8 age_time;
u16 val;
int err;
if (msecs < min || msecs > max)
return -ERANGE;
/* Round to nearest multiple of coeff */
age_time = (msecs + coeff / 2) / coeff;
err = mv88e6xxx_g1_read(chip, GLOBAL_ATU_CONTROL, &val);
if (err)
return err;
/* AgeTime is 11:4 bits */
val &= ~0xff0;
val |= age_time << 4;
return mv88e6xxx_g1_write(chip, GLOBAL_ATU_CONTROL, val);
}
/* Offset 0x0B: ATU Operation Register */
static int mv88e6xxx_g1_atu_op_wait(struct mv88e6xxx_chip *chip)
{
return mv88e6xxx_g1_wait(chip, GLOBAL_ATU_OP, GLOBAL_ATU_OP_BUSY);
}
static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op)
{
u16 val;
int err;
/* FID bits are dispatched all around gradually as more are supported */
if (mv88e6xxx_num_databases(chip) > 256) {
err = mv88e6xxx_g1_atu_fid_write(chip, fid);
if (err)
return err;
} else {
if (mv88e6xxx_num_databases(chip) > 16) {
/* ATU DBNum[7:4] are located in ATU Control 15:12 */
err = mv88e6xxx_g1_read(chip, GLOBAL_ATU_CONTROL, &val);
if (err)
return err;
val = (val & 0x0fff) | ((fid << 8) & 0xf000);
err = mv88e6xxx_g1_write(chip, GLOBAL_ATU_CONTROL, val);
if (err)
return err;
}
/* ATU DBNum[3:0] are located in ATU Operation 3:0 */
op |= fid & 0xf;
}
err = mv88e6xxx_g1_write(chip, GLOBAL_ATU_OP, op);
if (err)
return err;
return mv88e6xxx_g1_atu_op_wait(chip);
}
/* Offset 0x0C: ATU Data Register */
static int mv88e6xxx_g1_atu_data_read(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_atu_entry *entry)
{
u16 val;
int err;
err = mv88e6xxx_g1_read(chip, GLOBAL_ATU_DATA, &val);
if (err)
return err;
entry->state = val & 0xf;
if (entry->state != GLOBAL_ATU_DATA_STATE_UNUSED) {
if (val & GLOBAL_ATU_DATA_TRUNK)
entry->trunk = true;
entry->portvec = (val >> 4) & mv88e6xxx_port_mask(chip);
}
return 0;
}
static int mv88e6xxx_g1_atu_data_write(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_atu_entry *entry)
{
u16 data = entry->state & 0xf;
if (entry->state != GLOBAL_ATU_DATA_STATE_UNUSED) {
if (entry->trunk)
data |= GLOBAL_ATU_DATA_TRUNK;
data |= (entry->portvec & mv88e6xxx_port_mask(chip)) << 4;
}
return mv88e6xxx_g1_write(chip, GLOBAL_ATU_DATA, data);
}
/* Offset 0x0D: ATU MAC Address Register Bytes 0 & 1
* Offset 0x0E: ATU MAC Address Register Bytes 2 & 3
* Offset 0x0F: ATU MAC Address Register Bytes 4 & 5
*/
static int mv88e6xxx_g1_atu_mac_read(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_atu_entry *entry)
{
u16 val;
int i, err;
for (i = 0; i < 3; i++) {
err = mv88e6xxx_g1_read(chip, GLOBAL_ATU_MAC_01 + i, &val);
if (err)
return err;
entry->mac[i * 2] = val >> 8;
entry->mac[i * 2 + 1] = val & 0xff;
}
return 0;
}
static int mv88e6xxx_g1_atu_mac_write(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_atu_entry *entry)
{
u16 val;
int i, err;
for (i = 0; i < 3; i++) {
val = (entry->mac[i * 2] << 8) | entry->mac[i * 2 + 1];
err = mv88e6xxx_g1_write(chip, GLOBAL_ATU_MAC_01 + i, val);
if (err)
return err;
}
return 0;
}
/* Address Translation Unit operations */
int mv88e6xxx_g1_atu_getnext(struct mv88e6xxx_chip *chip, u16 fid,
struct mv88e6xxx_atu_entry *entry)
{
int err;
err = mv88e6xxx_g1_atu_op_wait(chip);
if (err)
return err;
/* Write the MAC address to iterate from only once */
if (entry->state == GLOBAL_ATU_DATA_STATE_UNUSED) {
err = mv88e6xxx_g1_atu_mac_write(chip, entry);
if (err)
return err;
}
err = mv88e6xxx_g1_atu_op(chip, fid, GLOBAL_ATU_OP_GET_NEXT_DB);
if (err)
return err;
err = mv88e6xxx_g1_atu_data_read(chip, entry);
if (err)
return err;
return mv88e6xxx_g1_atu_mac_read(chip, entry);
}
int mv88e6xxx_g1_atu_loadpurge(struct mv88e6xxx_chip *chip, u16 fid,
struct mv88e6xxx_atu_entry *entry)
{
int err;
err = mv88e6xxx_g1_atu_op_wait(chip);
if (err)
return err;
err = mv88e6xxx_g1_atu_mac_write(chip, entry);
if (err)
return err;
err = mv88e6xxx_g1_atu_data_write(chip, entry);
if (err)
return err;
return mv88e6xxx_g1_atu_op(chip, fid, GLOBAL_ATU_OP_LOAD_DB);
}
static int mv88e6xxx_g1_atu_flushmove(struct mv88e6xxx_chip *chip, u16 fid,
struct mv88e6xxx_atu_entry *entry,
bool all)
{
u16 op;
int err;
err = mv88e6xxx_g1_atu_op_wait(chip);
if (err)
return err;
err = mv88e6xxx_g1_atu_data_write(chip, entry);
if (err)
return err;
/* Flush/Move all or non-static entries from all or a given database */
if (all && fid)
op = GLOBAL_ATU_OP_FLUSH_MOVE_ALL_DB;
else if (fid)
op = GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC_DB;
else if (all)
op = GLOBAL_ATU_OP_FLUSH_MOVE_ALL;
else
op = GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC;
return mv88e6xxx_g1_atu_op(chip, fid, op);
}
int mv88e6xxx_g1_atu_flush(struct mv88e6xxx_chip *chip, u16 fid, bool all)
{
struct mv88e6xxx_atu_entry entry = {
.state = 0, /* Null EntryState means Flush */
};
return mv88e6xxx_g1_atu_flushmove(chip, fid, &entry, all);
}
static int mv88e6xxx_g1_atu_move(struct mv88e6xxx_chip *chip, u16 fid,
int from_port, int to_port, bool all)
{
struct mv88e6xxx_atu_entry entry = { 0 };
unsigned long mask;
int shift;
if (!chip->info->atu_move_port_mask)
return -EOPNOTSUPP;
mask = chip->info->atu_move_port_mask;
shift = bitmap_weight(&mask, 16);
entry.state = 0xf, /* Full EntryState means Move */
entry.portvec = from_port & mask;
entry.portvec |= (to_port & mask) << shift;
return mv88e6xxx_g1_atu_flushmove(chip, fid, &entry, all);
}
int mv88e6xxx_g1_atu_remove(struct mv88e6xxx_chip *chip, u16 fid, int port,
bool all)
{
int from_port = port;
int to_port = chip->info->atu_move_port_mask;
return mv88e6xxx_g1_atu_move(chip, fid, from_port, to_port, all);
}
...@@ -132,18 +132,19 @@ ...@@ -132,18 +132,19 @@
#define PORT_CONTROL_TAG_IF_BOTH BIT(6) #define PORT_CONTROL_TAG_IF_BOTH BIT(6)
#define PORT_CONTROL_USE_IP BIT(5) #define PORT_CONTROL_USE_IP BIT(5)
#define PORT_CONTROL_USE_TAG BIT(4) #define PORT_CONTROL_USE_TAG BIT(4)
#define PORT_CONTROL_FORWARD_UNKNOWN_MC BIT(3)
#define PORT_CONTROL_FORWARD_UNKNOWN BIT(2) #define PORT_CONTROL_FORWARD_UNKNOWN BIT(2)
#define PORT_CONTROL_NOT_EGRESS_UNKNOWN_DA (0x0 << 2) #define PORT_CONTROL_EGRESS_FLOODS_MASK (0x3 << 2)
#define PORT_CONTROL_NOT_EGRESS_UNKNOWN_MULTICAST_DA (0x1 << 2) #define PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_DA (0x0 << 2)
#define PORT_CONTROL_NOT_EGRESS_UNKNOWN_UNITCAST_DA (0x2 << 2) #define PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_MC_DA (0x1 << 2)
#define PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA (0x3 << 2) #define PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_UC_DA (0x2 << 2)
#define PORT_CONTROL_EGRESS_FLOODS_ALL_UNKNOWN_DA (0x3 << 2)
#define PORT_CONTROL_STATE_MASK 0x03 #define PORT_CONTROL_STATE_MASK 0x03
#define PORT_CONTROL_STATE_DISABLED 0x00 #define PORT_CONTROL_STATE_DISABLED 0x00
#define PORT_CONTROL_STATE_BLOCKING 0x01 #define PORT_CONTROL_STATE_BLOCKING 0x01
#define PORT_CONTROL_STATE_LEARNING 0x02 #define PORT_CONTROL_STATE_LEARNING 0x02
#define PORT_CONTROL_STATE_FORWARDING 0x03 #define PORT_CONTROL_STATE_FORWARDING 0x03
#define PORT_CONTROL_1 0x05 #define PORT_CONTROL_1 0x05
#define PORT_CONTROL_1_MESSAGE_PORT BIT(15)
#define PORT_CONTROL_1_FID_11_4_MASK (0xff << 0) #define PORT_CONTROL_1_FID_11_4_MASK (0xff << 0)
#define PORT_BASE_VLAN 0x06 #define PORT_BASE_VLAN 0x06
#define PORT_BASE_VLAN_FID_3_0_MASK (0xf << 12) #define PORT_BASE_VLAN_FID_3_0_MASK (0xf << 12)
...@@ -166,7 +167,6 @@ ...@@ -166,7 +167,6 @@
#define PORT_CONTROL_2_DISCARD_UNTAGGED BIT(8) #define PORT_CONTROL_2_DISCARD_UNTAGGED BIT(8)
#define PORT_CONTROL_2_MAP_DA BIT(7) #define PORT_CONTROL_2_MAP_DA BIT(7)
#define PORT_CONTROL_2_DEFAULT_FORWARD BIT(6) #define PORT_CONTROL_2_DEFAULT_FORWARD BIT(6)
#define PORT_CONTROL_2_FORWARD_UNKNOWN BIT(6)
#define PORT_CONTROL_2_EGRESS_MONITOR BIT(5) #define PORT_CONTROL_2_EGRESS_MONITOR BIT(5)
#define PORT_CONTROL_2_INGRESS_MONITOR BIT(4) #define PORT_CONTROL_2_INGRESS_MONITOR BIT(4)
#define PORT_CONTROL_2_UPSTREAM_MASK 0x0f #define PORT_CONTROL_2_UPSTREAM_MASK 0x0f
...@@ -181,6 +181,7 @@ ...@@ -181,6 +181,7 @@
#define PORT_ATU_CONTROL 0x0c #define PORT_ATU_CONTROL 0x0c
#define PORT_PRI_OVERRIDE 0x0d #define PORT_PRI_OVERRIDE 0x0d
#define PORT_ETH_TYPE 0x0f #define PORT_ETH_TYPE 0x0f
#define PORT_ETH_TYPE_DEFAULT 0x9100
#define PORT_IN_DISCARD_LO 0x10 #define PORT_IN_DISCARD_LO 0x10
#define PORT_IN_DISCARD_HI 0x11 #define PORT_IN_DISCARD_HI 0x11
#define PORT_IN_FILTERED 0x12 #define PORT_IN_FILTERED 0x12
...@@ -551,7 +552,6 @@ enum mv88e6xxx_cap { ...@@ -551,7 +552,6 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAG_SERDES BIT_ULL(MV88E6XXX_CAP_SERDES) #define MV88E6XXX_FLAG_SERDES BIT_ULL(MV88E6XXX_CAP_SERDES)
#define MV88E6XXX_FLAG_G1_ATU_FID BIT_ULL(MV88E6XXX_CAP_G1_ATU_FID)
#define MV88E6XXX_FLAG_G1_VTU_FID BIT_ULL(MV88E6XXX_CAP_G1_VTU_FID) #define MV88E6XXX_FLAG_G1_VTU_FID BIT_ULL(MV88E6XXX_CAP_G1_VTU_FID)
#define MV88E6XXX_FLAG_GLOBAL2 BIT_ULL(MV88E6XXX_CAP_GLOBAL2) #define MV88E6XXX_FLAG_GLOBAL2 BIT_ULL(MV88E6XXX_CAP_GLOBAL2)
...@@ -594,8 +594,7 @@ enum mv88e6xxx_cap { ...@@ -594,8 +594,7 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAGS_MULTI_CHIP) MV88E6XXX_FLAGS_MULTI_CHIP)
#define MV88E6XXX_FLAGS_FAMILY_6097 \ #define MV88E6XXX_FLAGS_FAMILY_6097 \
(MV88E6XXX_FLAG_G1_ATU_FID | \ (MV88E6XXX_FLAG_G1_VTU_FID | \
MV88E6XXX_FLAG_G1_VTU_FID | \
MV88E6XXX_FLAG_GLOBAL2 | \ MV88E6XXX_FLAG_GLOBAL2 | \
MV88E6XXX_FLAG_G2_INT | \ MV88E6XXX_FLAG_G2_INT | \
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
...@@ -608,8 +607,7 @@ enum mv88e6xxx_cap { ...@@ -608,8 +607,7 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAGS_PVT) MV88E6XXX_FLAGS_PVT)
#define MV88E6XXX_FLAGS_FAMILY_6165 \ #define MV88E6XXX_FLAGS_FAMILY_6165 \
(MV88E6XXX_FLAG_G1_ATU_FID | \ (MV88E6XXX_FLAG_G1_VTU_FID | \
MV88E6XXX_FLAG_G1_VTU_FID | \
MV88E6XXX_FLAG_GLOBAL2 | \ MV88E6XXX_FLAG_GLOBAL2 | \
MV88E6XXX_FLAG_G2_INT | \ MV88E6XXX_FLAG_G2_INT | \
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
...@@ -641,7 +639,6 @@ enum mv88e6xxx_cap { ...@@ -641,7 +639,6 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAGS_FAMILY_6341 \ #define MV88E6XXX_FLAGS_FAMILY_6341 \
(MV88E6XXX_FLAG_EEE | \ (MV88E6XXX_FLAG_EEE | \
MV88E6XXX_FLAG_G1_ATU_FID | \
MV88E6XXX_FLAG_G1_VTU_FID | \ MV88E6XXX_FLAG_G1_VTU_FID | \
MV88E6XXX_FLAG_GLOBAL2 | \ MV88E6XXX_FLAG_GLOBAL2 | \
MV88E6XXX_FLAG_G2_INT | \ MV88E6XXX_FLAG_G2_INT | \
...@@ -654,8 +651,7 @@ enum mv88e6xxx_cap { ...@@ -654,8 +651,7 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAGS_SERDES) MV88E6XXX_FLAGS_SERDES)
#define MV88E6XXX_FLAGS_FAMILY_6351 \ #define MV88E6XXX_FLAGS_FAMILY_6351 \
(MV88E6XXX_FLAG_G1_ATU_FID | \ (MV88E6XXX_FLAG_G1_VTU_FID | \
MV88E6XXX_FLAG_G1_VTU_FID | \
MV88E6XXX_FLAG_GLOBAL2 | \ MV88E6XXX_FLAG_GLOBAL2 | \
MV88E6XXX_FLAG_G2_INT | \ MV88E6XXX_FLAG_G2_INT | \
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
...@@ -669,7 +665,6 @@ enum mv88e6xxx_cap { ...@@ -669,7 +665,6 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAGS_FAMILY_6352 \ #define MV88E6XXX_FLAGS_FAMILY_6352 \
(MV88E6XXX_FLAG_EEE | \ (MV88E6XXX_FLAG_EEE | \
MV88E6XXX_FLAG_G1_ATU_FID | \
MV88E6XXX_FLAG_G1_VTU_FID | \ MV88E6XXX_FLAG_G1_VTU_FID | \
MV88E6XXX_FLAG_GLOBAL2 | \ MV88E6XXX_FLAG_GLOBAL2 | \
MV88E6XXX_FLAG_G2_INT | \ MV88E6XXX_FLAG_G2_INT | \
...@@ -707,14 +702,18 @@ struct mv88e6xxx_info { ...@@ -707,14 +702,18 @@ struct mv88e6xxx_info {
unsigned int g1_irqs; unsigned int g1_irqs;
enum dsa_tag_protocol tag_protocol; enum dsa_tag_protocol tag_protocol;
unsigned long long flags; unsigned long long flags;
/* Mask for FromPort and ToPort value of PortVec used in ATU Move
* operation. 0 means that the ATU Move operation is not supported.
*/
u8 atu_move_port_mask;
const struct mv88e6xxx_ops *ops; const struct mv88e6xxx_ops *ops;
}; };
struct mv88e6xxx_atu_entry { struct mv88e6xxx_atu_entry {
u16 fid;
u8 state; u8 state;
bool trunk; bool trunk;
u16 portv_trunkid; u16 portvec;
u8 mac[ETH_ALEN]; u8 mac[ETH_ALEN];
}; };
...@@ -864,14 +863,16 @@ struct mv88e6xxx_ops { ...@@ -864,14 +863,16 @@ struct mv88e6xxx_ops {
int (*port_set_frame_mode)(struct mv88e6xxx_chip *chip, int port, int (*port_set_frame_mode)(struct mv88e6xxx_chip *chip, int port,
enum mv88e6xxx_frame_mode mode); enum mv88e6xxx_frame_mode mode);
int (*port_set_egress_unknowns)(struct mv88e6xxx_chip *chip, int port, int (*port_set_egress_floods)(struct mv88e6xxx_chip *chip, int port,
bool on); bool unicast, bool multicast);
int (*port_set_ether_type)(struct mv88e6xxx_chip *chip, int port, int (*port_set_ether_type)(struct mv88e6xxx_chip *chip, int port,
u16 etype); u16 etype);
int (*port_jumbo_config)(struct mv88e6xxx_chip *chip, int port); int (*port_jumbo_config)(struct mv88e6xxx_chip *chip, int port);
int (*port_egress_rate_limiting)(struct mv88e6xxx_chip *chip, int port); int (*port_egress_rate_limiting)(struct mv88e6xxx_chip *chip, int port);
int (*port_pause_config)(struct mv88e6xxx_chip *chip, int port); int (*port_pause_config)(struct mv88e6xxx_chip *chip, int port);
int (*port_disable_learn_limit)(struct mv88e6xxx_chip *chip, int port);
int (*port_disable_pri_override)(struct mv88e6xxx_chip *chip, int port);
/* CMODE control what PHY mode the MAC will use, eg. SGMII, RGMII, etc. /* CMODE control what PHY mode the MAC will use, eg. SGMII, RGMII, etc.
* Some chips allow this to be configured on specific ports. * Some chips allow this to be configured on specific ports.
...@@ -944,6 +945,11 @@ static inline unsigned int mv88e6xxx_num_ports(struct mv88e6xxx_chip *chip) ...@@ -944,6 +945,11 @@ static inline unsigned int mv88e6xxx_num_ports(struct mv88e6xxx_chip *chip)
return chip->info->num_ports; return chip->info->num_ports;
} }
static inline u16 mv88e6xxx_port_mask(struct mv88e6xxx_chip *chip)
{
return GENMASK(mv88e6xxx_num_ports(chip) - 1, 0);
}
int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val); int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val);
int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val); int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val);
int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg,
......
...@@ -497,8 +497,8 @@ int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port, ...@@ -497,8 +497,8 @@ int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
} }
int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, static int mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip *chip,
bool on) int port, bool unicast)
{ {
int err; int err;
u16 reg; u16 reg;
...@@ -507,7 +507,7 @@ int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, ...@@ -507,7 +507,7 @@ int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
if (err) if (err)
return err; return err;
if (on) if (unicast)
reg |= PORT_CONTROL_FORWARD_UNKNOWN; reg |= PORT_CONTROL_FORWARD_UNKNOWN;
else else
reg &= ~PORT_CONTROL_FORWARD_UNKNOWN; reg &= ~PORT_CONTROL_FORWARD_UNKNOWN;
...@@ -515,8 +515,8 @@ int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, ...@@ -515,8 +515,8 @@ int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
} }
int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
bool on) bool unicast, bool multicast)
{ {
int err; int err;
u16 reg; u16 reg;
...@@ -525,21 +525,45 @@ int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, ...@@ -525,21 +525,45 @@ int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
if (err) if (err)
return err; return err;
if (on) reg &= ~PORT_CONTROL_EGRESS_FLOODS_MASK;
reg |= PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA;
if (unicast && multicast)
reg |= PORT_CONTROL_EGRESS_FLOODS_ALL_UNKNOWN_DA;
else if (unicast)
reg |= PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_MC_DA;
else if (multicast)
reg |= PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_UC_DA;
else else
reg &= ~PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA; reg |= PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_DA;
return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
} }
/* Offset 0x05: Port Control 1 */ /* Offset 0x05: Port Control 1 */
int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
bool message_port)
{
u16 val;
int err;
err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, &val);
if (err)
return err;
if (message_port)
val |= PORT_CONTROL_1_MESSAGE_PORT;
else
val &= ~PORT_CONTROL_1_MESSAGE_PORT;
return mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, val);
}
/* Offset 0x06: Port Based VLAN Map */ /* Offset 0x06: Port Based VLAN Map */
int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map) int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map)
{ {
const u16 mask = GENMASK(mv88e6xxx_num_ports(chip) - 1, 0); const u16 mask = mv88e6xxx_port_mask(chip);
u16 reg; u16 reg;
int err; int err;
...@@ -672,8 +696,8 @@ static const char * const mv88e6xxx_port_8021q_mode_names[] = { ...@@ -672,8 +696,8 @@ static const char * const mv88e6xxx_port_8021q_mode_names[] = {
[PORT_CONTROL_2_8021Q_SECURE] = "Secure", [PORT_CONTROL_2_8021Q_SECURE] = "Secure",
}; };
int mv88e6095_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, static int mv88e6185_port_set_default_forward(struct mv88e6xxx_chip *chip,
bool on) int port, bool multicast)
{ {
int err; int err;
u16 reg; u16 reg;
...@@ -682,14 +706,26 @@ int mv88e6095_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, ...@@ -682,14 +706,26 @@ int mv88e6095_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
if (err) if (err)
return err; return err;
if (on) if (multicast)
reg |= PORT_CONTROL_2_FORWARD_UNKNOWN; reg |= PORT_CONTROL_2_DEFAULT_FORWARD;
else else
reg &= ~PORT_CONTROL_2_FORWARD_UNKNOWN; reg &= ~PORT_CONTROL_2_DEFAULT_FORWARD;
return mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg); return mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
} }
int mv88e6185_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
bool unicast, bool multicast)
{
int err;
err = mv88e6185_port_set_forward_unknown(chip, port, unicast);
if (err)
return err;
return mv88e6185_port_set_default_forward(chip, port, multicast);
}
int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port, int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
int upstream_port) int upstream_port)
{ {
...@@ -769,6 +805,20 @@ int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port) ...@@ -769,6 +805,20 @@ int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
return mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL, 0x0001); return mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL, 0x0001);
} }
/* Offset 0x0C: Port ATU Control */
int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port)
{
return mv88e6xxx_port_write(chip, port, PORT_ATU_CONTROL, 0);
}
/* Offset 0x0D: (Priority) Override Register */
int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port)
{
return mv88e6xxx_port_write(chip, port, PORT_PRI_OVERRIDE, 0);
}
/* Offset 0x0f: Port Ether type */ /* Offset 0x0f: Port Ether type */
int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port, int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
......
...@@ -56,14 +56,14 @@ int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port, ...@@ -56,14 +56,14 @@ int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
enum mv88e6xxx_frame_mode mode); enum mv88e6xxx_frame_mode mode);
int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port, int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
enum mv88e6xxx_frame_mode mode); enum mv88e6xxx_frame_mode mode);
int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, int mv88e6185_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
bool on); bool unicast, bool multicast);
int mv88e6095_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
bool on); bool unicast, bool multicast);
int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
bool on);
int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port, int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
u16 etype); u16 etype);
int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
bool message_port);
int mv88e6165_port_jumbo_config(struct mv88e6xxx_chip *chip, int port); int mv88e6165_port_jumbo_config(struct mv88e6xxx_chip *chip, int port);
int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port); int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port); int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
...@@ -75,4 +75,8 @@ int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode); ...@@ -75,4 +75,8 @@ int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port); int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port);
int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port, int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
int upstream_port); int upstream_port);
int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port);
int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port);
#endif /* _MV88E6XXX_PORT_H */ #endif /* _MV88E6XXX_PORT_H */
...@@ -446,21 +446,6 @@ static inline void eth_addr_dec(u8 *addr) ...@@ -446,21 +446,6 @@ static inline void eth_addr_dec(u8 *addr)
u64_to_ether_addr(u, addr); u64_to_ether_addr(u, addr);
} }
/**
* ether_addr_greater - Compare two Ethernet addresses
* @addr1: Pointer to a six-byte array containing the Ethernet address
* @addr2: Pointer other six-byte array containing the Ethernet address
*
* Compare two Ethernet addresses, returns true addr1 is greater than addr2
*/
static inline bool ether_addr_greater(const u8 *addr1, const u8 *addr2)
{
u64 u1 = ether_addr_to_u64(addr1);
u64 u2 = ether_addr_to_u64(addr2);
return u1 > u2;
}
/** /**
* is_etherdev_addr - Tell if given Ethernet address belongs to the device. * is_etherdev_addr - Tell if given Ethernet address belongs to the device.
* @dev: Pointer to a device structure * @dev: Pointer to a device structure
......
...@@ -248,6 +248,11 @@ static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p) ...@@ -248,6 +248,11 @@ static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p)
return !!((ds->dsa_port_mask) & (1 << p)); return !!((ds->dsa_port_mask) & (1 << p));
} }
static inline bool dsa_is_normal_port(struct dsa_switch *ds, int p)
{
return !dsa_is_cpu_port(ds, p) && !dsa_is_dsa_port(ds, p);
}
static inline bool dsa_is_port_initialized(struct dsa_switch *ds, int p) static inline bool dsa_is_port_initialized(struct dsa_switch *ds, int p)
{ {
return ds->enabled_port_mask & (1 << p) && ds->ports[p].netdev; return ds->enabled_port_mask & (1 << p) && ds->ports[p].netdev;
......
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