Commit f82389ee authored by Paolo Abeni's avatar Paolo Abeni

Merge branch 'net-dsa-microchip-add-mtu-support-for-ksz8-series'

Oleksij Rempel says:

====================
net: dsa: microchip: add MTU support for KSZ8 series
====================

Link: https://lore.kernel.org/r/20221205052232.2834166-1-o.rempel@pengutronix.deSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents e22dcbc9 55a952ee
...@@ -57,5 +57,6 @@ int ksz8_reset_switch(struct ksz_device *dev); ...@@ -57,5 +57,6 @@ int ksz8_reset_switch(struct ksz_device *dev);
int ksz8_switch_detect(struct ksz_device *dev); int ksz8_switch_detect(struct ksz_device *dev);
int ksz8_switch_init(struct ksz_device *dev); int ksz8_switch_init(struct ksz_device *dev);
void ksz8_switch_exit(struct ksz_device *dev); void ksz8_switch_exit(struct ksz_device *dev);
int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu);
#endif #endif
...@@ -76,6 +76,57 @@ int ksz8_reset_switch(struct ksz_device *dev) ...@@ -76,6 +76,57 @@ int ksz8_reset_switch(struct ksz_device *dev)
return 0; return 0;
} }
static int ksz8863_change_mtu(struct ksz_device *dev, int frame_size)
{
u8 ctrl2 = 0;
if (frame_size <= KSZ8_LEGAL_PACKET_SIZE)
ctrl2 |= KSZ8863_LEGAL_PACKET_ENABLE;
else if (frame_size > KSZ8863_NORMAL_PACKET_SIZE)
ctrl2 |= KSZ8863_HUGE_PACKET_ENABLE;
return ksz_rmw8(dev, REG_SW_CTRL_2, KSZ8863_LEGAL_PACKET_ENABLE |
KSZ8863_HUGE_PACKET_ENABLE, ctrl2);
}
static int ksz8795_change_mtu(struct ksz_device *dev, int frame_size)
{
u8 ctrl1 = 0, ctrl2 = 0;
int ret;
if (frame_size > KSZ8_LEGAL_PACKET_SIZE)
ctrl2 |= SW_LEGAL_PACKET_DISABLE;
else if (frame_size > KSZ8863_NORMAL_PACKET_SIZE)
ctrl1 |= SW_HUGE_PACKET;
ret = ksz_rmw8(dev, REG_SW_CTRL_1, SW_HUGE_PACKET, ctrl1);
if (ret)
return ret;
return ksz_rmw8(dev, REG_SW_CTRL_2, SW_LEGAL_PACKET_DISABLE, ctrl2);
}
int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu)
{
u16 frame_size;
if (!dsa_is_cpu_port(dev->ds, port))
return 0;
frame_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
switch (dev->chip_id) {
case KSZ8795_CHIP_ID:
case KSZ8794_CHIP_ID:
case KSZ8765_CHIP_ID:
return ksz8795_change_mtu(dev, frame_size);
case KSZ8830_CHIP_ID:
return ksz8863_change_mtu(dev, frame_size);
}
return -EOPNOTSUPP;
}
static void ksz8795_set_prio_queue(struct ksz_device *dev, int port, int queue) static void ksz8795_set_prio_queue(struct ksz_device *dev, int port, int queue)
{ {
u8 hi, lo; u8 hi, lo;
...@@ -1233,8 +1284,6 @@ void ksz8_config_cpu_port(struct dsa_switch *ds) ...@@ -1233,8 +1284,6 @@ void ksz8_config_cpu_port(struct dsa_switch *ds)
masks = dev->info->masks; masks = dev->info->masks;
regs = dev->info->regs; regs = dev->info->regs;
/* Switch marks the maximum frame with extra byte as oversize. */
ksz_cfg(dev, REG_SW_CTRL_2, SW_LEGAL_PACKET_DISABLE, true);
ksz_cfg(dev, regs[S_TAIL_TAG_CTRL], masks[SW_TAIL_TAG_ENABLE], true); ksz_cfg(dev, regs[S_TAIL_TAG_CTRL], masks[SW_TAIL_TAG_ENABLE], true);
p = &dev->ports[dev->cpu_port]; p = &dev->ports[dev->cpu_port];
...@@ -1308,6 +1357,18 @@ int ksz8_setup(struct dsa_switch *ds) ...@@ -1308,6 +1357,18 @@ int ksz8_setup(struct dsa_switch *ds)
struct ksz_device *dev = ds->priv; struct ksz_device *dev = ds->priv;
int i; int i;
ds->mtu_enforcement_ingress = true;
/* We rely on software untagging on the CPU port, so that we
* can support both tagged and untagged VLANs
*/
ds->untag_bridge_pvid = true;
/* VLAN filtering is partly controlled by the global VLAN
* Enable flag
*/
ds->vlan_filtering_is_global = true;
ksz_cfg(dev, S_REPLACE_VID_CTRL, SW_FLOW_CTRL, true); ksz_cfg(dev, S_REPLACE_VID_CTRL, SW_FLOW_CTRL, true);
/* Enable automatic fast aging when link changed detected. */ /* Enable automatic fast aging when link changed detected. */
...@@ -1367,16 +1428,6 @@ int ksz8_switch_init(struct ksz_device *dev) ...@@ -1367,16 +1428,6 @@ int ksz8_switch_init(struct ksz_device *dev)
dev->phy_port_cnt = dev->info->port_cnt - 1; dev->phy_port_cnt = dev->info->port_cnt - 1;
dev->port_mask = (BIT(dev->phy_port_cnt) - 1) | dev->info->cpu_ports; dev->port_mask = (BIT(dev->phy_port_cnt) - 1) | dev->info->cpu_ports;
/* We rely on software untagging on the CPU port, so that we
* can support both tagged and untagged VLANs
*/
dev->ds->untag_bridge_pvid = true;
/* VLAN filtering is partly controlled by the global VLAN
* Enable flag
*/
dev->ds->vlan_filtering_is_global = true;
return 0; return 0;
} }
......
...@@ -48,6 +48,9 @@ ...@@ -48,6 +48,9 @@
#define NO_EXC_COLLISION_DROP BIT(3) #define NO_EXC_COLLISION_DROP BIT(3)
#define SW_LEGAL_PACKET_DISABLE BIT(1) #define SW_LEGAL_PACKET_DISABLE BIT(1)
#define KSZ8863_HUGE_PACKET_ENABLE BIT(2)
#define KSZ8863_LEGAL_PACKET_ENABLE BIT(1)
#define REG_SW_CTRL_3 0x05 #define REG_SW_CTRL_3 0x05
#define WEIGHTED_FAIR_QUEUE_ENABLE BIT(3) #define WEIGHTED_FAIR_QUEUE_ENABLE BIT(3)
......
...@@ -45,24 +45,15 @@ static void ksz9477_port_cfg32(struct ksz_device *dev, int port, int offset, ...@@ -45,24 +45,15 @@ static void ksz9477_port_cfg32(struct ksz_device *dev, int port, int offset,
int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu) int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu)
{ {
u16 frame_size, max_frame = 0; u16 frame_size;
int i;
frame_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
/* Cache the per-port MTU setting */ if (!dsa_is_cpu_port(dev->ds, port))
dev->ports[port].max_frame = frame_size; return 0;
for (i = 0; i < dev->info->port_cnt; i++) frame_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
max_frame = max(max_frame, dev->ports[i].max_frame);
return regmap_update_bits(dev->regmap[1], REG_SW_MTU__2, return regmap_update_bits(dev->regmap[1], REG_SW_MTU__2,
REG_SW_MTU_MASK, max_frame); REG_SW_MTU_MASK, frame_size);
}
int ksz9477_max_mtu(struct ksz_device *dev, int port)
{
return KSZ9477_MAX_FRAME_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;
} }
static int ksz9477_wait_vlan_ctrl_ready(struct ksz_device *dev) static int ksz9477_wait_vlan_ctrl_ready(struct ksz_device *dev)
...@@ -1143,6 +1134,8 @@ int ksz9477_setup(struct dsa_switch *ds) ...@@ -1143,6 +1134,8 @@ int ksz9477_setup(struct dsa_switch *ds)
struct ksz_device *dev = ds->priv; struct ksz_device *dev = ds->priv;
int ret = 0; int ret = 0;
ds->mtu_enforcement_ingress = true;
/* Required for port partitioning. */ /* Required for port partitioning. */
ksz9477_cfg32(dev, REG_SW_QM_CTRL__4, UNICAST_VLAN_BOUNDARY, ksz9477_cfg32(dev, REG_SW_QM_CTRL__4, UNICAST_VLAN_BOUNDARY,
true); true);
......
...@@ -50,7 +50,6 @@ int ksz9477_mdb_add(struct ksz_device *dev, int port, ...@@ -50,7 +50,6 @@ int ksz9477_mdb_add(struct ksz_device *dev, int port,
int ksz9477_mdb_del(struct ksz_device *dev, int port, int ksz9477_mdb_del(struct ksz_device *dev, int port,
const struct switchdev_obj_port_mdb *mdb, struct dsa_db db); const struct switchdev_obj_port_mdb *mdb, struct dsa_db db);
int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu); int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu);
int ksz9477_max_mtu(struct ksz_device *dev, int port);
void ksz9477_config_cpu_port(struct dsa_switch *ds); void ksz9477_config_cpu_port(struct dsa_switch *ds);
int ksz9477_enable_stp_addr(struct ksz_device *dev); int ksz9477_enable_stp_addr(struct ksz_device *dev);
int ksz9477_reset_switch(struct ksz_device *dev); int ksz9477_reset_switch(struct ksz_device *dev);
......
...@@ -1615,6 +1615,4 @@ ...@@ -1615,6 +1615,4 @@
#define PTP_TRIG_UNIT_M (BIT(MAX_TRIG_UNIT) - 1) #define PTP_TRIG_UNIT_M (BIT(MAX_TRIG_UNIT) - 1)
#define PTP_TS_UNIT_M (BIT(MAX_TIMESTAMP_UNIT) - 1) #define PTP_TS_UNIT_M (BIT(MAX_TIMESTAMP_UNIT) - 1)
#define KSZ9477_MAX_FRAME_SIZE 9000
#endif /* KSZ9477_REGS_H */ #endif /* KSZ9477_REGS_H */
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/if_bridge.h> #include <linux/if_bridge.h>
#include <linux/if_vlan.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/of_mdio.h> #include <linux/of_mdio.h>
...@@ -171,6 +172,7 @@ static const struct ksz_dev_ops ksz8_dev_ops = { ...@@ -171,6 +172,7 @@ static const struct ksz_dev_ops ksz8_dev_ops = {
.reset = ksz8_reset_switch, .reset = ksz8_reset_switch,
.init = ksz8_switch_init, .init = ksz8_switch_init,
.exit = ksz8_switch_exit, .exit = ksz8_switch_exit,
.change_mtu = ksz8_change_mtu,
}; };
static void ksz9477_phylink_mac_link_up(struct ksz_device *dev, int port, static void ksz9477_phylink_mac_link_up(struct ksz_device *dev, int port,
...@@ -206,7 +208,6 @@ static const struct ksz_dev_ops ksz9477_dev_ops = { ...@@ -206,7 +208,6 @@ static const struct ksz_dev_ops ksz9477_dev_ops = {
.mdb_add = ksz9477_mdb_add, .mdb_add = ksz9477_mdb_add,
.mdb_del = ksz9477_mdb_del, .mdb_del = ksz9477_mdb_del,
.change_mtu = ksz9477_change_mtu, .change_mtu = ksz9477_change_mtu,
.max_mtu = ksz9477_max_mtu,
.phylink_mac_link_up = ksz9477_phylink_mac_link_up, .phylink_mac_link_up = ksz9477_phylink_mac_link_up,
.config_cpu_port = ksz9477_config_cpu_port, .config_cpu_port = ksz9477_config_cpu_port,
.enable_stp_addr = ksz9477_enable_stp_addr, .enable_stp_addr = ksz9477_enable_stp_addr,
...@@ -243,7 +244,6 @@ static const struct ksz_dev_ops lan937x_dev_ops = { ...@@ -243,7 +244,6 @@ static const struct ksz_dev_ops lan937x_dev_ops = {
.mdb_add = ksz9477_mdb_add, .mdb_add = ksz9477_mdb_add,
.mdb_del = ksz9477_mdb_del, .mdb_del = ksz9477_mdb_del,
.change_mtu = lan937x_change_mtu, .change_mtu = lan937x_change_mtu,
.max_mtu = ksz9477_max_mtu,
.phylink_mac_link_up = ksz9477_phylink_mac_link_up, .phylink_mac_link_up = ksz9477_phylink_mac_link_up,
.config_cpu_port = lan937x_config_cpu_port, .config_cpu_port = lan937x_config_cpu_port,
.enable_stp_addr = ksz9477_enable_stp_addr, .enable_stp_addr = ksz9477_enable_stp_addr,
...@@ -2500,10 +2500,29 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port) ...@@ -2500,10 +2500,29 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port)
{ {
struct ksz_device *dev = ds->priv; struct ksz_device *dev = ds->priv;
if (!dev->dev_ops->max_mtu) switch (dev->chip_id) {
return -EOPNOTSUPP; case KSZ8795_CHIP_ID:
case KSZ8794_CHIP_ID:
case KSZ8765_CHIP_ID:
return KSZ8795_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;
case KSZ8830_CHIP_ID:
return KSZ8863_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;
case KSZ8563_CHIP_ID:
case KSZ9477_CHIP_ID:
case KSZ9563_CHIP_ID:
case KSZ9567_CHIP_ID:
case KSZ9893_CHIP_ID:
case KSZ9896_CHIP_ID:
case KSZ9897_CHIP_ID:
case LAN9370_CHIP_ID:
case LAN9371_CHIP_ID:
case LAN9372_CHIP_ID:
case LAN9373_CHIP_ID:
case LAN9374_CHIP_ID:
return KSZ9477_MAX_FRAME_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;
}
return dev->dev_ops->max_mtu(dev, port); return -EOPNOTSUPP;
} }
static void ksz_set_xmii(struct ksz_device *dev, int port, static void ksz_set_xmii(struct ksz_device *dev, int port,
......
...@@ -95,7 +95,6 @@ struct ksz_port { ...@@ -95,7 +95,6 @@ struct ksz_port {
struct ksz_port_mib mib; struct ksz_port_mib mib;
phy_interface_t interface; phy_interface_t interface;
u16 max_frame;
u32 rgmii_tx_val; u32 rgmii_tx_val;
u32 rgmii_rx_val; u32 rgmii_rx_val;
struct ksz_device *ksz_dev; struct ksz_device *ksz_dev;
...@@ -322,7 +321,6 @@ struct ksz_dev_ops { ...@@ -322,7 +321,6 @@ struct ksz_dev_ops {
void (*get_caps)(struct ksz_device *dev, int port, void (*get_caps)(struct ksz_device *dev, int port,
struct phylink_config *config); struct phylink_config *config);
int (*change_mtu)(struct ksz_device *dev, int port, int mtu); int (*change_mtu)(struct ksz_device *dev, int port, int mtu);
int (*max_mtu)(struct ksz_device *dev, int port);
void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze); void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze);
void (*port_init_cnt)(struct ksz_device *dev, int port); void (*port_init_cnt)(struct ksz_device *dev, int port);
void (*phylink_mac_config)(struct ksz_device *dev, int port, void (*phylink_mac_config)(struct ksz_device *dev, int port,
...@@ -456,6 +454,11 @@ static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value) ...@@ -456,6 +454,11 @@ static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value)
return regmap_bulk_write(dev->regmap[2], reg, val, 2); return regmap_bulk_write(dev->regmap[2], reg, val, 2);
} }
static inline int ksz_rmw8(struct ksz_device *dev, int offset, u8 mask, u8 val)
{
return regmap_update_bits(dev->regmap[0], offset, mask, val);
}
static inline int ksz_pread8(struct ksz_device *dev, int port, int offset, static inline int ksz_pread8(struct ksz_device *dev, int port, int offset,
u8 *data) u8 *data)
{ {
...@@ -588,6 +591,12 @@ static inline int is_lan937x(struct ksz_device *dev) ...@@ -588,6 +591,12 @@ static inline int is_lan937x(struct ksz_device *dev)
#define PORT_SRC_PHY_INT 1 #define PORT_SRC_PHY_INT 1
#define KSZ8795_HUGE_PACKET_SIZE 2000
#define KSZ8863_HUGE_PACKET_SIZE 1916
#define KSZ8863_NORMAL_PACKET_SIZE 1536
#define KSZ8_LEGAL_PACKET_SIZE 1518
#define KSZ9477_MAX_FRAME_SIZE 9000
/* Regmap tables generation */ /* Regmap tables generation */
#define KSZ_SPI_OP_RD 3 #define KSZ_SPI_OP_RD 3
#define KSZ_SPI_OP_WR 2 #define KSZ_SPI_OP_WR 2
......
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