Loading drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +15 −6 Original line number Diff line number Diff line Loading @@ -431,11 +431,16 @@ static int ipa3_attrib_dump(struct ipa_rule_attrib *attrib, uint32_t mask[4]; int i; if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) pr_err("tos_value:%d ", attrib->tos_value); if (attrib->attrib_mask & IPA_FLT_IS_PURE_ACK) pr_err("is_pure_ack "); if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) pr_err("tos_mask:%d ", attrib->tos_mask); if (attrib->attrib_mask & IPA_FLT_TOS) pr_cont("tos:%d ", attrib->u.v4.tos); if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) { pr_cont("tos_value:%d ", attrib->tos_value); pr_cont("tos_mask:%d ", attrib->tos_mask); } if (attrib->attrib_mask & IPA_FLT_PROTOCOL) pr_err("protocol:%d ", attrib->u.v4.protocol); Loading Loading @@ -557,8 +562,12 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib) int i; int j; if (attrib->tos_eq_present) pr_err("tos_value:%d ", attrib->tos_eq); if (attrib->tos_eq_present) { if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) pr_err("pure_ack "); else pr_err("tos:%d ", attrib->tos_eq); } if (attrib->protocol_eq_present) pr_err("protocol:%d ", attrib->protocol_eq); Loading drivers/platform/msm/ipa/ipa_v3/ipa_flt.c +20 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,26 @@ static int ipa3_generate_flt_hw_rule(enum ipa_ip_type ip, memset(&gen_params, 0, sizeof(gen_params)); if (entry->rule.hashable) { if (entry->rule.attrib.attrib_mask & IPA_FLT_IS_PURE_ACK && !entry->rule.eq_attrib_type) { IPAERR_RL("PURE_ACK rule atrb used with hash rule\n"); WARN_ON_RATELIMIT_IPA(1); return -EPERM; } /* * tos_eq_present field has two meanings: * tos equation for IPA ver < 4.5 (as the field name reveals) * pure_ack equation for IPA ver >= 4.5 */ if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5 && entry->rule.eq_attrib_type && entry->rule.eq_attrib.tos_eq_present) { IPAERR_RL("PURE_ACK rule eq used with hash rule\n"); return -EPERM; } } gen_params.ipt = ip; if (entry->rt_tbl) gen_params.rt_tbl_idx = entry->rt_tbl->idx; Loading drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +7 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,13 @@ static int ipa_generate_rt_hw_rule(enum ipa_ip_type ip, memset(&gen_params, 0, sizeof(gen_params)); if (entry->rule.hashable && entry->rule.attrib.attrib_mask & IPA_FLT_IS_PURE_ACK) { IPAERR_RL("PURE_ACK rule atrb used with hash rule\n"); WARN_ON_RATELIMIT_IPA(1); return -EPERM; } gen_params.ipt = ip; gen_params.dst_pipe_idx = ipa3_get_ep_mapping(entry->rule.dst); if (gen_params.dst_pipe_idx == -1) { Loading drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c +274 −67 Original line number Diff line number Diff line Loading @@ -44,7 +44,8 @@ * @flt_generate_eq: Generate flt equation attributes from rule attributes * @rt_parse_hw_rule: Parse rt rule read from H/W * @flt_parse_hw_rule: Parse flt rule read from H/W * @eq_bitfield: Array of the bit fields of the support equations * @eq_bitfield: Array of the bit fields of the support equations. * 0xFF means the equation is not supported */ struct ipahal_fltrt_obj { bool support_hash; Loading Loading @@ -172,6 +173,9 @@ static int ipa_flt_parse_hw_rule_ipav4(u8 *addr, #define IPA_GET_RULE_EQ_BIT_PTRN(__eq) \ (BIT(ipahal_fltrt_objs[ipahal_ctx->hw_type].eq_bitfield[(__eq)])) #define IPA_IS_RULE_EQ_VALID(__eq) \ (ipahal_fltrt_objs[ipahal_ctx->hw_type].eq_bitfield[(__eq)] != 0xFF) /* * ipa_fltrt_rule_generation_err_check() - check basic validity on the rule * attribs before starting building it Loading Loading @@ -489,6 +493,7 @@ static struct ipahal_fltrt_obj ipahal_fltrt_objs[IPA_HW_MAX] = { [IPA_IHL_OFFSET_EQ_16] = 13, [IPA_FL_EQ] = 14, [IPA_IS_FRAG] = 15, [IPA_IS_PURE_ACK] = 0xFF, }, }, Loading Loading @@ -533,6 +538,7 @@ static struct ipahal_fltrt_obj ipahal_fltrt_objs[IPA_HW_MAX] = { [IPA_IHL_OFFSET_EQ_16] = 13, [IPA_FL_EQ] = 14, [IPA_IS_FRAG] = 15, [IPA_IS_PURE_ACK] = 0xFF, }, }, Loading Loading @@ -577,6 +583,7 @@ static struct ipahal_fltrt_obj ipahal_fltrt_objs[IPA_HW_MAX] = { [IPA_IHL_OFFSET_EQ_16] = 13, [IPA_FL_EQ] = 14, [IPA_IS_FRAG] = 15, [IPA_IS_PURE_ACK] = 0xFF, }, }, Loading Loading @@ -605,7 +612,7 @@ static struct ipahal_fltrt_obj ipahal_fltrt_objs[IPA_HW_MAX] = { ipa_rt_parse_hw_rule, ipa_flt_parse_hw_rule_ipav4, { [IPA_TOS_EQ] = 0, [IPA_TOS_EQ] = 0xFF, [IPA_PROTOCOL_EQ] = 1, [IPA_TC_EQ] = 2, [IPA_OFFSET_MEQ128_0] = 3, Loading @@ -621,6 +628,7 @@ static struct ipahal_fltrt_obj ipahal_fltrt_objs[IPA_HW_MAX] = { [IPA_IHL_OFFSET_EQ_16] = 13, [IPA_FL_EQ] = 14, [IPA_IS_FRAG] = 15, [IPA_IS_PURE_ACK] = 0, }, }, }; Loading Loading @@ -696,10 +704,25 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, u8 ihl_ofst_meq32 = 0; u8 ofst_meq128 = 0; int rc = 0; bool tos_done = false; if (attrib->attrib_mask & IPA_FLT_IS_PURE_ACK) { if (!IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK)) { IPAHAL_ERR("is_pure_ack eq not supported\n"); goto err; } *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_PURE_ACK); extra = ipa_write_8(0, extra); } if (attrib->attrib_mask & IPA_FLT_TOS) { if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { if (!IPA_IS_RULE_EQ_VALID(IPA_TOS_EQ)) { IPAHAL_DBG("tos eq not supported\n"); } else { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_TOS_EQ); extra = ipa_write_8(attrib->u.v4.tos, extra); tos_done = true; } } if (attrib->attrib_mask & IPA_FLT_PROTOCOL) { Loading Loading @@ -790,7 +813,7 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, } *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( ipa3_0_ofst_meq32[ofst_meq32]); /* 0 => offset of TOS in v4 header */ /* 0 => Take the first word. offset of TOS in v4 header is 1 */ extra = ipa_write_8(0, extra); rest = ipa_write_32((attrib->tos_mask << 16), rest); rest = ipa_write_32((attrib->tos_value << 16), rest); Loading Loading @@ -841,6 +864,24 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, ofst_meq32++; } if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq32, ofst_meq32)) { IPAHAL_DBG("ran out of meq32 eq\n"); } else { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( ipa3_0_ofst_meq32[ofst_meq32]); /* * 0 => Take the first word. * offset of TOS in v4 header is 1 */ extra = ipa_write_8(0, extra); rest = ipa_write_32(0xFF << 16, rest); rest = ipa_write_32((attrib->u.v4.tos << 16), rest); ofst_meq32++; tos_done = true; } } if (attrib->attrib_mask & IPA_FLT_TYPE) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, ihl_ofst_meq32)) { Loading Loading @@ -933,6 +974,26 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, ihl_ofst_meq32++; } if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, ihl_ofst_meq32)) { IPAHAL_DBG("ran out of ihl_meq32 eq\n"); } else { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( ipa3_0_ihl_ofst_meq32[ihl_ofst_meq32]); /* * 0 => Take the first word. offset of TOS in * v4 header is 1. MSB bit asserted at IHL means * to ignore packet IHL and do offset inside IPA header */ extra = ipa_write_8(0x80, extra); rest = ipa_write_32(0xFF << 16, rest); rest = ipa_write_32((attrib->u.v4.tos << 16), rest); ihl_ofst_meq32++; tos_done = true; } } if (attrib->attrib_mask & IPA_FLT_META_DATA) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_METADATA_COMPARE); rest = ipa_write_32(attrib->meta_data_mask, rest); Loading Loading @@ -1010,6 +1071,11 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, if (attrib->attrib_mask & IPA_FLT_FRAGMENT) *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_FRAG); if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { IPAHAL_ERR("could not find equation for tos\n"); goto err; } goto done; err: Loading @@ -1033,6 +1099,14 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip6(u16 *en_rule, int rc = 0; /* v6 code below assumes no extension headers TODO: fix this */ if (attrib->attrib_mask & IPA_FLT_IS_PURE_ACK) { if (!IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK)) { IPAHAL_ERR("is_pure_ack eq not supported\n"); goto err; } *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_PURE_ACK); extra = ipa_write_8(0, extra); } if (attrib->attrib_mask & IPA_FLT_NEXT_HDR) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_PROTOCOL_EQ); Loading Loading @@ -1597,6 +1671,12 @@ static int ipa_fltrt_calc_extra_wrd_bytes( { int num = 0; /* * tos_eq_present field has two meanings: * tos equation for IPA ver < 4.5 (as the field name reveals) * pure_ack equation for IPA ver >= 4.5 * In both cases it needs one extra word. */ if (attrib->tos_eq_present) num++; if (attrib->protocol_eq_present) Loading Loading @@ -1650,8 +1730,22 @@ static int ipa_fltrt_generate_hw_rule_bdy_from_eq( rest = *buf; } if (attrib->tos_eq_present) /* * tos_eq_present field has two meanings: * tos equation for IPA ver < 4.5 (as the field name reveals) * pure_ack equation for IPA ver >= 4.5 * In both cases it needs one extra word. */ if (attrib->tos_eq_present) { if (IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK)) { extra = ipa_write_8(0, extra); } else if (IPA_IS_RULE_EQ_VALID(IPA_TOS_EQ)) { extra = ipa_write_8(attrib->tos_eq, extra); } else { IPAHAL_ERR("no support for pure_ack and tos eqs\n"); return -EPERM; } } if (attrib->protocol_eq_present) extra = ipa_write_8(attrib->protocol_eq, extra); Loading Loading @@ -1807,12 +1901,32 @@ static int ipa_flt_generate_eq_ip4(enum ipa_ip_type ip, u8 ofst_meq128 = 0; u16 eq_bitmap = 0; u16 *en_rule = &eq_bitmap; bool tos_done = false; if (attrib->attrib_mask & IPA_FLT_IS_PURE_ACK) { if (!IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK)) { IPAHAL_ERR("is_pure_ack eq not supported\n"); return -EPERM; } *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_PURE_ACK); /* * Starting IPA 4.5, where PURE ACK equation supported * and TOS equation support removed, field tos_eq_present * represent pure_ack presence. */ eq_atrb->tos_eq_present = 1; eq_atrb->tos_eq = 0; } if (attrib->attrib_mask & IPA_FLT_TOS) { if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { if (!IPA_IS_RULE_EQ_VALID(IPA_TOS_EQ)) { IPAHAL_DBG("tos eq not supported\n"); } else { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_TOS_EQ); eq_atrb->tos_eq_present = 1; eq_atrb->tos_eq = attrib->u.v4.tos; } } if (attrib->attrib_mask & IPA_FLT_PROTOCOL) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_PROTOCOL_EQ); Loading Loading @@ -1993,6 +2107,26 @@ static int ipa_flt_generate_eq_ip4(enum ipa_ip_type ip, ofst_meq32++; } if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq32, ofst_meq32)) { IPAHAL_DBG("ran out of meq32 eq\n"); } else { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( ipa3_0_ofst_meq32[ofst_meq32]); /* * offset 0 => Take the first word. * offset of TOS in v4 header is 1 */ eq_atrb->offset_meq_32[ofst_meq32].offset = 0; eq_atrb->offset_meq_32[ofst_meq32].mask = 0xFF << 16; eq_atrb->offset_meq_32[ofst_meq32].value = attrib->u.v4.tos << 16; ofst_meq32++; tos_done = true; } } if (attrib->attrib_mask & IPA_FLT_TYPE) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, ihl_ofst_meq32)) { Loading Loading @@ -2039,6 +2173,29 @@ static int ipa_flt_generate_eq_ip4(enum ipa_ip_type ip, ihl_ofst_meq32++; } if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, ihl_ofst_meq32)) { IPAHAL_DBG("ran out of ihl_meq32 eq\n"); } else { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( ipa3_0_ihl_ofst_meq32[ihl_ofst_meq32]); /* * 0 => Take the first word. offset of TOS in * v4 header is 1. MSB bit asserted at IHL means * to ignore packet IHL and do offset inside IPA header */ eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].offset = 0x80; eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].mask = 0xFF << 16; eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].value = attrib->u.v4.tos << 16; ihl_ofst_meq32++; tos_done = true; } } if (attrib->attrib_mask & IPA_FLT_META_DATA) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( IPA_METADATA_COMPARE); Loading Loading @@ -2125,6 +2282,11 @@ static int ipa_flt_generate_eq_ip4(enum ipa_ip_type ip, eq_atrb->ipv4_frag_eq_present = 1; } if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { IPAHAL_ERR("could not find equation for tos\n"); return -EPERM; } eq_atrb->rule_eq_bitmap = *en_rule; eq_atrb->num_offset_meq_32 = ofst_meq32; eq_atrb->num_ihl_offset_range_16 = ihl_ofst_rng16; Loading @@ -2145,6 +2307,21 @@ static int ipa_flt_generate_eq_ip6(enum ipa_ip_type ip, u16 eq_bitmap = 0; u16 *en_rule = &eq_bitmap; if (attrib->attrib_mask & IPA_FLT_IS_PURE_ACK) { if (!IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK)) { IPAHAL_ERR("is_pure_ack eq not supported\n"); return -EPERM; } *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_PURE_ACK); /* * Starting IPA 4.5, where PURE ACK equation supported * and TOS equation support removed, field tos_eq_present * represent pure_ack presenence. */ eq_atrb->tos_eq_present = 1; eq_atrb->tos_eq = 0; } if (attrib->attrib_mask & IPA_FLT_NEXT_HDR) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( IPA_PROTOCOL_EQ); Loading Loading @@ -2658,8 +2835,19 @@ static int ipa_fltrt_parse_hw_rule_eq(u8 *addr, u32 hdr_sz, IPAHAL_DBG_LOW("eq_bitmap=0x%x\n", eq_bitmap); if (eq_bitmap & IPA_GET_RULE_EQ_BIT_PTRN(IPA_TOS_EQ)) if (IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK) && (eq_bitmap & IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_PURE_ACK))) { /* * tos_eq_present field represents pure_ack when pure * ack equation valid (started IPA 4.5). In this case * tos equation should not be supported. */ atrb->tos_eq_present = true; } if (IPA_IS_RULE_EQ_VALID(IPA_TOS_EQ) && (eq_bitmap & IPA_GET_RULE_EQ_BIT_PTRN(IPA_TOS_EQ))) { atrb->tos_eq_present = true; } if (eq_bitmap & IPA_GET_RULE_EQ_BIT_PTRN(IPA_PROTOCOL_EQ)) atrb->protocol_eq_present = true; if (eq_bitmap & IPA_GET_RULE_EQ_BIT_PTRN(IPA_TC_EQ)) Loading Loading @@ -2715,8 +2903,12 @@ static int ipa_fltrt_parse_hw_rule_eq(u8 *addr, u32 hdr_sz, IPAHAL_DBG_LOW("addr=0x%pK extra=0x%pK rest=0x%pK\n", addr, extra, rest); if (atrb->tos_eq_present) if (IPA_IS_RULE_EQ_VALID(IPA_TOS_EQ) && atrb->tos_eq_present) atrb->tos_eq = *extra++; if (IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK) && atrb->tos_eq_present) { atrb->tos_eq = 0; extra++; } if (atrb->protocol_eq_present) atrb->protocol_eq = *extra++; if (atrb->tc_eq_present) Loading Loading @@ -2839,7 +3031,7 @@ static int ipa_rt_parse_hw_rule(u8 *addr, struct ipahal_rt_rule_entry *rule) IPAHAL_DBG_LOW("read hdr 0x%llx\n", rule_hdr->u.word); if (rule_hdr->u.word == 0) { /* table termintator - empty table */ /* table terminator - empty table */ rule->rule_size = 0; return 0; } Loading Loading @@ -2971,6 +3163,8 @@ int ipahal_fltrt_init(enum ipa_hw_type ipa_hw_type) int i; struct ipa_mem_buffer *mem; int rc = -EFAULT; u32 eq_bits; u8 *eq_bitfield; IPAHAL_DBG("Entry - HW_TYPE=%d\n", ipa_hw_type); Loading Loading @@ -3102,6 +3296,20 @@ int ipahal_fltrt_init(enum ipa_hw_type ipa_hw_type) } } eq_bits = 0; eq_bitfield = ipahal_fltrt_objs[ipa_hw_type].eq_bitfield; for (i = 0; i < IPA_EQ_MAX; i++) { if (!IPA_IS_RULE_EQ_VALID(i)) continue; if (eq_bits & IPA_GET_RULE_EQ_BIT_PTRN(eq_bitfield[i])) { IPAHAL_ERR("more than eq with same bit. eq=%d\n", i); WARN_ON(1); return -EFAULT; } eq_bits |= IPA_GET_RULE_EQ_BIT_PTRN(eq_bitfield[i]); } mem = &ipahal_ctx->empty_fltrt_tbl; /* setup an empty table in system memory; This will Loading Loading @@ -3735,14 +3943,14 @@ int ipahal_rt_generate_hw_rule(struct ipahal_rt_rule_gen_params *params, if (!tmp) return -ENOMEM; buf = tmp; } else } else { if ((long)buf & obj->rule_start_alignment) { IPAHAL_ERR("buff is not rule rule start aligned\n"); IPAHAL_ERR("buff is not rule start aligned\n"); return -EPERM; } } rc = ipahal_fltrt_objs[ipahal_ctx->hw_type].rt_generate_hw_rule( params, hw_len, buf); rc = obj->rt_generate_hw_rule(params, hw_len, buf); if (!tmp && !rc) { /* write the rule-set terminator */ memset(buf + *hw_len, 0, obj->tbl_width); Loading Loading @@ -3800,8 +4008,7 @@ int ipahal_flt_generate_hw_rule(struct ipahal_flt_rule_gen_params *params, return -EPERM; } rc = ipahal_fltrt_objs[ipahal_ctx->hw_type].flt_generate_hw_rule( params, hw_len, buf); rc = obj->flt_generate_hw_rule(params, hw_len, buf); if (!tmp && !rc) { /* write the rule-set terminator */ memset(buf + *hw_len, 0, obj->tbl_width); Loading drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt_i.h +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -36,6 +36,7 @@ enum ipa_fltrt_equations { IPA_IHL_OFFSET_EQ_16, IPA_FL_EQ, IPA_IS_FRAG, IPA_IS_PURE_ACK, IPA_EQ_MAX, }; Loading Loading
drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +15 −6 Original line number Diff line number Diff line Loading @@ -431,11 +431,16 @@ static int ipa3_attrib_dump(struct ipa_rule_attrib *attrib, uint32_t mask[4]; int i; if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) pr_err("tos_value:%d ", attrib->tos_value); if (attrib->attrib_mask & IPA_FLT_IS_PURE_ACK) pr_err("is_pure_ack "); if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) pr_err("tos_mask:%d ", attrib->tos_mask); if (attrib->attrib_mask & IPA_FLT_TOS) pr_cont("tos:%d ", attrib->u.v4.tos); if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) { pr_cont("tos_value:%d ", attrib->tos_value); pr_cont("tos_mask:%d ", attrib->tos_mask); } if (attrib->attrib_mask & IPA_FLT_PROTOCOL) pr_err("protocol:%d ", attrib->u.v4.protocol); Loading Loading @@ -557,8 +562,12 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib) int i; int j; if (attrib->tos_eq_present) pr_err("tos_value:%d ", attrib->tos_eq); if (attrib->tos_eq_present) { if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) pr_err("pure_ack "); else pr_err("tos:%d ", attrib->tos_eq); } if (attrib->protocol_eq_present) pr_err("protocol:%d ", attrib->protocol_eq); Loading
drivers/platform/msm/ipa/ipa_v3/ipa_flt.c +20 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,26 @@ static int ipa3_generate_flt_hw_rule(enum ipa_ip_type ip, memset(&gen_params, 0, sizeof(gen_params)); if (entry->rule.hashable) { if (entry->rule.attrib.attrib_mask & IPA_FLT_IS_PURE_ACK && !entry->rule.eq_attrib_type) { IPAERR_RL("PURE_ACK rule atrb used with hash rule\n"); WARN_ON_RATELIMIT_IPA(1); return -EPERM; } /* * tos_eq_present field has two meanings: * tos equation for IPA ver < 4.5 (as the field name reveals) * pure_ack equation for IPA ver >= 4.5 */ if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5 && entry->rule.eq_attrib_type && entry->rule.eq_attrib.tos_eq_present) { IPAERR_RL("PURE_ACK rule eq used with hash rule\n"); return -EPERM; } } gen_params.ipt = ip; if (entry->rt_tbl) gen_params.rt_tbl_idx = entry->rt_tbl->idx; Loading
drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +7 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,13 @@ static int ipa_generate_rt_hw_rule(enum ipa_ip_type ip, memset(&gen_params, 0, sizeof(gen_params)); if (entry->rule.hashable && entry->rule.attrib.attrib_mask & IPA_FLT_IS_PURE_ACK) { IPAERR_RL("PURE_ACK rule atrb used with hash rule\n"); WARN_ON_RATELIMIT_IPA(1); return -EPERM; } gen_params.ipt = ip; gen_params.dst_pipe_idx = ipa3_get_ep_mapping(entry->rule.dst); if (gen_params.dst_pipe_idx == -1) { Loading
drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c +274 −67 Original line number Diff line number Diff line Loading @@ -44,7 +44,8 @@ * @flt_generate_eq: Generate flt equation attributes from rule attributes * @rt_parse_hw_rule: Parse rt rule read from H/W * @flt_parse_hw_rule: Parse flt rule read from H/W * @eq_bitfield: Array of the bit fields of the support equations * @eq_bitfield: Array of the bit fields of the support equations. * 0xFF means the equation is not supported */ struct ipahal_fltrt_obj { bool support_hash; Loading Loading @@ -172,6 +173,9 @@ static int ipa_flt_parse_hw_rule_ipav4(u8 *addr, #define IPA_GET_RULE_EQ_BIT_PTRN(__eq) \ (BIT(ipahal_fltrt_objs[ipahal_ctx->hw_type].eq_bitfield[(__eq)])) #define IPA_IS_RULE_EQ_VALID(__eq) \ (ipahal_fltrt_objs[ipahal_ctx->hw_type].eq_bitfield[(__eq)] != 0xFF) /* * ipa_fltrt_rule_generation_err_check() - check basic validity on the rule * attribs before starting building it Loading Loading @@ -489,6 +493,7 @@ static struct ipahal_fltrt_obj ipahal_fltrt_objs[IPA_HW_MAX] = { [IPA_IHL_OFFSET_EQ_16] = 13, [IPA_FL_EQ] = 14, [IPA_IS_FRAG] = 15, [IPA_IS_PURE_ACK] = 0xFF, }, }, Loading Loading @@ -533,6 +538,7 @@ static struct ipahal_fltrt_obj ipahal_fltrt_objs[IPA_HW_MAX] = { [IPA_IHL_OFFSET_EQ_16] = 13, [IPA_FL_EQ] = 14, [IPA_IS_FRAG] = 15, [IPA_IS_PURE_ACK] = 0xFF, }, }, Loading Loading @@ -577,6 +583,7 @@ static struct ipahal_fltrt_obj ipahal_fltrt_objs[IPA_HW_MAX] = { [IPA_IHL_OFFSET_EQ_16] = 13, [IPA_FL_EQ] = 14, [IPA_IS_FRAG] = 15, [IPA_IS_PURE_ACK] = 0xFF, }, }, Loading Loading @@ -605,7 +612,7 @@ static struct ipahal_fltrt_obj ipahal_fltrt_objs[IPA_HW_MAX] = { ipa_rt_parse_hw_rule, ipa_flt_parse_hw_rule_ipav4, { [IPA_TOS_EQ] = 0, [IPA_TOS_EQ] = 0xFF, [IPA_PROTOCOL_EQ] = 1, [IPA_TC_EQ] = 2, [IPA_OFFSET_MEQ128_0] = 3, Loading @@ -621,6 +628,7 @@ static struct ipahal_fltrt_obj ipahal_fltrt_objs[IPA_HW_MAX] = { [IPA_IHL_OFFSET_EQ_16] = 13, [IPA_FL_EQ] = 14, [IPA_IS_FRAG] = 15, [IPA_IS_PURE_ACK] = 0, }, }, }; Loading Loading @@ -696,10 +704,25 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, u8 ihl_ofst_meq32 = 0; u8 ofst_meq128 = 0; int rc = 0; bool tos_done = false; if (attrib->attrib_mask & IPA_FLT_IS_PURE_ACK) { if (!IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK)) { IPAHAL_ERR("is_pure_ack eq not supported\n"); goto err; } *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_PURE_ACK); extra = ipa_write_8(0, extra); } if (attrib->attrib_mask & IPA_FLT_TOS) { if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { if (!IPA_IS_RULE_EQ_VALID(IPA_TOS_EQ)) { IPAHAL_DBG("tos eq not supported\n"); } else { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_TOS_EQ); extra = ipa_write_8(attrib->u.v4.tos, extra); tos_done = true; } } if (attrib->attrib_mask & IPA_FLT_PROTOCOL) { Loading Loading @@ -790,7 +813,7 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, } *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( ipa3_0_ofst_meq32[ofst_meq32]); /* 0 => offset of TOS in v4 header */ /* 0 => Take the first word. offset of TOS in v4 header is 1 */ extra = ipa_write_8(0, extra); rest = ipa_write_32((attrib->tos_mask << 16), rest); rest = ipa_write_32((attrib->tos_value << 16), rest); Loading Loading @@ -841,6 +864,24 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, ofst_meq32++; } if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq32, ofst_meq32)) { IPAHAL_DBG("ran out of meq32 eq\n"); } else { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( ipa3_0_ofst_meq32[ofst_meq32]); /* * 0 => Take the first word. * offset of TOS in v4 header is 1 */ extra = ipa_write_8(0, extra); rest = ipa_write_32(0xFF << 16, rest); rest = ipa_write_32((attrib->u.v4.tos << 16), rest); ofst_meq32++; tos_done = true; } } if (attrib->attrib_mask & IPA_FLT_TYPE) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, ihl_ofst_meq32)) { Loading Loading @@ -933,6 +974,26 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, ihl_ofst_meq32++; } if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, ihl_ofst_meq32)) { IPAHAL_DBG("ran out of ihl_meq32 eq\n"); } else { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( ipa3_0_ihl_ofst_meq32[ihl_ofst_meq32]); /* * 0 => Take the first word. offset of TOS in * v4 header is 1. MSB bit asserted at IHL means * to ignore packet IHL and do offset inside IPA header */ extra = ipa_write_8(0x80, extra); rest = ipa_write_32(0xFF << 16, rest); rest = ipa_write_32((attrib->u.v4.tos << 16), rest); ihl_ofst_meq32++; tos_done = true; } } if (attrib->attrib_mask & IPA_FLT_META_DATA) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_METADATA_COMPARE); rest = ipa_write_32(attrib->meta_data_mask, rest); Loading Loading @@ -1010,6 +1071,11 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip4(u16 *en_rule, if (attrib->attrib_mask & IPA_FLT_FRAGMENT) *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_FRAG); if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { IPAHAL_ERR("could not find equation for tos\n"); goto err; } goto done; err: Loading @@ -1033,6 +1099,14 @@ static int ipa_fltrt_generate_hw_rule_bdy_ip6(u16 *en_rule, int rc = 0; /* v6 code below assumes no extension headers TODO: fix this */ if (attrib->attrib_mask & IPA_FLT_IS_PURE_ACK) { if (!IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK)) { IPAHAL_ERR("is_pure_ack eq not supported\n"); goto err; } *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_PURE_ACK); extra = ipa_write_8(0, extra); } if (attrib->attrib_mask & IPA_FLT_NEXT_HDR) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_PROTOCOL_EQ); Loading Loading @@ -1597,6 +1671,12 @@ static int ipa_fltrt_calc_extra_wrd_bytes( { int num = 0; /* * tos_eq_present field has two meanings: * tos equation for IPA ver < 4.5 (as the field name reveals) * pure_ack equation for IPA ver >= 4.5 * In both cases it needs one extra word. */ if (attrib->tos_eq_present) num++; if (attrib->protocol_eq_present) Loading Loading @@ -1650,8 +1730,22 @@ static int ipa_fltrt_generate_hw_rule_bdy_from_eq( rest = *buf; } if (attrib->tos_eq_present) /* * tos_eq_present field has two meanings: * tos equation for IPA ver < 4.5 (as the field name reveals) * pure_ack equation for IPA ver >= 4.5 * In both cases it needs one extra word. */ if (attrib->tos_eq_present) { if (IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK)) { extra = ipa_write_8(0, extra); } else if (IPA_IS_RULE_EQ_VALID(IPA_TOS_EQ)) { extra = ipa_write_8(attrib->tos_eq, extra); } else { IPAHAL_ERR("no support for pure_ack and tos eqs\n"); return -EPERM; } } if (attrib->protocol_eq_present) extra = ipa_write_8(attrib->protocol_eq, extra); Loading Loading @@ -1807,12 +1901,32 @@ static int ipa_flt_generate_eq_ip4(enum ipa_ip_type ip, u8 ofst_meq128 = 0; u16 eq_bitmap = 0; u16 *en_rule = &eq_bitmap; bool tos_done = false; if (attrib->attrib_mask & IPA_FLT_IS_PURE_ACK) { if (!IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK)) { IPAHAL_ERR("is_pure_ack eq not supported\n"); return -EPERM; } *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_PURE_ACK); /* * Starting IPA 4.5, where PURE ACK equation supported * and TOS equation support removed, field tos_eq_present * represent pure_ack presence. */ eq_atrb->tos_eq_present = 1; eq_atrb->tos_eq = 0; } if (attrib->attrib_mask & IPA_FLT_TOS) { if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { if (!IPA_IS_RULE_EQ_VALID(IPA_TOS_EQ)) { IPAHAL_DBG("tos eq not supported\n"); } else { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_TOS_EQ); eq_atrb->tos_eq_present = 1; eq_atrb->tos_eq = attrib->u.v4.tos; } } if (attrib->attrib_mask & IPA_FLT_PROTOCOL) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_PROTOCOL_EQ); Loading Loading @@ -1993,6 +2107,26 @@ static int ipa_flt_generate_eq_ip4(enum ipa_ip_type ip, ofst_meq32++; } if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ofst_meq32, ofst_meq32)) { IPAHAL_DBG("ran out of meq32 eq\n"); } else { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( ipa3_0_ofst_meq32[ofst_meq32]); /* * offset 0 => Take the first word. * offset of TOS in v4 header is 1 */ eq_atrb->offset_meq_32[ofst_meq32].offset = 0; eq_atrb->offset_meq_32[ofst_meq32].mask = 0xFF << 16; eq_atrb->offset_meq_32[ofst_meq32].value = attrib->u.v4.tos << 16; ofst_meq32++; tos_done = true; } } if (attrib->attrib_mask & IPA_FLT_TYPE) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, ihl_ofst_meq32)) { Loading Loading @@ -2039,6 +2173,29 @@ static int ipa_flt_generate_eq_ip4(enum ipa_ip_type ip, ihl_ofst_meq32++; } if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { if (IPA_IS_RAN_OUT_OF_EQ(ipa3_0_ihl_ofst_meq32, ihl_ofst_meq32)) { IPAHAL_DBG("ran out of ihl_meq32 eq\n"); } else { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( ipa3_0_ihl_ofst_meq32[ihl_ofst_meq32]); /* * 0 => Take the first word. offset of TOS in * v4 header is 1. MSB bit asserted at IHL means * to ignore packet IHL and do offset inside IPA header */ eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].offset = 0x80; eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].mask = 0xFF << 16; eq_atrb->ihl_offset_meq_32[ihl_ofst_meq32].value = attrib->u.v4.tos << 16; ihl_ofst_meq32++; tos_done = true; } } if (attrib->attrib_mask & IPA_FLT_META_DATA) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( IPA_METADATA_COMPARE); Loading Loading @@ -2125,6 +2282,11 @@ static int ipa_flt_generate_eq_ip4(enum ipa_ip_type ip, eq_atrb->ipv4_frag_eq_present = 1; } if (attrib->attrib_mask & IPA_FLT_TOS && !tos_done) { IPAHAL_ERR("could not find equation for tos\n"); return -EPERM; } eq_atrb->rule_eq_bitmap = *en_rule; eq_atrb->num_offset_meq_32 = ofst_meq32; eq_atrb->num_ihl_offset_range_16 = ihl_ofst_rng16; Loading @@ -2145,6 +2307,21 @@ static int ipa_flt_generate_eq_ip6(enum ipa_ip_type ip, u16 eq_bitmap = 0; u16 *en_rule = &eq_bitmap; if (attrib->attrib_mask & IPA_FLT_IS_PURE_ACK) { if (!IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK)) { IPAHAL_ERR("is_pure_ack eq not supported\n"); return -EPERM; } *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_PURE_ACK); /* * Starting IPA 4.5, where PURE ACK equation supported * and TOS equation support removed, field tos_eq_present * represent pure_ack presenence. */ eq_atrb->tos_eq_present = 1; eq_atrb->tos_eq = 0; } if (attrib->attrib_mask & IPA_FLT_NEXT_HDR) { *en_rule |= IPA_GET_RULE_EQ_BIT_PTRN( IPA_PROTOCOL_EQ); Loading Loading @@ -2658,8 +2835,19 @@ static int ipa_fltrt_parse_hw_rule_eq(u8 *addr, u32 hdr_sz, IPAHAL_DBG_LOW("eq_bitmap=0x%x\n", eq_bitmap); if (eq_bitmap & IPA_GET_RULE_EQ_BIT_PTRN(IPA_TOS_EQ)) if (IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK) && (eq_bitmap & IPA_GET_RULE_EQ_BIT_PTRN(IPA_IS_PURE_ACK))) { /* * tos_eq_present field represents pure_ack when pure * ack equation valid (started IPA 4.5). In this case * tos equation should not be supported. */ atrb->tos_eq_present = true; } if (IPA_IS_RULE_EQ_VALID(IPA_TOS_EQ) && (eq_bitmap & IPA_GET_RULE_EQ_BIT_PTRN(IPA_TOS_EQ))) { atrb->tos_eq_present = true; } if (eq_bitmap & IPA_GET_RULE_EQ_BIT_PTRN(IPA_PROTOCOL_EQ)) atrb->protocol_eq_present = true; if (eq_bitmap & IPA_GET_RULE_EQ_BIT_PTRN(IPA_TC_EQ)) Loading Loading @@ -2715,8 +2903,12 @@ static int ipa_fltrt_parse_hw_rule_eq(u8 *addr, u32 hdr_sz, IPAHAL_DBG_LOW("addr=0x%pK extra=0x%pK rest=0x%pK\n", addr, extra, rest); if (atrb->tos_eq_present) if (IPA_IS_RULE_EQ_VALID(IPA_TOS_EQ) && atrb->tos_eq_present) atrb->tos_eq = *extra++; if (IPA_IS_RULE_EQ_VALID(IPA_IS_PURE_ACK) && atrb->tos_eq_present) { atrb->tos_eq = 0; extra++; } if (atrb->protocol_eq_present) atrb->protocol_eq = *extra++; if (atrb->tc_eq_present) Loading Loading @@ -2839,7 +3031,7 @@ static int ipa_rt_parse_hw_rule(u8 *addr, struct ipahal_rt_rule_entry *rule) IPAHAL_DBG_LOW("read hdr 0x%llx\n", rule_hdr->u.word); if (rule_hdr->u.word == 0) { /* table termintator - empty table */ /* table terminator - empty table */ rule->rule_size = 0; return 0; } Loading Loading @@ -2971,6 +3163,8 @@ int ipahal_fltrt_init(enum ipa_hw_type ipa_hw_type) int i; struct ipa_mem_buffer *mem; int rc = -EFAULT; u32 eq_bits; u8 *eq_bitfield; IPAHAL_DBG("Entry - HW_TYPE=%d\n", ipa_hw_type); Loading Loading @@ -3102,6 +3296,20 @@ int ipahal_fltrt_init(enum ipa_hw_type ipa_hw_type) } } eq_bits = 0; eq_bitfield = ipahal_fltrt_objs[ipa_hw_type].eq_bitfield; for (i = 0; i < IPA_EQ_MAX; i++) { if (!IPA_IS_RULE_EQ_VALID(i)) continue; if (eq_bits & IPA_GET_RULE_EQ_BIT_PTRN(eq_bitfield[i])) { IPAHAL_ERR("more than eq with same bit. eq=%d\n", i); WARN_ON(1); return -EFAULT; } eq_bits |= IPA_GET_RULE_EQ_BIT_PTRN(eq_bitfield[i]); } mem = &ipahal_ctx->empty_fltrt_tbl; /* setup an empty table in system memory; This will Loading Loading @@ -3735,14 +3943,14 @@ int ipahal_rt_generate_hw_rule(struct ipahal_rt_rule_gen_params *params, if (!tmp) return -ENOMEM; buf = tmp; } else } else { if ((long)buf & obj->rule_start_alignment) { IPAHAL_ERR("buff is not rule rule start aligned\n"); IPAHAL_ERR("buff is not rule start aligned\n"); return -EPERM; } } rc = ipahal_fltrt_objs[ipahal_ctx->hw_type].rt_generate_hw_rule( params, hw_len, buf); rc = obj->rt_generate_hw_rule(params, hw_len, buf); if (!tmp && !rc) { /* write the rule-set terminator */ memset(buf + *hw_len, 0, obj->tbl_width); Loading Loading @@ -3800,8 +4008,7 @@ int ipahal_flt_generate_hw_rule(struct ipahal_flt_rule_gen_params *params, return -EPERM; } rc = ipahal_fltrt_objs[ipahal_ctx->hw_type].flt_generate_hw_rule( params, hw_len, buf); rc = obj->flt_generate_hw_rule(params, hw_len, buf); if (!tmp && !rc) { /* write the rule-set terminator */ memset(buf + *hw_len, 0, obj->tbl_width); Loading
drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt_i.h +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -36,6 +36,7 @@ enum ipa_fltrt_equations { IPA_IHL_OFFSET_EQ_16, IPA_FL_EQ, IPA_IS_FRAG, IPA_IS_PURE_ACK, IPA_EQ_MAX, }; Loading