Merge pull request #360 from BU-Automation/topic/js/ksz9477-broadcast-rate-limit

Topic/js/ksz9477 broadcast rate limit
This commit is contained in:
Oleg KARFICH
2025-12-05 12:55:48 +01:00
committed by GitHub Enterprise
9 changed files with 348 additions and 117 deletions
+1
View File
@@ -10,6 +10,7 @@ ksz_switch-objs += ksz_ptp.o
endif
ksz_switch-objs += ksz8_ethtool.o
ksz_switch-objs += ksz9477_ethtool.o
ksz_switch-objs += ksz_devlink.o
obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477_I2C) += ksz9477_i2c.o
obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ_SPI) += ksz_spi.o
+66 -86
View File
@@ -2,64 +2,17 @@
#include "ksz8_ethtool.h"
#include "ksz8.h"
enum {
KSZ8_REGDUMP_ID_GLOBAL = 0x1100,
KSZ8_REGDUMP_ID_PORT = 0x1200,
KSZ8_REGDUMP_ID_STAT_MAC_TBL = 0x2000,
KSZ8_REGDUMP_ID_FDB = 0x2100,
};
struct ksz_regdump_hdr {
u32 module_id;
u32 len;
};
struct ksz_regdump_record {
struct ksz_regdump_hdr hdr;
u32 start_off;
u32 end_off;
};
// creates a regdump record entry
// note we use u32 to transport register values, despite their size in
// the device
#define KSZ_REGDUMP_ENTRY(id, start, end) { \
.hdr.module_id = (id), \
.hdr.len = (((end) - (start)) * sizeof(u32)) * 2 \
+ sizeof(struct ksz_regdump_hdr), \
.start_off = (start), \
.end_off = (end), \
}
#define SIZE_IS_MULTIPLE_OF(T, T2) (sizeof(T) == (DIV_ROUND_UP(sizeof(T), sizeof(T2))* sizeof(T2)))
// sizeof(ksz8_dyn_mac_entry) == 12
struct ksz8_dyn_mac_entry {
/*entry 1*/
u32 : 24;
u8 timestamp;
/* entry 2 & 3 */
u8 fid;
u8 src_port;
u8 mac[ETH_ALEN];
};
#define KSZ8_REGDUMP_MAC_ENTRY(id, entry_size, max_entries) { \
.hdr.module_id = (id), \
.hdr.len = 2 * sizeof(u32) + (entry_size) * (max_entries) \
+ sizeof(struct ksz_regdump_hdr), \
.start_off = 0, \
.end_off = 0, \
}
#include "ksz_ethtool.h"
static const struct ksz_regdump_record ksz8_regdump_records[] = {
KSZ_REGDUMP_ENTRY(KSZ8_REGDUMP_ID_GLOBAL, 0x00, 0x10),
KSZ_REGDUMP_ENTRY(KSZ8_REGDUMP_ID_PORT, 0x10, 0x20),
KSZ_REGDUMP_ENTRY(KSZ8_REGDUMP_ID_PORT + 1, 0x20, 0x30),
KSZ_REGDUMP_ENTRY(KSZ8_REGDUMP_ID_PORT + 2, 0x30, 0x40),
KSZ8_REGDUMP_MAC_ENTRY(KSZ8_REGDUMP_ID_STAT_MAC_TBL, sizeof(struct alu_struct), 8),
KSZ8_REGDUMP_MAC_ENTRY(KSZ8_REGDUMP_ID_FDB, sizeof(struct ksz8_dyn_mac_entry), 1024),
KSZ_REGDUMP_ENTRY(KSZ_REGDUMP_ID_GLOBAL, 0x00, 0x10),
KSZ_REGDUMP_ENTRY(KSZ_REGDUMP_ID_PORT, 0x10, 0x20),
KSZ_REGDUMP_ENTRY(KSZ_REGDUMP_ID_PORT + 1, 0x20, 0x30),
KSZ_REGDUMP_ENTRY(KSZ_REGDUMP_ID_PORT + 2, 0x30, 0x40),
KSZ8_REGDUMP_MAC_ENTRY(KSZ_REGDUMP_ID_STAT_MAC_TBL,
sizeof(struct alu_struct), 8),
KSZ8_REGDUMP_MAC_ENTRY(KSZ_REGDUMP_ID_FDB,
sizeof(struct ksz8_dyn_mac_entry), 1024),
};
int ksz8_get_regs_len(struct ksz_device *dev, int port)
@@ -72,20 +25,22 @@ int ksz8_get_regs_len(struct ksz_device *dev, int port)
return length;
}
static void ksz8_get_regs_dump_static_mac_table(struct ksz_device *dev, u32 *reg, u32 *pos)
static void ksz8_get_regs_dump_static_mac_table(struct ksz_device *dev,
u32 *reg, u32 *pos)
{
BUILD_BUG_ON(!SIZE_IS_MULTIPLE_OF(struct alu_struct, u32));
int index, ret;
u32 cnt = *pos;
reg[cnt++] = KSZ8_REGDUMP_ID_STAT_MAC_TBL;
struct ksz_regdump_hdr *hdr = (struct ksz_regdump_hdr *)&reg[cnt];
const u32 pos_length = cnt++;
reg[pos_length] = sizeof(struct ksz_regdump_hdr);
hdr->module_id = KSZ_REGDUMP_ID_STAT_MAC_TBL;
hdr->len = sizeof(struct ksz_regdump_hdr);
cnt += 2;
for (index = 0; index < dev->info->num_statics; index++) {
bool valid;
struct alu_struct* alu = (struct alu_struct*)&reg[cnt];
struct alu_struct *alu = (struct alu_struct *)&reg[cnt];
ret = ksz8_r_sta_mac_table(dev, index, alu, &valid);
if (ret)
@@ -94,7 +49,7 @@ static void ksz8_get_regs_dump_static_mac_table(struct ksz_device *dev, u32 *reg
if (!valid)
continue;
reg[pos_length] += sizeof(struct alu_struct);
hdr->len += sizeof(struct alu_struct);
cnt += sizeof(struct alu_struct) / sizeof(u32);
}
*pos = cnt;
@@ -107,55 +62,80 @@ static void ksz8_get_regs_dump_fdb(struct ksz_device *dev, u32 *reg, u32 *pos)
u16 entries = 0;
u32 cnt = *pos;
reg[cnt++] = KSZ8_REGDUMP_ID_FDB;
struct ksz_regdump_hdr *hdr = (struct ksz_regdump_hdr *)&reg[cnt];
const u32 pos_length = cnt++;
reg[pos_length] = sizeof(struct ksz_regdump_hdr);
hdr->module_id = KSZ_REGDUMP_ID_FDB;
hdr->len = sizeof(struct ksz_regdump_hdr);
cnt += 2;
do {
struct ksz8_dyn_mac_entry *entry = (struct ksz8_dyn_mac_entry*) &reg[cnt];
int ret = ksz8_r_dyn_mac_table(dev, i, entry->mac, &entry->fid, &entry->src_port,
&entry->timestamp, &entries);
struct ksz8_dyn_mac_entry *entry =
(struct ksz8_dyn_mac_entry *)&reg[cnt];
int ret = ksz8_r_dyn_mac_table(dev, i, entry->mac, &entry->fid,
&entry->src_port,
&entry->timestamp, &entries);
if (!ret) {
reg[pos_length] += sizeof(struct ksz8_dyn_mac_entry);
cnt += DIV_ROUND_UP(sizeof(struct ksz8_dyn_mac_entry), sizeof(u32));
hdr->len += sizeof(struct ksz8_dyn_mac_entry);
cnt += DIV_ROUND_UP(sizeof(struct ksz8_dyn_mac_entry),
sizeof(u32));
}
i++;
} while (i < entries);
*pos = cnt;
}
void ksz8_get_regs(struct ksz_device *dev, int port,
struct ethtool_regs *regs, void *p)
static void ksz_dump_regmap_range(struct ksz_device *dev, u32 *regs, u32 *pos,
u32 start, u32 end)
{
int i, j;
int i, length = *pos;
const struct regmap_range *yes_ranges = dev->info->rd_table->yes_ranges;
for (i = 0; i < dev->info->rd_table->n_yes_ranges; i++) {
const struct regmap_range range = yes_ranges[i];
u32 reg;
if (range.range_max < start || range.range_min >= end)
continue;
for (reg = range.range_min; reg <= range.range_max; reg++) {
u8 val;
ksz_read8(dev, reg, &val);
regs[length++] = reg;
regs[length++] = val;
}
}
*pos = length;
}
void ksz8_get_regs(struct ksz_device *dev, int port, struct ethtool_regs *regs,
void *p)
{
int i;
u32 pos = 0;
u32 *reg = p;
for (i = 0; i < ARRAY_SIZE(ksz8_regdump_records); i++) {
struct ksz_regdump_record rec = ksz8_regdump_records[i];
struct ksz_regdump_hdr *hdr =
(struct ksz_regdump_hdr *)&reg[pos];
if (rec.hdr.module_id == KSZ8_REGDUMP_ID_STAT_MAC_TBL) {
if (rec.hdr.module_id == KSZ_REGDUMP_ID_STAT_MAC_TBL) {
ksz8_get_regs_dump_static_mac_table(dev, reg, &pos);
continue;
}
if (rec.hdr.module_id == KSZ8_REGDUMP_ID_FDB) {
if (rec.hdr.module_id == KSZ_REGDUMP_ID_FDB) {
ksz8_get_regs_dump_fdb(dev, reg, &pos);
continue;
}
reg[pos++] = rec.hdr.module_id;
reg[pos++] = rec.hdr.len;
for (j = rec.start_off;
j < rec.end_off; j++) {
u8 val;
reg[pos++] = j;
ksz_read8(dev, j, &val);
reg[pos++] = val;
}
pos += 2;
hdr->module_id = rec.hdr.module_id;
hdr->len = pos;
ksz_dump_regmap_range(dev, reg, &pos, rec.start_off,
rec.end_off);
hdr->len = (pos - hdr->len + 2) * sizeof(u32);
}
}
+2
View File
@@ -4,8 +4,10 @@
#define __KSZ8XXX_ETHTOOL_H
#include <linux/types.h>
#include "ksz_ethtool.h"
#include "ksz_common.h"
int ksz8_get_regs_len(struct ksz_device *dev, int port);
void ksz8_get_regs(struct ksz_device *dev, int port,
struct ethtool_regs *regs, void *p);
@@ -0,0 +1,86 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "ksz9477_ethtool.h"
#include "ksz_ethtool.h"
static const struct ksz_regdump_record ksz8_regdump_records[] = {
KSZ_REGDUMP_ENTRY(KSZ_REGDUMP_ID_GLOBAL, 0x00, 0x700),
KSZ_REGDUMP_ENTRY(KSZ_REGDUMP_ID_PORT + 0, 0x1000, 0x1fff),
KSZ_REGDUMP_ENTRY(KSZ_REGDUMP_ID_PORT + 1, 0x2000, 0x2fff),
KSZ_REGDUMP_ENTRY(KSZ_REGDUMP_ID_PORT + 2, 0x3000, 0x3fff),
KSZ_REGDUMP_ENTRY(KSZ_REGDUMP_ID_PORT + 3, 0x4000, 0x4fff),
KSZ_REGDUMP_ENTRY(KSZ_REGDUMP_ID_PORT + 4, 0x5000, 0x5fff),
KSZ_REGDUMP_ENTRY(KSZ_REGDUMP_ID_PORT + 5, 0x6000, 0x6fff),
KSZ_REGDUMP_ENTRY(KSZ_REGDUMP_ID_PORT + 6, 0x7000, 0x7fff),
};
int ksz9477_get_regs_len(struct ksz_device *dev, int port)
{
int i, length = 0;
const struct regmap_range *yes_ranges = dev->info->rd_table->yes_ranges;
for (i = 0; i < dev->info->rd_table->n_yes_ranges; i++) {
const struct regmap_range range = yes_ranges[i];
length += (range.range_max - range.range_min + 1) *
sizeof(u32) * 2;
}
// ports + global + stat + fdb
length += (7 + 1 + 1 + 1) * sizeof(struct ksz_regdump_hdr);
return length;
}
static void ksz_dump_regmap_range(struct ksz_device *dev, u32 *regs, u32 *pos,
u32 start, u32 end)
{
int i, length = *pos;
const struct regmap_range *yes_ranges = dev->info->rd_table->yes_ranges;
for (i = 0; i < dev->info->rd_table->n_yes_ranges; i++) {
const struct regmap_range range = yes_ranges[i];
u32 reg;
if (range.range_max < start || range.range_min >= end)
continue;
for (reg = range.range_min; reg <= range.range_max; reg++) {
u8 val;
ksz_read8(dev, reg, &val);
regs[length++] = reg;
regs[length++] = val;
}
}
*pos = length;
}
void ksz9477_get_regs(struct ksz_device *dev, int port,
struct ethtool_regs *regs, void *p)
{
int i;
u32 pos = 0;
u32 *reg = p;
for (i = 0; i < ARRAY_SIZE(ksz8_regdump_records); i++) {
struct ksz_regdump_record rec = ksz8_regdump_records[i];
struct ksz_regdump_hdr *hdr =
(struct ksz_regdump_hdr *)&reg[pos];
hdr->module_id = rec.hdr.module_id;
pos += 2;
if (rec.hdr.module_id == KSZ_REGDUMP_ID_STAT_MAC_TBL) {
continue;
}
if (rec.hdr.module_id == KSZ_REGDUMP_ID_FDB) {
continue;
}
hdr->len = pos;
ksz_dump_regmap_range(dev, reg, &pos, rec.start_off,
rec.end_off);
hdr->len = (pos - hdr->len + 2) * sizeof(u32);
}
}
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef __KSZ9477_ETHTOOL_H
#define __KSZ9477_ETHTOOL_H
#include <linux/types.h>
#include "ksz_ethtool.h"
#include "ksz_common.h"
int ksz9477_get_regs_len(struct ksz_device *dev, int port);
void ksz9477_get_regs(struct ksz_device *dev, int port,
struct ethtool_regs *regs, void *p);
#endif
+17 -9
View File
@@ -33,6 +33,7 @@
#include "lan937x.h"
#include "ksz_devlink.h"
#include "ksz8_ethtool.h"
#include "ksz9477_ethtool.h"
#define MIB_COUNTER_NUM 0x20
@@ -218,9 +219,9 @@ static const struct ksz_dev_ops ksz8_dev_ops = {
.change_mtu = ksz8_change_mtu,
.devlink_param_setup = ksz8_setup_devlink_params,
.devlink_param_teardown = ksz8_teardown_devlink_params,
.devlink_param_get = ksz8_devlink_param_get,
.devlink_param_set = ksz8_devlink_param_set,
.devlink_info_get= ksz8_devlink_info_get,
.devlink_param_get = ksz_devlink_param_get,
.devlink_param_set = ksz_devlink_param_set,
.devlink_info_get= ksz_devlink_info_get,
.get_regs = ksz8_get_regs,
.get_regs_len = ksz8_get_regs_len,
};
@@ -262,9 +263,16 @@ static const struct ksz_dev_ops ksz9477_dev_ops = {
.config_cpu_port = ksz9477_config_cpu_port,
.tc_cbs_set_cinc = ksz9477_tc_cbs_set_cinc,
.enable_stp_addr = ksz9477_enable_stp_addr,
.devlink_info_get = ksz_devlink_info_get,
.devlink_param_get = ksz_devlink_param_get,
.devlink_param_set = ksz_devlink_param_set,
.devlink_param_setup = ksz9477_setup_devlink_params,
.devlink_param_teardown = ksz9477_teardown_devlink_params,
.reset = ksz9477_reset_switch,
.init = ksz9477_switch_init,
.exit = ksz9477_switch_exit,
.get_regs = ksz9477_get_regs,
.get_regs_len = ksz9477_get_regs_len,
};
static const struct ksz_dev_ops lan937x_dev_ops = {
@@ -3442,7 +3450,7 @@ static int ksz_devlink_param_setup(struct dsa_switch *ds)
return 0;
}
static int ksz_devlink_info_get(struct dsa_switch *ds, struct devlink_info_req *req, struct netlink_ext_ack *extack) {
static int ksz_get_devlink_info(struct dsa_switch *ds, struct devlink_info_req *req, struct netlink_ext_ack *extack) {
struct ksz_device* dev = ds->priv;
@@ -3452,7 +3460,7 @@ static int ksz_devlink_info_get(struct dsa_switch *ds, struct devlink_info_req *
return -EOPNOTSUPP;
}
static int ksz_devlink_param_get(struct dsa_switch *ds, u32 id,
static int ksz_get_devlink_param(struct dsa_switch *ds, u32 id,
struct devlink_param_gset_ctx *ctx)
{
struct ksz_device *dev = ds->priv;
@@ -3463,7 +3471,7 @@ static int ksz_devlink_param_get(struct dsa_switch *ds, u32 id,
return -EOPNOTSUPP;
}
static int ksz_devlink_param_set(struct dsa_switch *ds, u32 id,
static int ksz_set_devlink_param(struct dsa_switch *ds, u32 id,
struct devlink_param_gset_ctx *ctx)
{
struct ksz_device *dev = ds->priv;
@@ -3538,9 +3546,9 @@ static const struct dsa_switch_ops ksz_switch_ops = {
.port_setup_tc = ksz_setup_tc,
.get_mac_eee = ksz_get_mac_eee,
.set_mac_eee = ksz_set_mac_eee,
.devlink_param_get = ksz_devlink_param_get,
.devlink_param_set = ksz_devlink_param_set,
.devlink_info_get = ksz_devlink_info_get,
.devlink_param_get = ksz_get_devlink_param,
.devlink_param_set = ksz_set_devlink_param,
.devlink_info_get = ksz_get_devlink_info,
.get_regs = ksz_get_regs,
.get_regs_len = ksz_get_regs_len,
};
+96 -19
View File
@@ -7,13 +7,20 @@
#include <net/devlink.h>
#include <net/dsa.h>
#include "ksz8795_reg.h"
#include "ksz_common.h"
#define KSZ8_P_BCAST_STORM_CTRL 0
#define KSZ8_PORT_BROADCAST_STORM BIT(7)
#define KSZ9_P_BCAST_STORM_CTRL 0x400
#define KSZ9_PORT_BROADCAST_STORM BIT(1)
static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
bool set)
{
regmap_update_bits(ksz_regmap_8(dev), PORT_CTRL_ADDR(port, offset),
regmap_update_bits(ksz_regmap_8(dev), dev->dev_ops->get_port_addr(port, offset),
bits, set ? bits : 0);
}
@@ -23,9 +30,11 @@ enum ksz_devlink_param_id {
KSZ_DEVLINK_PARAM_ID_MCAST_STORM_RATE_DISABLE,
KSZ_DEVLINK_PARAM_ID_PORT_BASE,
KSZ_DEVLINK_PARAM_ID_PORT_MAX = KSZ_DEVLINK_PARAM_ID_PORT_BASE + 3,
KSZ9_DEVLINK_PARAM_ID_PORT_BASE,
KSZ9_DEVLINK_PARAM_ID_PORT_MAX = KSZ9_DEVLINK_PARAM_ID_PORT_BASE + 8,
};
static const struct devlink_param ksz_devlink_params[] = {
static const struct devlink_param ksz8_devlink_params[] = {
DSA_DEVLINK_PARAM_DRIVER(KSZ_DEVLINK_PARAM_ID_BROADCAST_STORM_RATE,
"bcast storm rate", DEVLINK_PARAM_TYPE_U16,
BIT(DEVLINK_PARAM_CMODE_RUNTIME)),
@@ -48,19 +57,73 @@ static const struct devlink_param ksz_devlink_params[] = {
};
static const struct devlink_param ksz9_devlink_params[] = {
DSA_DEVLINK_PARAM_DRIVER(KSZ_DEVLINK_PARAM_ID_BROADCAST_STORM_RATE,
"bcast storm rate", DEVLINK_PARAM_TYPE_U16,
BIT(DEVLINK_PARAM_CMODE_RUNTIME)),
DSA_DEVLINK_PARAM_DRIVER(KSZ_DEVLINK_PARAM_ID_MCAST_STORM_RATE_DISABLE,
"mcast storm rate disable",
DEVLINK_PARAM_TYPE_BOOL,
BIT(DEVLINK_PARAM_CMODE_RUNTIME)),
DSA_DEVLINK_PARAM_DRIVER(KSZ9_DEVLINK_PARAM_ID_PORT_BASE,
"bcast storm protection enable port 0",
DEVLINK_PARAM_TYPE_BOOL,
BIT(DEVLINK_PARAM_CMODE_RUNTIME)),
DSA_DEVLINK_PARAM_DRIVER(KSZ9_DEVLINK_PARAM_ID_PORT_BASE + 1,
"bcast storm protection enable port 1",
DEVLINK_PARAM_TYPE_BOOL,
BIT(DEVLINK_PARAM_CMODE_RUNTIME)),
DSA_DEVLINK_PARAM_DRIVER(KSZ9_DEVLINK_PARAM_ID_PORT_BASE + 2,
"bcast storm protection enable port 2",
DEVLINK_PARAM_TYPE_BOOL,
BIT(DEVLINK_PARAM_CMODE_RUNTIME)),
DSA_DEVLINK_PARAM_DRIVER(KSZ9_DEVLINK_PARAM_ID_PORT_BASE + 3,
"bcast storm protection enable port 3",
DEVLINK_PARAM_TYPE_BOOL,
BIT(DEVLINK_PARAM_CMODE_RUNTIME)),
DSA_DEVLINK_PARAM_DRIVER(KSZ9_DEVLINK_PARAM_ID_PORT_BASE + 4,
"bcast storm protection enable port 4",
DEVLINK_PARAM_TYPE_BOOL,
BIT(DEVLINK_PARAM_CMODE_RUNTIME)),
DSA_DEVLINK_PARAM_DRIVER(KSZ9_DEVLINK_PARAM_ID_PORT_BASE + 5,
"bcast storm protection enable port 5",
DEVLINK_PARAM_TYPE_BOOL,
BIT(DEVLINK_PARAM_CMODE_RUNTIME)),
DSA_DEVLINK_PARAM_DRIVER(KSZ9_DEVLINK_PARAM_ID_PORT_BASE + 6,
"bcast storm protection enable port 6",
DEVLINK_PARAM_TYPE_BOOL,
BIT(DEVLINK_PARAM_CMODE_RUNTIME)),
DSA_DEVLINK_PARAM_DRIVER(KSZ9_DEVLINK_PARAM_ID_PORT_BASE + 7,
"bcast storm protection enable port 7",
DEVLINK_PARAM_TYPE_BOOL,
BIT(DEVLINK_PARAM_CMODE_RUNTIME)),
};
int ksz8_setup_devlink_params(struct dsa_switch *ds)
{
return dsa_devlink_params_register(ds, ksz_devlink_params,
ARRAY_SIZE(ksz_devlink_params));
return dsa_devlink_params_register(ds, ksz8_devlink_params,
ARRAY_SIZE(ksz8_devlink_params));
}
void ksz8_teardown_devlink_params(struct dsa_switch *ds)
{
dsa_devlink_params_unregister(ds, ksz_devlink_params,
ARRAY_SIZE(ksz_devlink_params));
dsa_devlink_params_unregister(ds, ksz8_devlink_params,
ARRAY_SIZE(ksz8_devlink_params));
}
int ksz8_devlink_param_get(struct ksz_device *dev, u32 id,
int ksz9477_setup_devlink_params(struct dsa_switch *ds)
{
return dsa_devlink_params_register(ds, ksz9_devlink_params,
ARRAY_SIZE(ksz9_devlink_params));
}
void ksz9477_teardown_devlink_params(struct dsa_switch *ds)
{
dsa_devlink_params_unregister(ds, ksz9_devlink_params,
ARRAY_SIZE(ksz9_devlink_params));
}
int ksz_devlink_param_get(struct ksz_device *dev, u32 id,
struct devlink_param_gset_ctx *ctx)
{
const u16 *regs = dev->info->regs;
@@ -84,9 +147,19 @@ int ksz8_devlink_param_get(struct ksz_device *dev, u32 id,
int port = id - KSZ_DEVLINK_PARAM_ID_PORT_BASE;
u8 val;
ksz_pread8(dev, port, P_BCAST_STORM_CTRL, &val);
ctx->val.vbool = (val & PORT_BROADCAST_STORM) ==
PORT_BROADCAST_STORM;
ksz_pread8(dev, port, KSZ8_P_BCAST_STORM_CTRL, &val);
ctx->val.vbool = (val & KSZ8_PORT_BROADCAST_STORM) ==
KSZ8_PORT_BROADCAST_STORM;
} break;
case KSZ9_DEVLINK_PARAM_ID_PORT_BASE ... KSZ9_DEVLINK_PARAM_ID_PORT_MAX: {
int port = id - KSZ9_DEVLINK_PARAM_ID_PORT_BASE;
u8 val;
ksz_pread8(dev, port, 0x400, &val);
ctx->val.vbool = (val & KSZ9_PORT_BROADCAST_STORM) ==
KSZ9_PORT_BROADCAST_STORM;
} break;
default:
@@ -96,7 +169,7 @@ int ksz8_devlink_param_get(struct ksz_device *dev, u32 id,
return 0;
}
int ksz8_devlink_param_set(struct ksz_device *dev, u32 id,
int ksz_devlink_param_set(struct ksz_device *dev, u32 id,
struct devlink_param_gset_ctx *ctx)
{
const u16 *regs;
@@ -128,8 +201,15 @@ int ksz8_devlink_param_set(struct ksz_device *dev, u32 id,
case KSZ_DEVLINK_PARAM_ID_PORT_BASE ... KSZ_DEVLINK_PARAM_ID_PORT_MAX: {
int port = id - KSZ_DEVLINK_PARAM_ID_PORT_BASE;
ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL,
PORT_BROADCAST_STORM, ctx->val.vbool);
ksz_port_cfg(dev, port, KSZ8_P_BCAST_STORM_CTRL,
KSZ8_PORT_BROADCAST_STORM, ctx->val.vbool);
} break;
case KSZ9_DEVLINK_PARAM_ID_PORT_BASE ... KSZ9_DEVLINK_PARAM_ID_PORT_MAX: {
int port = id - KSZ9_DEVLINK_PARAM_ID_PORT_BASE;
ksz_port_cfg(dev, port, KSZ9_P_BCAST_STORM_CTRL,
KSZ9_PORT_BROADCAST_STORM, ctx->val.vbool);
} break;
default:
@@ -139,12 +219,9 @@ int ksz8_devlink_param_set(struct ksz_device *dev, u32 id,
return 0;
}
int ksz8_devlink_info_get(struct ksz_device *dev, struct devlink_info_req *req,
int ksz_devlink_info_get(struct ksz_device *dev, struct devlink_info_req *req,
struct netlink_ext_ack *extack)
{
return devlink_info_version_fixed_put(
req, DEVLINK_INFO_VERSION_GENERIC_ASIC_ID,
dev->info->dev_name);
req, DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, dev->info->dev_name);
}
+6 -3
View File
@@ -13,12 +13,15 @@
int ksz8_setup_devlink_params(struct dsa_switch *ds);
void ksz8_teardown_devlink_params(struct dsa_switch *ds);
int ksz8_devlink_param_get(struct ksz_device *dev, u32 id,
int ksz9477_setup_devlink_params(struct dsa_switch *ds);
void ksz9477_teardown_devlink_params(struct dsa_switch *ds);
int ksz_devlink_param_get(struct ksz_device *dev, u32 id,
struct devlink_param_gset_ctx *ctx);
int ksz8_devlink_param_set(struct ksz_device *dev, u32 id,
int ksz_devlink_param_set(struct ksz_device *dev, u32 id,
struct devlink_param_gset_ctx *ctx);
int ksz8_devlink_info_get(struct ksz_device *dev, struct devlink_info_req *req,
int ksz_devlink_info_get(struct ksz_device *dev, struct devlink_info_req *req,
struct netlink_ext_ack *extack);
#endif
+60
View File
@@ -0,0 +1,60 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef __KSZ_ETHTOOL_H
#define __KSZ_ETHTOOL_H
#include <linux/types.h>
#include <linux/if_ether.h>
// sizeof(ksz8_dyn_mac_entry) == 12
struct ksz8_dyn_mac_entry {
/*entry 1*/
u32 : 24;
u8 timestamp;
/* entry 2 & 3 */
u8 fid;
u8 src_port;
u8 mac[ETH_ALEN];
};
struct ksz_regdump_hdr {
u32 module_id;
u32 len;
};
struct ksz_regdump_record {
struct ksz_regdump_hdr hdr;
u32 start_off;
u32 end_off;
};
enum {
KSZ_REGDUMP_ID_GLOBAL = 0x1100,
KSZ_REGDUMP_ID_PORT = 0x1200,
KSZ_REGDUMP_ID_STAT_MAC_TBL = 0x2000,
KSZ_REGDUMP_ID_FDB = 0x2100,
};
// creates a regdump record entry
// note we use u32 to transport register values, despite their size in
// the device
#define KSZ_REGDUMP_ENTRY(id, start, end) { \
.hdr.module_id = (id), \
.hdr.len = (((end) - (start)) * sizeof(u32)) * 2 \
+ sizeof(struct ksz_regdump_hdr), \
.start_off = (start), \
.end_off = (end), \
}
#define SIZE_IS_MULTIPLE_OF(T, T2) (sizeof(T) == (DIV_ROUND_UP(sizeof(T), sizeof(T2))* sizeof(T2)))
#define KSZ8_REGDUMP_MAC_ENTRY(id, entry_size, max_entries) { \
.hdr.module_id = (id), \
.hdr.len = 2 * sizeof(u32) + (entry_size) * (max_entries) \
+ sizeof(struct ksz_regdump_hdr), \
.start_off = 0, \
.end_off = 0, \
}
#endif