net: ethernet: ti: ale: switch to use tables for vlan entry description
The ALE VLAN entries are too much differ between different TI CPSW ALE versions. So, handling them using flags, defines and get/set functions became over-complicated. This patch introduces tables to describe the ALE VLAN entries fields, which are different between TI CPSW ALE versions, and new get/set access functions. It also allows to detect incorrect access to not available ALL entry fields. Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
23015ff1a0
commit
aa61296c30
@ -50,6 +50,18 @@
|
||||
/* ALE_AGING_TIMER */
|
||||
#define ALE_AGING_TIMER_MASK GENMASK(23, 0)
|
||||
|
||||
/**
|
||||
* struct ale_entry_fld - The ALE tbl entry field description
|
||||
* @start_bit: field start bit
|
||||
* @num_bits: field bit length
|
||||
* @flags: field flags
|
||||
*/
|
||||
struct ale_entry_fld {
|
||||
u8 start_bit;
|
||||
u8 num_bits;
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
enum {
|
||||
CPSW_ALE_F_STATUS_REG = BIT(0), /* Status register present */
|
||||
CPSW_ALE_F_HW_AUTOAGING = BIT(1), /* HW auto aging */
|
||||
@ -64,6 +76,7 @@ enum {
|
||||
* @tbl_entries: number of ALE entries
|
||||
* @major_ver_mask: mask of ALE Major Version Value in ALE_IDVER reg.
|
||||
* @nu_switch_ale: NU Switch ALE
|
||||
* @vlan_entry_tbl: ALE vlan entry fields description tbl
|
||||
*/
|
||||
struct cpsw_ale_dev_id {
|
||||
const char *dev_id;
|
||||
@ -71,6 +84,7 @@ struct cpsw_ale_dev_id {
|
||||
u32 tbl_entries;
|
||||
u32 major_ver_mask;
|
||||
bool nu_switch_ale;
|
||||
const struct ale_entry_fld *vlan_entry_tbl;
|
||||
};
|
||||
|
||||
#define ALE_TABLE_WRITE BIT(31)
|
||||
@ -132,6 +146,51 @@ static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value, \
|
||||
cpsw_ale_set_field(ale_entry, start, bits, value); \
|
||||
}
|
||||
|
||||
enum {
|
||||
ALE_ENT_VID_MEMBER_LIST = 0,
|
||||
ALE_ENT_VID_UNREG_MCAST_MSK,
|
||||
ALE_ENT_VID_REG_MCAST_MSK,
|
||||
ALE_ENT_VID_FORCE_UNTAGGED_MSK,
|
||||
ALE_ENT_VID_UNREG_MCAST_IDX,
|
||||
ALE_ENT_VID_REG_MCAST_IDX,
|
||||
ALE_ENT_VID_LAST,
|
||||
};
|
||||
|
||||
#define ALE_FLD_ALLOWED BIT(0)
|
||||
#define ALE_FLD_SIZE_PORT_MASK_BITS BIT(1)
|
||||
#define ALE_FLD_SIZE_PORT_NUM_BITS BIT(2)
|
||||
|
||||
#define ALE_ENTRY_FLD(id, start, bits) \
|
||||
[id] = { \
|
||||
.start_bit = start, \
|
||||
.num_bits = bits, \
|
||||
.flags = ALE_FLD_ALLOWED, \
|
||||
}
|
||||
|
||||
#define ALE_ENTRY_FLD_DYN_MSK_SIZE(id, start) \
|
||||
[id] = { \
|
||||
.start_bit = start, \
|
||||
.num_bits = 0, \
|
||||
.flags = ALE_FLD_ALLOWED | \
|
||||
ALE_FLD_SIZE_PORT_MASK_BITS, \
|
||||
}
|
||||
|
||||
/* dm814x, am3/am4/am5, k2hk */
|
||||
static const struct ale_entry_fld vlan_entry_cpsw[ALE_ENT_VID_LAST] = {
|
||||
ALE_ENTRY_FLD(ALE_ENT_VID_MEMBER_LIST, 0, 3),
|
||||
ALE_ENTRY_FLD(ALE_ENT_VID_UNREG_MCAST_MSK, 8, 3),
|
||||
ALE_ENTRY_FLD(ALE_ENT_VID_REG_MCAST_MSK, 16, 3),
|
||||
ALE_ENTRY_FLD(ALE_ENT_VID_FORCE_UNTAGGED_MSK, 24, 3),
|
||||
};
|
||||
|
||||
/* k2e/k2l, k3 am65/j721e cpsw2g */
|
||||
static const struct ale_entry_fld vlan_entry_nu[ALE_ENT_VID_LAST] = {
|
||||
ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_MEMBER_LIST, 0),
|
||||
ALE_ENTRY_FLD(ALE_ENT_VID_UNREG_MCAST_IDX, 20, 3),
|
||||
ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_FORCE_UNTAGGED_MSK, 24),
|
||||
ALE_ENTRY_FLD(ALE_ENT_VID_REG_MCAST_IDX, 44, 3),
|
||||
};
|
||||
|
||||
DEFINE_ALE_FIELD(entry_type, 60, 2)
|
||||
DEFINE_ALE_FIELD(vlan_id, 48, 12)
|
||||
DEFINE_ALE_FIELD(mcast_state, 62, 2)
|
||||
@ -141,17 +200,76 @@ DEFINE_ALE_FIELD(ucast_type, 62, 2)
|
||||
DEFINE_ALE_FIELD1(port_num, 66)
|
||||
DEFINE_ALE_FIELD(blocked, 65, 1)
|
||||
DEFINE_ALE_FIELD(secure, 64, 1)
|
||||
DEFINE_ALE_FIELD1(vlan_untag_force, 24)
|
||||
DEFINE_ALE_FIELD1(vlan_reg_mcast, 16)
|
||||
DEFINE_ALE_FIELD1(vlan_unreg_mcast, 8)
|
||||
DEFINE_ALE_FIELD1(vlan_member_list, 0)
|
||||
DEFINE_ALE_FIELD(mcast, 40, 1)
|
||||
/* ALE NetCP nu switch specific */
|
||||
DEFINE_ALE_FIELD(vlan_unreg_mcast_idx, 20, 3)
|
||||
DEFINE_ALE_FIELD(vlan_reg_mcast_idx, 44, 3)
|
||||
|
||||
#define NU_VLAN_UNREG_MCAST_IDX 1
|
||||
|
||||
static int cpsw_ale_entry_get_fld(struct cpsw_ale *ale,
|
||||
u32 *ale_entry,
|
||||
const struct ale_entry_fld *entry_tbl,
|
||||
int fld_id)
|
||||
{
|
||||
const struct ale_entry_fld *entry_fld;
|
||||
u32 bits;
|
||||
|
||||
if (!ale || !ale_entry)
|
||||
return -EINVAL;
|
||||
|
||||
entry_fld = &entry_tbl[fld_id];
|
||||
if (!(entry_fld->flags & ALE_FLD_ALLOWED)) {
|
||||
dev_err(ale->params.dev, "get: wrong ale fld id %d\n", fld_id);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
bits = entry_fld->num_bits;
|
||||
if (entry_fld->flags & ALE_FLD_SIZE_PORT_MASK_BITS)
|
||||
bits = ale->port_mask_bits;
|
||||
|
||||
return cpsw_ale_get_field(ale_entry, entry_fld->start_bit, bits);
|
||||
}
|
||||
|
||||
static void cpsw_ale_entry_set_fld(struct cpsw_ale *ale,
|
||||
u32 *ale_entry,
|
||||
const struct ale_entry_fld *entry_tbl,
|
||||
int fld_id,
|
||||
u32 value)
|
||||
{
|
||||
const struct ale_entry_fld *entry_fld;
|
||||
u32 bits;
|
||||
|
||||
if (!ale || !ale_entry)
|
||||
return;
|
||||
|
||||
entry_fld = &entry_tbl[fld_id];
|
||||
if (!(entry_fld->flags & ALE_FLD_ALLOWED)) {
|
||||
dev_err(ale->params.dev, "set: wrong ale fld id %d\n", fld_id);
|
||||
return;
|
||||
}
|
||||
|
||||
bits = entry_fld->num_bits;
|
||||
if (entry_fld->flags & ALE_FLD_SIZE_PORT_MASK_BITS)
|
||||
bits = ale->port_mask_bits;
|
||||
|
||||
cpsw_ale_set_field(ale_entry, entry_fld->start_bit, bits, value);
|
||||
}
|
||||
|
||||
static int cpsw_ale_vlan_get_fld(struct cpsw_ale *ale,
|
||||
u32 *ale_entry,
|
||||
int fld_id)
|
||||
{
|
||||
return cpsw_ale_entry_get_fld(ale, ale_entry,
|
||||
ale->vlan_entry_tbl, fld_id);
|
||||
}
|
||||
|
||||
static void cpsw_ale_vlan_set_fld(struct cpsw_ale *ale,
|
||||
u32 *ale_entry,
|
||||
int fld_id,
|
||||
u32 value)
|
||||
{
|
||||
cpsw_ale_entry_set_fld(ale, ale_entry,
|
||||
ale->vlan_entry_tbl, fld_id, value);
|
||||
}
|
||||
|
||||
/* The MAC address field in the ALE entry cannot be macroized as above */
|
||||
static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr)
|
||||
{
|
||||
@ -446,19 +564,22 @@ static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry,
|
||||
int idx;
|
||||
|
||||
/* Set VLAN registered multicast flood mask */
|
||||
idx = cpsw_ale_get_vlan_reg_mcast_idx(ale_entry);
|
||||
idx = cpsw_ale_vlan_get_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_REG_MCAST_IDX);
|
||||
writel(reg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
|
||||
|
||||
/* Set VLAN unregistered multicast flood mask */
|
||||
idx = cpsw_ale_get_vlan_unreg_mcast_idx(ale_entry);
|
||||
idx = cpsw_ale_vlan_get_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_UNREG_MCAST_IDX);
|
||||
writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
|
||||
}
|
||||
|
||||
static void cpsw_ale_set_vlan_untag(struct cpsw_ale *ale, u32 *ale_entry,
|
||||
u16 vid, int untag_mask)
|
||||
{
|
||||
cpsw_ale_set_vlan_untag_force(ale_entry,
|
||||
untag_mask, ale->vlan_field_bits);
|
||||
cpsw_ale_vlan_set_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_FORCE_UNTAGGED_MSK,
|
||||
untag_mask);
|
||||
if (untag_mask & ALE_PORT_HOST)
|
||||
bitmap_set(ale->p0_untag_vid_mask, vid, 1);
|
||||
else
|
||||
@ -480,17 +601,19 @@ int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port_mask, int untag,
|
||||
cpsw_ale_set_vlan_untag(ale, ale_entry, vid, untag);
|
||||
|
||||
if (!ale->params.nu_switch_ale) {
|
||||
cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast,
|
||||
ale->vlan_field_bits);
|
||||
cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast,
|
||||
ale->vlan_field_bits);
|
||||
cpsw_ale_vlan_set_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_REG_MCAST_MSK, reg_mcast);
|
||||
cpsw_ale_vlan_set_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_UNREG_MCAST_MSK, unreg_mcast);
|
||||
} else {
|
||||
cpsw_ale_set_vlan_unreg_mcast_idx(ale_entry,
|
||||
NU_VLAN_UNREG_MCAST_IDX);
|
||||
cpsw_ale_vlan_set_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_UNREG_MCAST_IDX,
|
||||
NU_VLAN_UNREG_MCAST_IDX);
|
||||
cpsw_ale_set_vlan_mcast(ale, ale_entry, reg_mcast, unreg_mcast);
|
||||
}
|
||||
cpsw_ale_set_vlan_member_list(ale_entry, port_mask,
|
||||
ale->vlan_field_bits);
|
||||
|
||||
cpsw_ale_vlan_set_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_MEMBER_LIST, port_mask);
|
||||
|
||||
if (idx < 0)
|
||||
idx = cpsw_ale_match_free(ale);
|
||||
@ -509,20 +632,20 @@ static void cpsw_ale_del_vlan_modify(struct cpsw_ale *ale, u32 *ale_entry,
|
||||
int reg_mcast, unreg_mcast;
|
||||
int members, untag;
|
||||
|
||||
members = cpsw_ale_get_vlan_member_list(ale_entry,
|
||||
ale->vlan_field_bits);
|
||||
members = cpsw_ale_vlan_get_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_MEMBER_LIST);
|
||||
members &= ~port_mask;
|
||||
if (!members) {
|
||||
cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
|
||||
return;
|
||||
}
|
||||
|
||||
untag = cpsw_ale_get_vlan_untag_force(ale_entry,
|
||||
ale->vlan_field_bits);
|
||||
reg_mcast = cpsw_ale_get_vlan_reg_mcast(ale_entry,
|
||||
ale->vlan_field_bits);
|
||||
unreg_mcast = cpsw_ale_get_vlan_unreg_mcast(ale_entry,
|
||||
ale->vlan_field_bits);
|
||||
untag = cpsw_ale_vlan_get_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_FORCE_UNTAGGED_MSK);
|
||||
reg_mcast = cpsw_ale_vlan_get_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_REG_MCAST_MSK);
|
||||
unreg_mcast = cpsw_ale_vlan_get_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_UNREG_MCAST_MSK);
|
||||
untag &= members;
|
||||
reg_mcast &= members;
|
||||
unreg_mcast &= members;
|
||||
@ -530,16 +653,16 @@ static void cpsw_ale_del_vlan_modify(struct cpsw_ale *ale, u32 *ale_entry,
|
||||
cpsw_ale_set_vlan_untag(ale, ale_entry, vid, untag);
|
||||
|
||||
if (!ale->params.nu_switch_ale) {
|
||||
cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast,
|
||||
ale->vlan_field_bits);
|
||||
cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast,
|
||||
ale->vlan_field_bits);
|
||||
cpsw_ale_vlan_set_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_REG_MCAST_MSK, reg_mcast);
|
||||
cpsw_ale_vlan_set_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_UNREG_MCAST_MSK, unreg_mcast);
|
||||
} else {
|
||||
cpsw_ale_set_vlan_mcast(ale, ale_entry, reg_mcast,
|
||||
unreg_mcast);
|
||||
}
|
||||
cpsw_ale_set_vlan_member_list(ale_entry, members,
|
||||
ale->vlan_field_bits);
|
||||
cpsw_ale_vlan_set_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_MEMBER_LIST, members);
|
||||
}
|
||||
|
||||
int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
|
||||
@ -577,15 +700,15 @@ int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask,
|
||||
if (idx >= 0)
|
||||
cpsw_ale_read(ale, idx, ale_entry);
|
||||
|
||||
vlan_members = cpsw_ale_get_vlan_member_list(ale_entry,
|
||||
ale->vlan_field_bits);
|
||||
reg_mcast_members = cpsw_ale_get_vlan_reg_mcast(ale_entry,
|
||||
ale->vlan_field_bits);
|
||||
vlan_members = cpsw_ale_vlan_get_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_MEMBER_LIST);
|
||||
reg_mcast_members = cpsw_ale_vlan_get_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_REG_MCAST_MSK);
|
||||
unreg_mcast_members =
|
||||
cpsw_ale_get_vlan_unreg_mcast(ale_entry,
|
||||
ale->vlan_field_bits);
|
||||
untag_members = cpsw_ale_get_vlan_untag_force(ale_entry,
|
||||
ale->vlan_field_bits);
|
||||
cpsw_ale_vlan_get_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_UNREG_MCAST_MSK);
|
||||
untag_members = cpsw_ale_vlan_get_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_FORCE_UNTAGGED_MSK);
|
||||
|
||||
vlan_members |= port_mask;
|
||||
untag_members = (untag_members & ~port_mask) | untag_mask;
|
||||
@ -618,14 +741,15 @@ void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,
|
||||
continue;
|
||||
|
||||
unreg_members =
|
||||
cpsw_ale_get_vlan_unreg_mcast(ale_entry,
|
||||
ale->vlan_field_bits);
|
||||
cpsw_ale_vlan_get_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_UNREG_MCAST_MSK);
|
||||
if (add)
|
||||
unreg_members |= unreg_mcast_mask;
|
||||
else
|
||||
unreg_members &= ~unreg_mcast_mask;
|
||||
cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_members,
|
||||
ale->vlan_field_bits);
|
||||
cpsw_ale_vlan_set_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_UNREG_MCAST_MSK,
|
||||
unreg_members);
|
||||
cpsw_ale_write(ale, idx, ale_entry);
|
||||
}
|
||||
}
|
||||
@ -635,15 +759,15 @@ static void cpsw_ale_vlan_set_unreg_mcast(struct cpsw_ale *ale, u32 *ale_entry,
|
||||
{
|
||||
int unreg_mcast;
|
||||
|
||||
unreg_mcast =
|
||||
cpsw_ale_get_vlan_unreg_mcast(ale_entry,
|
||||
ale->vlan_field_bits);
|
||||
unreg_mcast = cpsw_ale_vlan_get_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_UNREG_MCAST_MSK);
|
||||
if (allmulti)
|
||||
unreg_mcast |= ALE_PORT_HOST;
|
||||
else
|
||||
unreg_mcast &= ~ALE_PORT_HOST;
|
||||
cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast,
|
||||
ale->vlan_field_bits);
|
||||
|
||||
cpsw_ale_vlan_set_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_UNREG_MCAST_MSK, unreg_mcast);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -653,7 +777,8 @@ cpsw_ale_vlan_set_unreg_mcast_idx(struct cpsw_ale *ale, u32 *ale_entry,
|
||||
int unreg_mcast;
|
||||
int idx;
|
||||
|
||||
idx = cpsw_ale_get_vlan_unreg_mcast_idx(ale_entry);
|
||||
idx = cpsw_ale_vlan_get_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_UNREG_MCAST_IDX);
|
||||
|
||||
unreg_mcast = readl(ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
|
||||
|
||||
@ -677,9 +802,9 @@ void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti, int port)
|
||||
type = cpsw_ale_get_entry_type(ale_entry);
|
||||
if (type != ALE_TYPE_VLAN)
|
||||
continue;
|
||||
vlan_members =
|
||||
cpsw_ale_get_vlan_member_list(ale_entry,
|
||||
ale->vlan_field_bits);
|
||||
|
||||
vlan_members = cpsw_ale_vlan_get_fld(ale, ale_entry,
|
||||
ALE_ENT_VID_MEMBER_LIST);
|
||||
|
||||
if (port != -1 && !(vlan_members & BIT(port)))
|
||||
continue;
|
||||
@ -1056,18 +1181,21 @@ static const struct cpsw_ale_dev_id cpsw_ale_id_match[] = {
|
||||
.dev_id = "cpsw",
|
||||
.tbl_entries = 1024,
|
||||
.major_ver_mask = 0xff,
|
||||
.vlan_entry_tbl = vlan_entry_cpsw,
|
||||
},
|
||||
{
|
||||
/* 66ak2h_xgbe */
|
||||
.dev_id = "66ak2h-xgbe",
|
||||
.tbl_entries = 2048,
|
||||
.major_ver_mask = 0xff,
|
||||
.vlan_entry_tbl = vlan_entry_cpsw,
|
||||
},
|
||||
{
|
||||
.dev_id = "66ak2el",
|
||||
.features = CPSW_ALE_F_STATUS_REG,
|
||||
.major_ver_mask = 0x7,
|
||||
.nu_switch_ale = true,
|
||||
.vlan_entry_tbl = vlan_entry_nu,
|
||||
},
|
||||
{
|
||||
.dev_id = "66ak2g",
|
||||
@ -1075,6 +1203,7 @@ static const struct cpsw_ale_dev_id cpsw_ale_id_match[] = {
|
||||
.tbl_entries = 64,
|
||||
.major_ver_mask = 0x7,
|
||||
.nu_switch_ale = true,
|
||||
.vlan_entry_tbl = vlan_entry_nu,
|
||||
},
|
||||
{
|
||||
.dev_id = "am65x-cpsw2g",
|
||||
@ -1082,6 +1211,7 @@ static const struct cpsw_ale_dev_id cpsw_ale_id_match[] = {
|
||||
.tbl_entries = 64,
|
||||
.major_ver_mask = 0x7,
|
||||
.nu_switch_ale = true,
|
||||
.vlan_entry_tbl = vlan_entry_nu,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
@ -1129,6 +1259,7 @@ struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params)
|
||||
ale->params = *params;
|
||||
ale->ageout = ale->params.ale_ageout * HZ;
|
||||
ale->features = ale_dev_id->features;
|
||||
ale->vlan_entry_tbl = ale_dev_id->vlan_entry_tbl;
|
||||
|
||||
rev = readl_relaxed(ale->params.ale_regs + ALE_IDVER);
|
||||
ale->version =
|
||||
|
@ -28,6 +28,8 @@ struct cpsw_ale_params {
|
||||
unsigned long bus_freq;
|
||||
};
|
||||
|
||||
struct ale_entry_fld;
|
||||
|
||||
struct cpsw_ale {
|
||||
struct cpsw_ale_params params;
|
||||
struct timer_list timer;
|
||||
@ -39,6 +41,7 @@ struct cpsw_ale {
|
||||
u32 port_num_bits;
|
||||
u32 vlan_field_bits;
|
||||
unsigned long *p0_untag_vid_mask;
|
||||
const struct ale_entry_fld *vlan_entry_tbl;
|
||||
};
|
||||
|
||||
enum cpsw_ale_control {
|
||||
|
Loading…
Reference in New Issue
Block a user