|
@@ -1917,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;
|
|
@@ -1935,16 +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;
|
|
|
|
|
|
- mvpp2_prs_init_from_hw(priv, pe, tid);
|
|
|
- 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 */
|
|
@@ -2188,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++) {
|
|
@@ -2209,17 +2197,17 @@ static struct mvpp2_prs_entry *mvpp2_prs_vlan_find(struct mvpp2 *priv,
|
|
|
priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
|
|
|
continue;
|
|
|
|
|
|
- mvpp2_prs_init_from_hw(priv, pe, tid);
|
|
|
- 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;
|
|
|
|
|
@@ -2228,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));
|
|
|
+
|
|
|
+ tid = mvpp2_prs_vlan_find(priv, tpid, ai);
|
|
|
|
|
|
- if (!pe) {
|
|
|
+ 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--) {
|
|
@@ -2265,48 +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;
|
|
|
|
|
|
- mvpp2_prs_init_from_hw(priv, pe, tid_aux);
|
|
|
- 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;
|
|
|
}
|
|
@@ -2325,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++) {
|
|
@@ -2347,21 +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;
|
|
|
|
|
|
- mvpp2_prs_init_from_hw(priv, pe, tid);
|
|
|
+ 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 */
|
|
@@ -2369,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));
|
|
|
+
|
|
|
+ tid = mvpp2_prs_double_vlan_find(priv, tpid1, tpid2);
|
|
|
|
|
|
- if (!pe) {
|
|
|
+ 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;
|
|
@@ -2401,45 +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;
|
|
|
|
|
|
- mvpp2_prs_init_from_hw(priv, pe, tid_aux);
|
|
|
- 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;
|
|
|
}
|
|
|
|
|
@@ -3508,6 +3479,7 @@ static int mvpp2_prs_vid_range_find(struct mvpp2 *priv, int pmap, u16 vid,
|
|
|
continue;
|
|
|
|
|
|
mvpp2_prs_init_from_hw(priv, &pe, tid);
|
|
|
+
|
|
|
mvpp2_prs_tcam_data_byte_get(&pe, 2, &byte[0], &enable[0]);
|
|
|
mvpp2_prs_tcam_data_byte_get(&pe, 3, &byte[1], &enable[1]);
|
|
|
|
|
@@ -3520,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 */
|
|
@@ -3533,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);
|
|
|
|
|
@@ -3543,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,
|
|
@@ -3596,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);
|
|
@@ -3763,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++) {
|
|
@@ -3785,16 +3753,15 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
|
|
|
(priv->prs_shadow[tid].udf != udf_type))
|
|
|
continue;
|
|
|
|
|
|
- mvpp2_prs_init_from_hw(priv, pe, tid);
|
|
|
- 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 */
|
|
@@ -3804,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;
|
|
|
|
|
@@ -3824,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)) {
|
|
@@ -3870,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;
|
|
|
}
|
|
@@ -4004,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,
|
|
@@ -4018,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;
|
|
|
}
|