Commit 0f729970 authored by Paolo Abeni's avatar Paolo Abeni

Merge branch 'net-dsa-microchip-ksz8-enhance-static-mac-table-operations-and-error-handling'

Oleksij Rempel says:

====================
net: dsa: microchip: ksz8: Enhance static MAC table operations and error handling

This patch series improves the Microchip ksz8 driver by refactoring
static MAC table operations for code reuse, implementing add/del_fdb
functions, and making better use of error values in
ksz8_r_sta_mac_table() and ksz8_w_sta_mac_table(). The changes aim to
provide a more robust and maintainable driver with improved error
handling.
====================

Link: https://lore.kernel.org/r/20230404101842.1382986-1-o.rempel@pengutronix.deSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents b536f32b 3c2e6b54
...@@ -21,10 +21,6 @@ int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val); ...@@ -21,10 +21,6 @@ int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val); int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr, u8 *mac_addr, int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr, u8 *mac_addr,
u8 *fid, u8 *src_port, u8 *timestamp, u16 *entries); u8 *fid, u8 *src_port, u8 *timestamp, u16 *entries);
int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr,
struct alu_struct *alu);
void ksz8_w_sta_mac_table(struct ksz_device *dev, u16 addr,
struct alu_struct *alu);
void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt); void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt);
void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
u64 *dropped, u64 *cnt); u64 *dropped, u64 *cnt);
...@@ -32,6 +28,10 @@ void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze); ...@@ -32,6 +28,10 @@ void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze);
void ksz8_port_init_cnt(struct ksz_device *dev, int port); void ksz8_port_init_cnt(struct ksz_device *dev, int port);
int ksz8_fdb_dump(struct ksz_device *dev, int port, int ksz8_fdb_dump(struct ksz_device *dev, int port,
dsa_fdb_dump_cb_t *cb, void *data); dsa_fdb_dump_cb_t *cb, void *data);
int ksz8_fdb_add(struct ksz_device *dev, int port, const unsigned char *addr,
u16 vid, struct dsa_db db);
int ksz8_fdb_del(struct ksz_device *dev, int port, const unsigned char *addr,
u16 vid, struct dsa_db db);
int ksz8_mdb_add(struct ksz_device *dev, int port, int ksz8_mdb_add(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 ksz8_mdb_del(struct ksz_device *dev, int port, int ksz8_mdb_del(struct ksz_device *dev, int port,
......
...@@ -336,34 +336,48 @@ void ksz8_port_init_cnt(struct ksz_device *dev, int port) ...@@ -336,34 +336,48 @@ void ksz8_port_init_cnt(struct ksz_device *dev, int port)
} }
} }
static void ksz8_r_table(struct ksz_device *dev, int table, u16 addr, u64 *data) static int ksz8_r_table(struct ksz_device *dev, int table, u16 addr, u64 *data)
{ {
const u16 *regs; const u16 *regs;
u16 ctrl_addr; u16 ctrl_addr;
int ret;
regs = dev->info->regs; regs = dev->info->regs;
ctrl_addr = IND_ACC_TABLE(table | TABLE_READ) | addr; ctrl_addr = IND_ACC_TABLE(table | TABLE_READ) | addr;
mutex_lock(&dev->alu_mutex); mutex_lock(&dev->alu_mutex);
ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr); ret = ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr);
ksz_read64(dev, regs[REG_IND_DATA_HI], data); if (ret)
goto unlock_alu;
ret = ksz_read64(dev, regs[REG_IND_DATA_HI], data);
unlock_alu:
mutex_unlock(&dev->alu_mutex); mutex_unlock(&dev->alu_mutex);
return ret;
} }
static void ksz8_w_table(struct ksz_device *dev, int table, u16 addr, u64 data) static int ksz8_w_table(struct ksz_device *dev, int table, u16 addr, u64 data)
{ {
const u16 *regs; const u16 *regs;
u16 ctrl_addr; u16 ctrl_addr;
int ret;
regs = dev->info->regs; regs = dev->info->regs;
ctrl_addr = IND_ACC_TABLE(table) | addr; ctrl_addr = IND_ACC_TABLE(table) | addr;
mutex_lock(&dev->alu_mutex); mutex_lock(&dev->alu_mutex);
ksz_write64(dev, regs[REG_IND_DATA_HI], data); ret = ksz_write64(dev, regs[REG_IND_DATA_HI], data);
ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr); if (ret)
goto unlock_alu;
ret = ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr);
unlock_alu:
mutex_unlock(&dev->alu_mutex); mutex_unlock(&dev->alu_mutex);
return ret;
} }
static int ksz8_valid_dyn_entry(struct ksz_device *dev, u8 *data) static int ksz8_valid_dyn_entry(struct ksz_device *dev, u8 *data)
...@@ -457,46 +471,54 @@ int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr, u8 *mac_addr, ...@@ -457,46 +471,54 @@ int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr, u8 *mac_addr,
return rc; return rc;
} }
int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr, static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr,
struct alu_struct *alu) struct alu_struct *alu, bool *valid)
{ {
u32 data_hi, data_lo; u32 data_hi, data_lo;
const u8 *shifts; const u8 *shifts;
const u32 *masks; const u32 *masks;
u64 data; u64 data;
int ret;
shifts = dev->info->shifts; shifts = dev->info->shifts;
masks = dev->info->masks; masks = dev->info->masks;
ksz8_r_table(dev, TABLE_STATIC_MAC, addr, &data); ret = ksz8_r_table(dev, TABLE_STATIC_MAC, addr, &data);
if (ret)
return ret;
data_hi = data >> 32; data_hi = data >> 32;
data_lo = (u32)data; data_lo = (u32)data;
if (data_hi & (masks[STATIC_MAC_TABLE_VALID] |
masks[STATIC_MAC_TABLE_OVERRIDE])) { if (!(data_hi & (masks[STATIC_MAC_TABLE_VALID] |
alu->mac[5] = (u8)data_lo; masks[STATIC_MAC_TABLE_OVERRIDE]))) {
alu->mac[4] = (u8)(data_lo >> 8); *valid = false;
alu->mac[3] = (u8)(data_lo >> 16);
alu->mac[2] = (u8)(data_lo >> 24);
alu->mac[1] = (u8)data_hi;
alu->mac[0] = (u8)(data_hi >> 8);
alu->port_forward =
(data_hi & masks[STATIC_MAC_TABLE_FWD_PORTS]) >>
shifts[STATIC_MAC_FWD_PORTS];
alu->is_override =
(data_hi & masks[STATIC_MAC_TABLE_OVERRIDE]) ? 1 : 0;
data_hi >>= 1;
alu->is_static = true;
alu->is_use_fid =
(data_hi & masks[STATIC_MAC_TABLE_USE_FID]) ? 1 : 0;
alu->fid = (data_hi & masks[STATIC_MAC_TABLE_FID]) >>
shifts[STATIC_MAC_FID];
return 0; return 0;
} }
return -ENXIO;
alu->mac[5] = (u8)data_lo;
alu->mac[4] = (u8)(data_lo >> 8);
alu->mac[3] = (u8)(data_lo >> 16);
alu->mac[2] = (u8)(data_lo >> 24);
alu->mac[1] = (u8)data_hi;
alu->mac[0] = (u8)(data_hi >> 8);
alu->port_forward =
(data_hi & masks[STATIC_MAC_TABLE_FWD_PORTS]) >>
shifts[STATIC_MAC_FWD_PORTS];
alu->is_override = (data_hi & masks[STATIC_MAC_TABLE_OVERRIDE]) ? 1 : 0;
data_hi >>= 1;
alu->is_static = true;
alu->is_use_fid = (data_hi & masks[STATIC_MAC_TABLE_USE_FID]) ? 1 : 0;
alu->fid = (data_hi & masks[STATIC_MAC_TABLE_FID]) >>
shifts[STATIC_MAC_FID];
*valid = true;
return 0;
} }
void ksz8_w_sta_mac_table(struct ksz_device *dev, u16 addr, static int ksz8_w_sta_mac_table(struct ksz_device *dev, u16 addr,
struct alu_struct *alu) struct alu_struct *alu)
{ {
u32 data_hi, data_lo; u32 data_hi, data_lo;
const u8 *shifts; const u8 *shifts;
...@@ -524,7 +546,8 @@ void ksz8_w_sta_mac_table(struct ksz_device *dev, u16 addr, ...@@ -524,7 +546,8 @@ void ksz8_w_sta_mac_table(struct ksz_device *dev, u16 addr,
data_hi &= ~masks[STATIC_MAC_TABLE_OVERRIDE]; data_hi &= ~masks[STATIC_MAC_TABLE_OVERRIDE];
data = (u64)data_hi << 32 | data_lo; data = (u64)data_hi << 32 | data_lo;
ksz8_w_table(dev, TABLE_STATIC_MAC, addr, data);
return ksz8_w_table(dev, TABLE_STATIC_MAC, addr, data);
} }
static void ksz8_from_vlan(struct ksz_device *dev, u32 vlan, u8 *fid, static void ksz8_from_vlan(struct ksz_device *dev, u32 vlan, u8 *fid,
...@@ -977,24 +1000,29 @@ int ksz8_fdb_dump(struct ksz_device *dev, int port, ...@@ -977,24 +1000,29 @@ int ksz8_fdb_dump(struct ksz_device *dev, int port,
return ret; return ret;
} }
int ksz8_mdb_add(struct ksz_device *dev, int port, static int ksz8_add_sta_mac(struct ksz_device *dev, int port,
const struct switchdev_obj_port_mdb *mdb, struct dsa_db db) const unsigned char *addr, u16 vid)
{ {
struct alu_struct alu; struct alu_struct alu;
int index; int index, ret;
int empty = 0; int empty = 0;
alu.port_forward = 0; alu.port_forward = 0;
for (index = 0; index < dev->info->num_statics; index++) { for (index = 0; index < dev->info->num_statics; index++) {
if (!ksz8_r_sta_mac_table(dev, index, &alu)) { bool valid;
/* Found one already in static MAC table. */
if (!memcmp(alu.mac, mdb->addr, ETH_ALEN) && ret = ksz8_r_sta_mac_table(dev, index, &alu, &valid);
alu.fid == mdb->vid) if (ret)
break; return ret;
/* Remember the first empty entry. */ if (!valid) {
} else if (!empty) { /* Remember the first empty entry. */
empty = index + 1; if (!empty)
empty = index + 1;
continue;
} }
if (!memcmp(alu.mac, addr, ETH_ALEN) && alu.fid == vid)
break;
} }
/* no available entry */ /* no available entry */
...@@ -1005,48 +1033,73 @@ int ksz8_mdb_add(struct ksz_device *dev, int port, ...@@ -1005,48 +1033,73 @@ int ksz8_mdb_add(struct ksz_device *dev, int port,
if (index == dev->info->num_statics) { if (index == dev->info->num_statics) {
index = empty - 1; index = empty - 1;
memset(&alu, 0, sizeof(alu)); memset(&alu, 0, sizeof(alu));
memcpy(alu.mac, mdb->addr, ETH_ALEN); memcpy(alu.mac, addr, ETH_ALEN);
alu.is_static = true; alu.is_static = true;
} }
alu.port_forward |= BIT(port); alu.port_forward |= BIT(port);
if (mdb->vid) { if (vid) {
alu.is_use_fid = true; alu.is_use_fid = true;
/* Need a way to map VID to FID. */ /* Need a way to map VID to FID. */
alu.fid = mdb->vid; alu.fid = vid;
} }
ksz8_w_sta_mac_table(dev, index, &alu);
return 0; return ksz8_w_sta_mac_table(dev, index, &alu);
} }
int ksz8_mdb_del(struct ksz_device *dev, int port, static int ksz8_del_sta_mac(struct ksz_device *dev, int port,
const struct switchdev_obj_port_mdb *mdb, struct dsa_db db) const unsigned char *addr, u16 vid)
{ {
struct alu_struct alu; struct alu_struct alu;
int index; int index, ret;
for (index = 0; index < dev->info->num_statics; index++) { for (index = 0; index < dev->info->num_statics; index++) {
if (!ksz8_r_sta_mac_table(dev, index, &alu)) { bool valid;
/* Found one already in static MAC table. */
if (!memcmp(alu.mac, mdb->addr, ETH_ALEN) && ret = ksz8_r_sta_mac_table(dev, index, &alu, &valid);
alu.fid == mdb->vid) if (ret)
break; return ret;
} if (!valid)
continue;
if (!memcmp(alu.mac, addr, ETH_ALEN) && alu.fid == vid)
break;
} }
/* no available entry */ /* no available entry */
if (index == dev->info->num_statics) if (index == dev->info->num_statics)
goto exit; return 0;
/* clear port */ /* clear port */
alu.port_forward &= ~BIT(port); alu.port_forward &= ~BIT(port);
if (!alu.port_forward) if (!alu.port_forward)
alu.is_static = false; alu.is_static = false;
ksz8_w_sta_mac_table(dev, index, &alu);
exit: return ksz8_w_sta_mac_table(dev, index, &alu);
return 0; }
int ksz8_mdb_add(struct ksz_device *dev, int port,
const struct switchdev_obj_port_mdb *mdb, struct dsa_db db)
{
return ksz8_add_sta_mac(dev, port, mdb->addr, mdb->vid);
}
int ksz8_mdb_del(struct ksz_device *dev, int port,
const struct switchdev_obj_port_mdb *mdb, struct dsa_db db)
{
return ksz8_del_sta_mac(dev, port, mdb->addr, mdb->vid);
}
int ksz8_fdb_add(struct ksz_device *dev, int port, const unsigned char *addr,
u16 vid, struct dsa_db db)
{
return ksz8_add_sta_mac(dev, port, addr, vid);
}
int ksz8_fdb_del(struct ksz_device *dev, int port, const unsigned char *addr,
u16 vid, struct dsa_db db)
{
return ksz8_del_sta_mac(dev, port, addr, vid);
} }
int ksz8_port_vlan_filtering(struct ksz_device *dev, int port, bool flag, int ksz8_port_vlan_filtering(struct ksz_device *dev, int port, bool flag,
...@@ -1346,9 +1399,7 @@ int ksz8_enable_stp_addr(struct ksz_device *dev) ...@@ -1346,9 +1399,7 @@ int ksz8_enable_stp_addr(struct ksz_device *dev)
alu.is_override = true; alu.is_override = true;
alu.port_forward = dev->info->cpu_ports; alu.port_forward = dev->info->cpu_ports;
ksz8_w_sta_mac_table(dev, 0, &alu); return ksz8_w_sta_mac_table(dev, 0, &alu);
return 0;
} }
int ksz8_setup(struct dsa_switch *ds) int ksz8_setup(struct dsa_switch *ds)
......
...@@ -200,6 +200,8 @@ static const struct ksz_dev_ops ksz8_dev_ops = { ...@@ -200,6 +200,8 @@ static const struct ksz_dev_ops ksz8_dev_ops = {
.freeze_mib = ksz8_freeze_mib, .freeze_mib = ksz8_freeze_mib,
.port_init_cnt = ksz8_port_init_cnt, .port_init_cnt = ksz8_port_init_cnt,
.fdb_dump = ksz8_fdb_dump, .fdb_dump = ksz8_fdb_dump,
.fdb_add = ksz8_fdb_add,
.fdb_del = ksz8_fdb_del,
.mdb_add = ksz8_mdb_add, .mdb_add = ksz8_mdb_add,
.mdb_del = ksz8_mdb_del, .mdb_del = ksz8_mdb_del,
.vlan_filtering = ksz8_port_vlan_filtering, .vlan_filtering = ksz8_port_vlan_filtering,
......
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