Commit 776d7c5f authored by David S. Miller's avatar David S. Miller

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