diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c index f8bc3d4a39ff8066a1cbba35a537799b4b3a58b8..7075e5ab78f3d1fae99b055f7a6f5f67e1439353 100644 --- a/drivers/net/ethernet/marvell/mvpp2.c +++ b/drivers/net/ethernet/marvell/mvpp2.c @@ -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)); + + 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--) { @@ -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 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 */ -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 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; }