Merge branch 'net-mvpp2-Remove-unnecessary-dynamic-allocs'

Maxime Chevallier says:

====================
net: mvpp2: Remove unnecessary dynamic allocs

Some utility functions in mvpp2 make use of dynamic alloc to exchange temporary
objects representing Parser Entries (which are generic filtering entries in the
PPv2 controller).

These objects are small (44 bytes each), we can use the stack to exchange them.

Some previous discussion on this topic showed that the mvpp2_prs_hw_read, which
initializes a struct mvpp2_prs_entry based on one of its fields, can easily lead
to erroneous code if we don't zero-out the struct beforehand :

https://lkml.org/lkml/2018/3/21/739

To fix this, I propose to rename mvpp2_prs_hw_read into mvpp2_prs_init_from_hw,
make it zero-out the struct and take the index as a parameter. That's what's
done in the first patch of the series.

The second patch is the V3 of
("net: mvpp2: Don't use dynamic allocs for local variables"), making use of
mvpp2_prs_init_from_hw and taking previous comments into account.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2018-03-27 10:47:23 -04:00
commit 776d7c5f69
1 changed files with 137 additions and 183 deletions

View File

@ -1582,14 +1582,18 @@ static int mvpp2_prs_hw_write(struct mvpp2 *priv, struct mvpp2_prs_entry *pe)
return 0;
}
/* Read tcam entry from hw */
static int mvpp2_prs_hw_read(struct mvpp2 *priv, struct mvpp2_prs_entry *pe)
/* Initialize tcam entry from hw */
static int mvpp2_prs_init_from_hw(struct mvpp2 *priv,
struct mvpp2_prs_entry *pe, int tid)
{
int i;
if (pe->index > MVPP2_PRS_TCAM_SRAM_SIZE - 1)
return -EINVAL;
memset(pe, 0, sizeof(*pe));
pe->index = tid;
/* Write tcam index - indirect access */
mvpp2_write(priv, MVPP2_PRS_TCAM_IDX_REG, pe->index);
@ -1913,16 +1917,11 @@ static void mvpp2_prs_sram_offset_set(struct mvpp2_prs_entry *pe,
}
/* Find parser flow entry */
static struct mvpp2_prs_entry *mvpp2_prs_flow_find(struct mvpp2 *priv, int flow)
static int mvpp2_prs_flow_find(struct mvpp2 *priv, int flow)
{
struct mvpp2_prs_entry *pe;
struct mvpp2_prs_entry pe;
int tid;
pe = kzalloc(sizeof(*pe), GFP_KERNEL);
if (!pe)
return NULL;
mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_FLOWS);
/* Go through the all entires with MVPP2_PRS_LU_FLOWS */
for (tid = MVPP2_PRS_TCAM_SRAM_SIZE - 1; tid >= 0; tid--) {
u8 bits;
@ -1931,17 +1930,15 @@ static struct mvpp2_prs_entry *mvpp2_prs_flow_find(struct mvpp2 *priv, int flow)
priv->prs_shadow[tid].lu != MVPP2_PRS_LU_FLOWS)
continue;
pe->index = tid;
mvpp2_prs_hw_read(priv, pe);
bits = mvpp2_prs_sram_ai_get(pe);
mvpp2_prs_init_from_hw(priv, &pe, tid);
bits = mvpp2_prs_sram_ai_get(&pe);
/* Sram store classification lookup ID in AI bits [5:0] */
if ((bits & MVPP2_PRS_FLOW_ID_MASK) == flow)
return pe;
return tid;
}
kfree(pe);
return NULL;
return -ENOENT;
}
/* Return first free tcam index, seeking from start to end */
@ -1971,8 +1968,7 @@ static void mvpp2_prs_mac_drop_all_set(struct mvpp2 *priv, int port, bool add)
if (priv->prs_shadow[MVPP2_PE_DROP_ALL].valid) {
/* Entry exist - update port only */
pe.index = MVPP2_PE_DROP_ALL;
mvpp2_prs_hw_read(priv, &pe);
mvpp2_prs_init_from_hw(priv, &pe, MVPP2_PE_DROP_ALL);
} else {
/* Entry doesn't exist - create new */
memset(&pe, 0, sizeof(pe));
@ -2020,8 +2016,7 @@ static void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port,
/* promiscuous mode - Accept unknown unicast or multicast packets */
if (priv->prs_shadow[tid].valid) {
pe.index = tid;
mvpp2_prs_hw_read(priv, &pe);
mvpp2_prs_init_from_hw(priv, &pe, tid);
} else {
memset(&pe, 0, sizeof(pe));
mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
@ -2071,8 +2066,7 @@ static void mvpp2_prs_dsa_tag_set(struct mvpp2 *priv, int port, bool add,
if (priv->prs_shadow[tid].valid) {
/* Entry exist - update port only */
pe.index = tid;
mvpp2_prs_hw_read(priv, &pe);
mvpp2_prs_init_from_hw(priv, &pe, tid);
} else {
/* Entry doesn't exist - create new */
memset(&pe, 0, sizeof(pe));
@ -2140,8 +2134,7 @@ static void mvpp2_prs_dsa_tag_ethertype_set(struct mvpp2 *priv, int port,
if (priv->prs_shadow[tid].valid) {
/* Entry exist - update port only */
pe.index = tid;
mvpp2_prs_hw_read(priv, &pe);
mvpp2_prs_init_from_hw(priv, &pe, tid);
} else {
/* Entry doesn't exist - create new */
memset(&pe, 0, sizeof(pe));
@ -2189,17 +2182,11 @@ static void mvpp2_prs_dsa_tag_ethertype_set(struct mvpp2 *priv, int port,
}
/* Search for existing single/triple vlan entry */
static struct mvpp2_prs_entry *mvpp2_prs_vlan_find(struct mvpp2 *priv,
unsigned short tpid, int ai)
static int mvpp2_prs_vlan_find(struct mvpp2 *priv, unsigned short tpid, int ai)
{
struct mvpp2_prs_entry *pe;
struct mvpp2_prs_entry pe;
int tid;
pe = kzalloc(sizeof(*pe), GFP_KERNEL);
if (!pe)
return NULL;
mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
/* Go through the all entries with MVPP2_PRS_LU_VLAN */
for (tid = MVPP2_PE_FIRST_FREE_TID;
tid <= MVPP2_PE_LAST_FREE_TID; tid++) {
@ -2210,19 +2197,17 @@ static struct mvpp2_prs_entry *mvpp2_prs_vlan_find(struct mvpp2 *priv,
priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
continue;
pe->index = tid;
mvpp2_prs_hw_read(priv, pe);
match = mvpp2_prs_tcam_data_cmp(pe, 0, swab16(tpid));
mvpp2_prs_init_from_hw(priv, &pe, tid);
match = mvpp2_prs_tcam_data_cmp(&pe, 0, swab16(tpid));
if (!match)
continue;
/* Get vlan type */
ri_bits = mvpp2_prs_sram_ri_get(pe);
ri_bits = mvpp2_prs_sram_ri_get(&pe);
ri_bits &= MVPP2_PRS_RI_VLAN_MASK;
/* Get current ai value from tcam */
ai_bits = mvpp2_prs_tcam_ai_get(pe);
ai_bits = mvpp2_prs_tcam_ai_get(&pe);
/* Clear double vlan bit */
ai_bits &= ~MVPP2_PRS_DBL_VLAN_AI_BIT;
@ -2231,34 +2216,31 @@ static struct mvpp2_prs_entry *mvpp2_prs_vlan_find(struct mvpp2 *priv,
if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE ||
ri_bits == MVPP2_PRS_RI_VLAN_TRIPLE)
return pe;
return tid;
}
kfree(pe);
return NULL;
return -ENOENT;
}
/* Add/update single/triple vlan entry */
static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
unsigned int port_map)
{
struct mvpp2_prs_entry *pe;
struct mvpp2_prs_entry pe;
int tid_aux, tid;
int ret = 0;
pe = mvpp2_prs_vlan_find(priv, tpid, ai);
memset(&pe, 0, sizeof(pe));
if (!pe) {
tid = mvpp2_prs_vlan_find(priv, tpid, ai);
if (tid < 0) {
/* Create new tcam entry */
tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_LAST_FREE_TID,
MVPP2_PE_FIRST_FREE_TID);
if (tid < 0)
return tid;
pe = kzalloc(sizeof(*pe), GFP_KERNEL);
if (!pe)
return -ENOMEM;
/* Get last double vlan tid */
for (tid_aux = MVPP2_PE_LAST_FREE_TID;
tid_aux >= MVPP2_PE_FIRST_FREE_TID; tid_aux--) {
@ -2268,49 +2250,46 @@ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
continue;
pe->index = tid_aux;
mvpp2_prs_hw_read(priv, pe);
ri_bits = mvpp2_prs_sram_ri_get(pe);
mvpp2_prs_init_from_hw(priv, &pe, tid_aux);
ri_bits = mvpp2_prs_sram_ri_get(&pe);
if ((ri_bits & MVPP2_PRS_RI_VLAN_MASK) ==
MVPP2_PRS_RI_VLAN_DOUBLE)
break;
}
if (tid <= tid_aux) {
ret = -EINVAL;
goto free_pe;
}
if (tid <= tid_aux)
return -EINVAL;
memset(pe, 0, sizeof(*pe));
mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
pe->index = tid;
memset(&pe, 0, sizeof(pe));
pe.index = tid;
mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VLAN);
mvpp2_prs_match_etype(pe, 0, tpid);
mvpp2_prs_match_etype(&pe, 0, tpid);
/* VLAN tag detected, proceed with VID filtering */
mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_VID);
mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VID);
/* Clear all ai bits for next iteration */
mvpp2_prs_sram_ai_update(pe, 0, MVPP2_PRS_SRAM_AI_MASK);
mvpp2_prs_sram_ai_update(&pe, 0, MVPP2_PRS_SRAM_AI_MASK);
if (ai == MVPP2_PRS_SINGLE_VLAN_AI) {
mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_SINGLE,
mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_SINGLE,
MVPP2_PRS_RI_VLAN_MASK);
} else {
ai |= MVPP2_PRS_DBL_VLAN_AI_BIT;
mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_TRIPLE,
mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_TRIPLE,
MVPP2_PRS_RI_VLAN_MASK);
}
mvpp2_prs_tcam_ai_update(pe, ai, MVPP2_PRS_SRAM_AI_MASK);
mvpp2_prs_tcam_ai_update(&pe, ai, MVPP2_PRS_SRAM_AI_MASK);
mvpp2_prs_shadow_set(priv, pe->index, MVPP2_PRS_LU_VLAN);
mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN);
} else {
mvpp2_prs_init_from_hw(priv, &pe, tid);
}
/* Update ports' mask */
mvpp2_prs_tcam_port_map_set(pe, port_map);
mvpp2_prs_tcam_port_map_set(&pe, port_map);
mvpp2_prs_hw_write(priv, pe);
free_pe:
kfree(pe);
mvpp2_prs_hw_write(priv, &pe);
return ret;
}
@ -2329,18 +2308,12 @@ static int mvpp2_prs_double_vlan_ai_free_get(struct mvpp2 *priv)
}
/* Search for existing double vlan entry */
static struct mvpp2_prs_entry *mvpp2_prs_double_vlan_find(struct mvpp2 *priv,
unsigned short tpid1,
unsigned short tpid2)
static int mvpp2_prs_double_vlan_find(struct mvpp2 *priv, unsigned short tpid1,
unsigned short tpid2)
{
struct mvpp2_prs_entry *pe;
struct mvpp2_prs_entry pe;
int tid;
pe = kzalloc(sizeof(*pe), GFP_KERNEL);
if (!pe)
return NULL;
mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
/* Go through the all entries with MVPP2_PRS_LU_VLAN */
for (tid = MVPP2_PE_FIRST_FREE_TID;
tid <= MVPP2_PE_LAST_FREE_TID; tid++) {
@ -2351,22 +2324,20 @@ static struct mvpp2_prs_entry *mvpp2_prs_double_vlan_find(struct mvpp2 *priv,
priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
continue;
pe->index = tid;
mvpp2_prs_hw_read(priv, pe);
mvpp2_prs_init_from_hw(priv, &pe, tid);
match = mvpp2_prs_tcam_data_cmp(pe, 0, swab16(tpid1))
&& mvpp2_prs_tcam_data_cmp(pe, 4, swab16(tpid2));
match = mvpp2_prs_tcam_data_cmp(&pe, 0, swab16(tpid1)) &&
mvpp2_prs_tcam_data_cmp(&pe, 4, swab16(tpid2));
if (!match)
continue;
ri_mask = mvpp2_prs_sram_ri_get(pe) & MVPP2_PRS_RI_VLAN_MASK;
ri_mask = mvpp2_prs_sram_ri_get(&pe) & MVPP2_PRS_RI_VLAN_MASK;
if (ri_mask == MVPP2_PRS_RI_VLAN_DOUBLE)
return pe;
return tid;
}
kfree(pe);
return NULL;
return -ENOENT;
}
/* Add or update double vlan entry */
@ -2374,28 +2345,24 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
unsigned short tpid2,
unsigned int port_map)
{
struct mvpp2_prs_entry *pe;
int tid_aux, tid, ai, ret = 0;
struct mvpp2_prs_entry pe;
pe = mvpp2_prs_double_vlan_find(priv, tpid1, tpid2);
memset(&pe, 0, sizeof(pe));
if (!pe) {
tid = mvpp2_prs_double_vlan_find(priv, tpid1, tpid2);
if (tid < 0) {
/* Create new tcam entry */
tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
MVPP2_PE_LAST_FREE_TID);
if (tid < 0)
return tid;
pe = kzalloc(sizeof(*pe), GFP_KERNEL);
if (!pe)
return -ENOMEM;
/* Set ai value for new double vlan entry */
ai = mvpp2_prs_double_vlan_ai_free_get(priv);
if (ai < 0) {
ret = ai;
goto free_pe;
}
if (ai < 0)
return ai;
/* Get first single/triple vlan tid */
for (tid_aux = MVPP2_PE_FIRST_FREE_TID;
@ -2406,46 +2373,44 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
continue;
pe->index = tid_aux;
mvpp2_prs_hw_read(priv, pe);
ri_bits = mvpp2_prs_sram_ri_get(pe);
mvpp2_prs_init_from_hw(priv, &pe, tid_aux);
ri_bits = mvpp2_prs_sram_ri_get(&pe);
ri_bits &= MVPP2_PRS_RI_VLAN_MASK;
if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE ||
ri_bits == MVPP2_PRS_RI_VLAN_TRIPLE)
break;
}
if (tid >= tid_aux) {
ret = -ERANGE;
goto free_pe;
}
if (tid >= tid_aux)
return -ERANGE;
memset(pe, 0, sizeof(*pe));
mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
pe->index = tid;
memset(&pe, 0, sizeof(pe));
mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VLAN);
pe.index = tid;
priv->prs_double_vlans[ai] = true;
mvpp2_prs_match_etype(pe, 0, tpid1);
mvpp2_prs_match_etype(pe, 4, tpid2);
mvpp2_prs_match_etype(&pe, 0, tpid1);
mvpp2_prs_match_etype(&pe, 4, tpid2);
mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_VLAN);
mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VLAN);
/* Shift 4 bytes - skip outer vlan tag */
mvpp2_prs_sram_shift_set(pe, MVPP2_VLAN_TAG_LEN,
mvpp2_prs_sram_shift_set(&pe, MVPP2_VLAN_TAG_LEN,
MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_DOUBLE,
mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_DOUBLE,
MVPP2_PRS_RI_VLAN_MASK);
mvpp2_prs_sram_ai_update(pe, ai | MVPP2_PRS_DBL_VLAN_AI_BIT,
mvpp2_prs_sram_ai_update(&pe, ai | MVPP2_PRS_DBL_VLAN_AI_BIT,
MVPP2_PRS_SRAM_AI_MASK);
mvpp2_prs_shadow_set(priv, pe->index, MVPP2_PRS_LU_VLAN);
mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN);
} else {
mvpp2_prs_init_from_hw(priv, &pe, tid);
}
/* Update ports' mask */
mvpp2_prs_tcam_port_map_set(pe, port_map);
mvpp2_prs_hw_write(priv, pe);
free_pe:
kfree(pe);
mvpp2_prs_tcam_port_map_set(&pe, port_map);
mvpp2_prs_hw_write(priv, &pe);
return ret;
}
@ -3513,9 +3478,8 @@ static int mvpp2_prs_vid_range_find(struct mvpp2 *priv, int pmap, u16 vid,
priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VID)
continue;
pe.index = tid;
mvpp2_prs_init_from_hw(priv, &pe, tid);
mvpp2_prs_hw_read(priv, &pe);
mvpp2_prs_tcam_data_byte_get(&pe, 2, &byte[0], &enable[0]);
mvpp2_prs_tcam_data_byte_get(&pe, 3, &byte[1], &enable[1]);
@ -3528,7 +3492,7 @@ static int mvpp2_prs_vid_range_find(struct mvpp2 *priv, int pmap, u16 vid,
return tid;
}
return 0;
return -ENOENT;
}
/* Write parser entry for VID filtering */
@ -3541,6 +3505,8 @@ static int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
struct mvpp2_prs_entry pe;
int tid;
memset(&pe, 0, sizeof(pe));
/* Scan TCAM and see if entry with this <vid,port> already exist */
tid = mvpp2_prs_vid_range_find(priv, (1 << port->id), vid, mask);
@ -3551,8 +3517,7 @@ static int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
shift = MVPP2_VLAN_TAG_LEN;
/* No such entry */
if (!tid) {
memset(&pe, 0, sizeof(pe));
if (tid < 0) {
/* Go through all entries from first to last in vlan range */
tid = mvpp2_prs_tcam_first_free(priv, vid_start,
@ -3569,7 +3534,7 @@ static int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
/* Mask all ports */
mvpp2_prs_tcam_port_map_set(&pe, 0);
} else {
mvpp2_prs_hw_read(priv, &pe);
mvpp2_prs_init_from_hw(priv, &pe, tid);
}
/* Enable the current port */
@ -3604,7 +3569,7 @@ static void mvpp2_prs_vid_entry_remove(struct mvpp2_port *port, u16 vid)
tid = mvpp2_prs_vid_range_find(priv, (1 << port->id), vid, 0xfff);
/* No such entry */
if (tid)
if (tid < 0)
return;
mvpp2_prs_hw_inv(priv, tid);
@ -3771,18 +3736,13 @@ static bool mvpp2_prs_mac_range_equals(struct mvpp2_prs_entry *pe,
}
/* Find tcam entry with matched pair <MAC DA, port> */
static struct mvpp2_prs_entry *
static int
mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
unsigned char *mask, int udf_type)
{
struct mvpp2_prs_entry *pe;
struct mvpp2_prs_entry pe;
int tid;
pe = kzalloc(sizeof(*pe), GFP_ATOMIC);
if (!pe)
return NULL;
mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC);
/* Go through the all entires with MVPP2_PRS_LU_MAC */
for (tid = MVPP2_PE_MAC_RANGE_START;
tid <= MVPP2_PE_MAC_RANGE_END; tid++) {
@ -3793,17 +3753,15 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
(priv->prs_shadow[tid].udf != udf_type))
continue;
pe->index = tid;
mvpp2_prs_hw_read(priv, pe);
entry_pmap = mvpp2_prs_tcam_port_map_get(pe);
mvpp2_prs_init_from_hw(priv, &pe, tid);
entry_pmap = mvpp2_prs_tcam_port_map_get(&pe);
if (mvpp2_prs_mac_range_equals(pe, da, mask) &&
if (mvpp2_prs_mac_range_equals(&pe, da, mask) &&
entry_pmap == pmap)
return pe;
return tid;
}
kfree(pe);
return NULL;
return -ENOENT;
}
/* Update parser's mac da entry */
@ -3813,15 +3771,17 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da,
unsigned char mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
struct mvpp2 *priv = port->priv;
unsigned int pmap, len, ri;
struct mvpp2_prs_entry *pe;
struct mvpp2_prs_entry pe;
int tid;
memset(&pe, 0, sizeof(pe));
/* Scan TCAM and see if entry with this <MAC DA, port> already exist */
pe = mvpp2_prs_mac_da_range_find(priv, BIT(port->id), da, mask,
MVPP2_PRS_UDF_MAC_DEF);
tid = mvpp2_prs_mac_da_range_find(priv, BIT(port->id), da, mask,
MVPP2_PRS_UDF_MAC_DEF);
/* No such entry */
if (!pe) {
if (tid < 0) {
if (!add)
return 0;
@ -3833,39 +3793,37 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da,
if (tid < 0)
return tid;
pe = kzalloc(sizeof(*pe), GFP_ATOMIC);
if (!pe)
return -ENOMEM;
mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC);
pe->index = tid;
pe.index = tid;
/* Mask all ports */
mvpp2_prs_tcam_port_map_set(pe, 0);
mvpp2_prs_tcam_port_map_set(&pe, 0);
} else {
mvpp2_prs_init_from_hw(priv, &pe, tid);
}
mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
/* Update port mask */
mvpp2_prs_tcam_port_set(pe, port->id, add);
mvpp2_prs_tcam_port_set(&pe, port->id, add);
/* Invalidate the entry if no ports are left enabled */
pmap = mvpp2_prs_tcam_port_map_get(pe);
pmap = mvpp2_prs_tcam_port_map_get(&pe);
if (pmap == 0) {
if (add) {
kfree(pe);
if (add)
return -EINVAL;
}
mvpp2_prs_hw_inv(priv, pe->index);
priv->prs_shadow[pe->index].valid = false;
kfree(pe);
mvpp2_prs_hw_inv(priv, pe.index);
priv->prs_shadow[pe.index].valid = false;
return 0;
}
/* Continue - set next lookup */
mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_DSA);
mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_DSA);
/* Set match on DA */
len = ETH_ALEN;
while (len--)
mvpp2_prs_tcam_data_byte_set(pe, len, da[len], 0xff);
mvpp2_prs_tcam_data_byte_set(&pe, len, da[len], 0xff);
/* Set result info bits */
if (is_broadcast_ether_addr(da)) {
@ -3879,21 +3837,19 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da,
ri |= MVPP2_PRS_RI_MAC_ME_MASK;
}
mvpp2_prs_sram_ri_update(pe, ri, MVPP2_PRS_RI_L2_CAST_MASK |
mvpp2_prs_sram_ri_update(&pe, ri, MVPP2_PRS_RI_L2_CAST_MASK |
MVPP2_PRS_RI_MAC_ME_MASK);
mvpp2_prs_shadow_ri_set(priv, pe->index, ri, MVPP2_PRS_RI_L2_CAST_MASK |
mvpp2_prs_shadow_ri_set(priv, pe.index, ri, MVPP2_PRS_RI_L2_CAST_MASK |
MVPP2_PRS_RI_MAC_ME_MASK);
/* Shift to ethertype */
mvpp2_prs_sram_shift_set(pe, 2 * ETH_ALEN,
mvpp2_prs_sram_shift_set(&pe, 2 * ETH_ALEN,
MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
/* Update shadow table and hw entry */
priv->prs_shadow[pe->index].udf = MVPP2_PRS_UDF_MAC_DEF;
mvpp2_prs_shadow_set(priv, pe->index, MVPP2_PRS_LU_MAC);
mvpp2_prs_hw_write(priv, pe);
kfree(pe);
priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_MAC_DEF;
mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC);
mvpp2_prs_hw_write(priv, &pe);
return 0;
}
@ -3935,8 +3891,7 @@ static void mvpp2_prs_mac_del_all(struct mvpp2_port *port)
(priv->prs_shadow[tid].udf != MVPP2_PRS_UDF_MAC_DEF))
continue;
pe.index = tid;
mvpp2_prs_hw_read(priv, &pe);
mvpp2_prs_init_from_hw(priv, &pe, tid);
pmap = mvpp2_prs_tcam_port_map_get(&pe);
@ -4014,13 +3969,15 @@ static int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type)
/* Set prs flow for the port */
static int mvpp2_prs_def_flow(struct mvpp2_port *port)
{
struct mvpp2_prs_entry *pe;
struct mvpp2_prs_entry pe;
int tid;
pe = mvpp2_prs_flow_find(port->priv, port->id);
memset(&pe, 0, sizeof(pe));
tid = mvpp2_prs_flow_find(port->priv, port->id);
/* Such entry not exist */
if (!pe) {
if (tid < 0) {
/* Go through the all entires from last to first */
tid = mvpp2_prs_tcam_first_free(port->priv,
MVPP2_PE_LAST_FREE_TID,
@ -4028,24 +3985,21 @@ static int mvpp2_prs_def_flow(struct mvpp2_port *port)
if (tid < 0)
return tid;
pe = kzalloc(sizeof(*pe), GFP_KERNEL);
if (!pe)
return -ENOMEM;
mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_FLOWS);
pe->index = tid;
pe.index = tid;
/* Set flow ID*/
mvpp2_prs_sram_ai_update(pe, port->id, MVPP2_PRS_FLOW_ID_MASK);
mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_LU_DONE_BIT, 1);
mvpp2_prs_sram_ai_update(&pe, port->id, MVPP2_PRS_FLOW_ID_MASK);
mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_DONE_BIT, 1);
/* Update shadow table */
mvpp2_prs_shadow_set(port->priv, pe->index, MVPP2_PRS_LU_FLOWS);
mvpp2_prs_shadow_set(port->priv, pe.index, MVPP2_PRS_LU_FLOWS);
} else {
mvpp2_prs_init_from_hw(port->priv, &pe, tid);
}
mvpp2_prs_tcam_port_map_set(pe, (1 << port->id));
mvpp2_prs_hw_write(port->priv, pe);
kfree(pe);
mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
mvpp2_prs_tcam_port_map_set(&pe, (1 << port->id));
mvpp2_prs_hw_write(port->priv, &pe);
return 0;
}