msm: ipa: Fix Tos value issue in IPA
Fix TOS mast-filtering rules configured in HW,
the QOS value is set in the upper 3 bits of the
TOS field. The other bits in the TOS field need
to be ignored.
Change-Id: Id55bb101b9f19dae0210d0c0f958a1be68506f75
Signed-off-by: Skylar Chang <chiaweic@codeaurora.org>
diff --git a/drivers/platform/msm/ipa/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_debugfs.c
index aaf5cc0..87ddf59 100644
--- a/drivers/platform/msm/ipa/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_debugfs.c
@@ -346,11 +346,18 @@
uint32_t mask[4];
int i;
- if (attrib->attrib_mask & IPA_FLT_TOS) {
- nbytes = scnprintf(buff + cnt, sz - cnt, "tos:%d ",
- attrib->u.v4.tos);
+
+ if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) {
+ nbytes = scnprintf(buff + cnt, sz - cnt, "tos_value:%d ",
+ attrib->tos_value);
cnt += nbytes;
}
+ if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) {
+ nbytes = scnprintf(buff + cnt, sz - cnt, "tos_mask:%d ",
+ attrib->tos_mask);
+ cnt += nbytes;
+ }
+
if (attrib->attrib_mask & IPA_FLT_PROTOCOL) {
nbytes = scnprintf(buff + cnt, sz - cnt, "protocol:%d ",
attrib->u.v4.protocol);
diff --git a/drivers/platform/msm/ipa/ipa_rt.c b/drivers/platform/msm/ipa/ipa_rt.c
index 6430c07..5c27c40 100644
--- a/drivers/platform/msm/ipa/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_rt.c
@@ -67,13 +67,31 @@
}
rule_hdr->u.hdr.pipe_dest_idx = pipe_idx;
rule_hdr->u.hdr.system = !ipa_ctx->hdr_tbl_lcl;
- if (entry->hdr)
+ if (entry->hdr) {
rule_hdr->u.hdr.hdr_offset =
entry->hdr->offset_entry->offset >> 2;
- else
+ } else {
rule_hdr->u.hdr.hdr_offset = 0;
-
+ }
buf += sizeof(struct ipa_rt_rule_hw_hdr);
+ if ((ip == IPA_IP_v4) &&
+ (entry->rule.attrib.attrib_mask & IPA_FLT_TOS)) {
+ entry->rule.attrib.tos_value =
+ (entry->rule.attrib.u.v4.tos << 5);
+ entry->rule.attrib.tos_mask = 0xe0;
+ entry->rule.attrib.attrib_mask &= ~IPA_FLT_TOS;
+ entry->rule.attrib.attrib_mask |= IPA_FLT_TOS_MASKED;
+ }
+
+ if ((ip == IPA_IP_v6) &&
+ (entry->rule.attrib.attrib_mask & IPA_FLT_TC)) {
+ entry->rule.attrib.tos_value =
+ (entry->rule.attrib.u.v6.tc << 5);
+ entry->rule.attrib.tos_mask = 0xe0;
+ entry->rule.attrib.attrib_mask &= ~IPA_FLT_TC;
+ entry->rule.attrib.attrib_mask |= IPA_FLT_TOS_MASKED;
+ }
+
if (ipa_generate_hw_rule(ip, &rule->attrib, &buf, &en_rule)) {
IPAERR("fail to generate hw rule\n");
return -EPERM;
diff --git a/drivers/platform/msm/ipa/ipa_utils.c b/drivers/platform/msm/ipa/ipa_utils.c
index 23de300..21a6dc4 100644
--- a/drivers/platform/msm/ipa/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_utils.c
@@ -237,6 +237,20 @@
*buf = ipa_pad_to_32(*buf);
}
+ if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) {
+ if (ipa_ofst_meq32[ofst_meq32] == -1) {
+ IPAERR("ran out of meq32 eq\n");
+ return -EPERM;
+ }
+ *en_rule |= ipa_ofst_meq32[ofst_meq32];
+ /* 0 => offset of TOS in v4 header */
+ *buf = ipa_write_8(0, *buf);
+ *buf = ipa_write_32((attrib->tos_mask << 16), *buf);
+ *buf = ipa_write_32(attrib->tos_value, *buf);
+ *buf = ipa_pad_to_32(*buf);
+ ofst_meq32++;
+ }
+
if (attrib->attrib_mask & IPA_FLT_PROTOCOL) {
*en_rule |= IPA_PROTOCOL_EQ;
*buf = ipa_write_8(attrib->u.v4.protocol, *buf);
@@ -568,6 +582,20 @@
*buf = ipa_pad_to_32(*buf);
}
+ if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) {
+ if (ipa_ofst_meq32[ofst_meq32] == -1) {
+ IPAERR("ran out of meq32 eq\n");
+ return -EPERM;
+ }
+ *en_rule |= ipa_ofst_meq32[ofst_meq32];
+ /* 0 => offset of TOS in v4 header */
+ *buf = ipa_write_8(0, *buf);
+ *buf = ipa_write_32((attrib->tos_mask << 20), *buf);
+ *buf = ipa_write_32(attrib->tos_value, *buf);
+ *buf = ipa_pad_to_32(*buf);
+ ofst_meq32++;
+ }
+
if (attrib->attrib_mask & IPA_FLT_FLOW_LABEL) {
*en_rule |= IPA_FLT_FLOW_LABEL;
/* FIXME FL is only 20 bits */
diff --git a/include/linux/msm_ipa.h b/include/linux/msm_ipa.h
index 5151654..b2229d3 100644
--- a/include/linux/msm_ipa.h
+++ b/include/linux/msm_ipa.h
@@ -87,6 +87,7 @@
#define IPA_FLT_NEXT_HDR (1ul << 13)
#define IPA_FLT_META_DATA (1ul << 14)
#define IPA_FLT_FRAGMENT (1ul << 15)
+#define IPA_FLT_TOS_MASKED (1ul << 16)
/**
* enum ipa_client_type - names for the various IPA "clients"
@@ -243,6 +244,8 @@
uint16_t dst_port_hi;
uint8_t type;
uint8_t code;
+ uint8_t tos_value;
+ uint8_t tos_mask;
uint32_t spi;
uint16_t src_port;
uint16_t dst_port;