msm: ipa3: Move IPA headers building to IPAHAL

IPA headers building is a logic related to H/W.
As such, migrating this logic to IPAHAL (H/W abstraction
layer) of IPA driver and adapt the core driver code to use
it. New internal S/W API is added to access IPAHAL for
headers building.

CRs-fixed: 989231
Change-Id: I2cec6c6f9fe7aea0e2276b01133f8c3505b9919f
Signed-off-by: Amir Levy <alevy@codeaurora.org>
This commit is contained in:
Amir Levy 2016-05-02 17:00:13 +03:00 committed by Jeevan Shriram
parent 3f5faf42db
commit a5560fb54c
6 changed files with 348 additions and 124 deletions

View file

@ -22,12 +22,6 @@ static const u32 ipa_hdr_proc_ctx_bin_sz[IPA_HDR_PROC_CTX_BIN_MAX] = { 32, 64};
#define HDR_PROC_TYPE_IS_VALID(type) \
((type) >= 0 && (type) < IPA_HDR_PROC_MAX)
/* uCP command numbers */
#define IPA_HDR_UCP_802_3_TO_802_3 6
#define IPA_HDR_UCP_802_3_TO_ETHII 7
#define IPA_HDR_UCP_ETHII_TO_802_3 8
#define IPA_HDR_UCP_ETHII_TO_ETHII 9
/**
* ipa3_generate_hdr_hw_tbl() - generates the headers table
* @mem: [out] buffer to put the header table
@ -60,70 +54,36 @@ static int ipa3_generate_hdr_hw_tbl(struct ipa3_mem_buffer *mem)
continue;
IPADBG_LOW("hdr of len %d ofst=%d\n", entry->hdr_len,
entry->offset_entry->offset);
memcpy(mem->base + entry->offset_entry->offset, entry->hdr,
entry->hdr_len);
ipahal_cp_hdr_to_hw_buff(mem->base, entry->offset_entry->offset,
entry->hdr, entry->hdr_len);
}
return 0;
}
static void ipa3_hdr_proc_ctx_to_hw_format(struct ipa3_mem_buffer *mem,
static int ipa3_hdr_proc_ctx_to_hw_format(struct ipa3_mem_buffer *mem,
u32 hdr_base_addr)
{
struct ipa3_hdr_proc_ctx_entry *entry;
int ret;
list_for_each_entry(entry,
&ipa3_ctx->hdr_proc_ctx_tbl.head_proc_ctx_entry_list,
link) {
IPADBG_LOW("processing type %d ofst=%d\n",
entry->type, entry->offset_entry->offset);
if (entry->type == IPA_HDR_PROC_NONE) {
struct ipa3_hdr_proc_ctx_add_hdr_seq *ctx;
ctx = (struct ipa3_hdr_proc_ctx_add_hdr_seq *)
(mem->base + entry->offset_entry->offset);
ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
ctx->hdr_add.tlv.length = 1;
ctx->hdr_add.tlv.value = entry->hdr->hdr_len;
ctx->hdr_add.hdr_addr = (entry->hdr->is_hdr_proc_ctx) ?
entry->hdr->phys_base :
hdr_base_addr +
entry->hdr->offset_entry->offset;
IPADBG_LOW("header address 0x%x\n",
ctx->hdr_add.hdr_addr);
ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END;
ctx->end.length = 0;
ctx->end.value = 0;
} else {
struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq *ctx;
ctx = (struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq *)
(mem->base + entry->offset_entry->offset);
ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
ctx->hdr_add.tlv.length = 1;
ctx->hdr_add.tlv.value = entry->hdr->hdr_len;
ctx->hdr_add.hdr_addr = (entry->hdr->is_hdr_proc_ctx) ?
entry->hdr->phys_base :
hdr_base_addr +
entry->hdr->offset_entry->offset;
IPADBG_LOW("header address 0x%x\n",
ctx->hdr_add.hdr_addr);
ctx->cmd.type = IPA_PROC_CTX_TLV_TYPE_PROC_CMD;
ctx->cmd.length = 0;
if (entry->type == IPA_HDR_PROC_ETHII_TO_ETHII)
ctx->cmd.value = IPA_HDR_UCP_ETHII_TO_ETHII;
else if (entry->type == IPA_HDR_PROC_ETHII_TO_802_3)
ctx->cmd.value = IPA_HDR_UCP_ETHII_TO_802_3;
else if (entry->type == IPA_HDR_PROC_802_3_TO_ETHII)
ctx->cmd.value = IPA_HDR_UCP_802_3_TO_ETHII;
else if (entry->type == IPA_HDR_PROC_802_3_TO_802_3)
ctx->cmd.value = IPA_HDR_UCP_802_3_TO_802_3;
IPADBG_LOW("command id %d\n", ctx->cmd.value);
ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END;
ctx->end.length = 0;
ctx->end.value = 0;
}
ret = ipahal_cp_proc_ctx_to_hw_buff(entry->type, mem->base,
entry->offset_entry->offset,
entry->hdr->hdr_len,
entry->hdr->is_hdr_proc_ctx,
entry->hdr->phys_base,
hdr_base_addr,
entry->hdr->offset_entry->offset);
if (ret)
return ret;
}
return 0;
}
/**
@ -162,9 +122,7 @@ static int ipa3_generate_hdr_proc_ctx_hw_tbl(u32 hdr_sys_addr,
memset(aligned_mem->base, 0, aligned_mem->size);
hdr_base_addr = (ipa3_ctx->hdr_tbl_lcl) ? IPA_MEM_PART(apps_hdr_ofst) :
hdr_sys_addr;
ipa3_hdr_proc_ctx_to_hw_format(aligned_mem, hdr_base_addr);
return 0;
return ipa3_hdr_proc_ctx_to_hw_format(aligned_mem, hdr_base_addr);
}
/**
@ -395,9 +353,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx,
hdr_entry->ref_cnt++;
entry->cookie = IPA_COOKIE;
needed_len = (proc_ctx->type == IPA_HDR_PROC_NONE) ?
sizeof(struct ipa3_hdr_proc_ctx_add_hdr_seq) :
sizeof(struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq);
needed_len = ipahal_get_proc_ctx_needed_len(proc_ctx->type);
if (needed_len <= ipa_hdr_proc_ctx_bin_sz[IPA_HDR_PROC_CTX_BIN0]) {
bin = IPA_HDR_PROC_CTX_BIN0;

View file

@ -16,11 +16,6 @@
/* This header defines various HW related data types */
/* Processing context TLV type */
#define IPA_PROC_CTX_TLV_TYPE_END 0
#define IPA_PROC_CTX_TLV_TYPE_HDR_ADD 1
#define IPA_PROC_CTX_TLV_TYPE_PROC_CMD 3
#define IPA_RULE_ID_INVALID 0x3FF
/**
@ -94,40 +89,6 @@ struct ipa3_rt_rule_hw_hdr {
} u;
};
/**
* struct ipa3_hdr_proc_ctx_tlv -
* HW structure of IPA processing context header - TLV part
* @type: 0 - end type
* 1 - header addition type
* 3 - processing command type
* @length: number of bytes after tlv
* for type:
* 0 - needs to be 0
* 1 - header addition length
* 3 - number of 32B including type and length.
* @value: specific value for type
* for type:
* 0 - needs to be 0
* 1 - header length
* 3 - command ID (see IPA_HDR_UCP_* definitions)
*/
struct ipa3_hdr_proc_ctx_tlv {
u32 type:8;
u32 length:8;
u32 value:16;
};
/**
* struct ipa3_hdr_proc_ctx_hdr_add -
* HW structure of IPA processing context - add header tlv
* @tlv: IPA processing context TLV
* @hdr_addr: processing context header address
*/
struct ipa3_hdr_proc_ctx_hdr_add {
struct ipa3_hdr_proc_ctx_tlv tlv;
u32 hdr_addr;
};
#define IPA_A5_MUX_HDR_EXCP_FLAG_IP BIT(7)
#define IPA_A5_MUX_HDR_EXCP_FLAG_NAT BIT(6)
#define IPA_A5_MUX_HDR_EXCP_FLAG_SW_FLT BIT(5)

View file

@ -395,30 +395,6 @@ struct ipa3_hdr_proc_ctx_offset_entry {
u32 bin;
};
/**
* struct ipa3_hdr_proc_ctx_add_hdr_seq -
* IPA processing context header - add header sequence
* @hdr_add: add header command
* @end: tlv end command (cmd.type must be 0)
*/
struct ipa3_hdr_proc_ctx_add_hdr_seq {
struct ipa3_hdr_proc_ctx_hdr_add hdr_add;
struct ipa3_hdr_proc_ctx_tlv end;
};
/**
* struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq -
* IPA processing context header - process command sequence
* @hdr_add: add header command
* @cmd: tlv processing command (cmd.type must be 3)
* @end: tlv end command (cmd.type must be 0)
*/
struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq {
struct ipa3_hdr_proc_ctx_hdr_add hdr_add;
struct ipa3_hdr_proc_ctx_tlv cmd;
struct ipa3_hdr_proc_ctx_tlv end;
};
/**
struct ipa3_hdr_proc_ctx_entry - IPA processing context header table entry
* @link: entry's link in global header table entries list

View file

@ -1018,6 +1018,229 @@ static void ipahal_debugfs_init(void) {}
static void ipahal_debugfs_remove(void) {}
#endif /* CONFIG_DEBUG_FS */
/*
* ipahal_cp_hdr_to_hw_buff_v3() - copy header to hardware buffer according to
* base address and offset given.
* @base: dma base address
* @offset: offset from base address where the data will be copied
* @hdr: the header to be copied
* @hdr_len: the length of the header
*/
static void ipahal_cp_hdr_to_hw_buff_v3(void *const base, u32 offset,
u8 *const hdr, u32 hdr_len)
{
memcpy(base + offset, hdr, hdr_len);
}
/*
* ipahal_cp_proc_ctx_to_hw_buff_v3() - copy processing context to
* base address and offset given.
* @type: header processing context type (no processing context,
* IPA_HDR_PROC_ETHII_TO_ETHII etc.)
* @base: dma base address
* @offset: offset from base address where the data will be copied
* @hdr_len: the length of the header
* @is_hdr_proc_ctx: header is located in phys_base (true) or hdr_base_addr
* @phys_base: memory location in DDR
* @hdr_base_addr: base address in table
* @hdr_offset_entry: offset from hdr_base_addr in table
*/
static int ipahal_cp_proc_ctx_to_hw_buff_v3(enum ipa_hdr_proc_type type,
void *const base, u32 offset,
u32 hdr_len, bool is_hdr_proc_ctx,
dma_addr_t phys_base, u32 hdr_base_addr,
u32 hdr_offset_entry){
if (type == IPA_HDR_PROC_NONE) {
struct ipa_hw_hdr_proc_ctx_add_hdr_seq *ctx;
ctx = (struct ipa_hw_hdr_proc_ctx_add_hdr_seq *)
(base + offset);
ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
ctx->hdr_add.tlv.length = 1;
ctx->hdr_add.tlv.value = hdr_len;
ctx->hdr_add.hdr_addr = is_hdr_proc_ctx ? phys_base :
hdr_base_addr + hdr_offset_entry;
IPAHAL_DBG("header address 0x%x\n",
ctx->hdr_add.hdr_addr);
ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END;
ctx->end.length = 0;
ctx->end.value = 0;
} else {
struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq *ctx;
ctx = (struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq *)
(base + offset);
ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
ctx->hdr_add.tlv.length = 1;
ctx->hdr_add.tlv.value = hdr_len;
ctx->hdr_add.hdr_addr = is_hdr_proc_ctx ? phys_base :
hdr_base_addr + hdr_offset_entry;
IPAHAL_DBG("header address 0x%x\n",
ctx->hdr_add.hdr_addr);
ctx->cmd.type = IPA_PROC_CTX_TLV_TYPE_PROC_CMD;
ctx->cmd.length = 0;
switch (type) {
case IPA_HDR_PROC_ETHII_TO_ETHII:
ctx->cmd.value = IPA_HDR_UCP_ETHII_TO_ETHII;
break;
case IPA_HDR_PROC_ETHII_TO_802_3:
ctx->cmd.value = IPA_HDR_UCP_ETHII_TO_802_3;
break;
case IPA_HDR_PROC_802_3_TO_ETHII:
ctx->cmd.value = IPA_HDR_UCP_802_3_TO_ETHII;
break;
case IPA_HDR_PROC_802_3_TO_802_3:
ctx->cmd.value = IPA_HDR_UCP_802_3_TO_802_3;
break;
default:
IPAHAL_ERR("unknown ipa_hdr_proc_type %d", type);
WARN_ON(1);
return -EINVAL;
}
IPAHAL_DBG("command id %d\n", ctx->cmd.value);
ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END;
ctx->end.length = 0;
ctx->end.value = 0;
}
return 0;
}
/*
* ipahal_get_proc_ctx_needed_len_v3() - calculates the needed length for
* addition of header processing context according to the type of processing
* context.
* @type: header processing context type (no processing context,
* IPA_HDR_PROC_ETHII_TO_ETHII etc.)
*/
static int ipahal_get_proc_ctx_needed_len_v3(enum ipa_hdr_proc_type type)
{
return (type == IPA_HDR_PROC_NONE) ?
sizeof(struct ipa_hw_hdr_proc_ctx_add_hdr_seq) :
sizeof(struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq);
}
/*
* struct ipahal_hdr_funcs - headers handling functions for specific IPA
* version
* @ipahal_cp_hdr_to_hw_buff - copy function for regular headers
*/
struct ipahal_hdr_funcs {
void (*ipahal_cp_hdr_to_hw_buff)(void *const base, u32 offset,
u8 *const hdr, u32 hdr_len);
int (*ipahal_cp_proc_ctx_to_hw_buff)(enum ipa_hdr_proc_type type,
void *const base, u32 offset, u32 hdr_len,
bool is_hdr_proc_ctx, dma_addr_t phys_base,
u32 hdr_base_addr, u32 hdr_offset_entry);
int (*ipahal_get_proc_ctx_needed_len)(enum ipa_hdr_proc_type type);
};
static struct ipahal_hdr_funcs hdr_funcs;
static void ipahal_hdr_init(enum ipa_hw_type ipa_hw_type)
{
IPAHAL_DBG("Entry - HW_TYPE=%d\n", ipa_hw_type);
/*
* once there are changes in HW and need to use different case, insert
* new case for the new h/w. put the default always for the latest HW
* and make sure all previous supported versions have their cases.
*/
switch (ipa_hw_type) {
case IPA_HW_v3_0:
default:
hdr_funcs.ipahal_cp_hdr_to_hw_buff =
ipahal_cp_hdr_to_hw_buff_v3;
hdr_funcs.ipahal_cp_proc_ctx_to_hw_buff =
ipahal_cp_proc_ctx_to_hw_buff_v3;
hdr_funcs.ipahal_get_proc_ctx_needed_len =
ipahal_get_proc_ctx_needed_len_v3;
}
IPAHAL_DBG("Exit\n");
}
/*
* ipahal_cp_hdr_to_hw_buff() - copy header to hardware buffer according to
* base address and offset given.
* @base: dma base address
* @offset: offset from base address where the data will be copied
* @hdr: the header to be copied
* @hdr_len: the length of the header
*/
void ipahal_cp_hdr_to_hw_buff(void *base, u32 offset, u8 *const hdr,
u32 hdr_len)
{
IPAHAL_DBG_LOW("Entry\n");
IPAHAL_DBG("base %p, offset %d, hdr %p, hdr_len %d\n", base,
offset, hdr, hdr_len);
if (!base || !hdr_len || !hdr) {
IPAHAL_ERR("failed on validating params");
return;
}
hdr_funcs.ipahal_cp_hdr_to_hw_buff(base, offset, hdr, hdr_len);
IPAHAL_DBG_LOW("Exit\n");
}
/*
* ipahal_cp_proc_ctx_to_hw_buff() - copy processing context to
* base address and offset given.
* @type: type of header processing context
* @base: dma base address
* @offset: offset from base address where the data will be copied
* @hdr_len: the length of the header
* @is_hdr_proc_ctx: header is located in phys_base (true) or hdr_base_addr
* @phys_base: memory location in DDR
* @hdr_base_addr: base address in table
* @hdr_offset_entry: offset from hdr_base_addr in table
*/
int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type,
void *const base, u32 offset, u32 hdr_len,
bool is_hdr_proc_ctx, dma_addr_t phys_base,
u32 hdr_base_addr, u32 hdr_offset_entry)
{
IPAHAL_DBG(
"type %d, base %p, offset %d, hdr_len %d, is_hdr_proc_ctx %d, hdr_base_addr %d, hdr_offset_entry %d\n"
, type, base, offset, hdr_len, is_hdr_proc_ctx,
hdr_base_addr, hdr_offset_entry);
if (!base ||
!hdr_len ||
(!phys_base && !hdr_base_addr) ||
!hdr_base_addr) {
IPAHAL_ERR("failed on validating params");
return -EINVAL;
}
return hdr_funcs.ipahal_cp_proc_ctx_to_hw_buff(type, base, offset,
hdr_len, is_hdr_proc_ctx, phys_base,
hdr_base_addr, hdr_offset_entry);
}
/*
* ipahal_get_proc_ctx_needed_len() - calculates the needed length for
* addition of header processing context according to the type of processing
* context
* @type: header processing context type (no processing context,
* IPA_HDR_PROC_ETHII_TO_ETHII etc.)
*/
int ipahal_get_proc_ctx_needed_len(enum ipa_hdr_proc_type type)
{
int res;
IPAHAL_DBG("entry\n");
res = hdr_funcs.ipahal_get_proc_ctx_needed_len(type);
IPAHAL_DBG("Exit\n");
return res;
}
int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base)
{
int result;
@ -1065,6 +1288,8 @@ int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base)
goto bail_free_ctx;
}
ipahal_hdr_init(ipa_hw_type);
ipahal_debugfs_init();
return 0;

View file

@ -597,6 +597,41 @@ void ipahal_pkt_status_parse(const void *unparsed_status,
const char *ipahal_pkt_status_exception_str(
enum ipahal_pkt_status_exception exception);
/*
* ipahal_cp_hdr_to_hw_buff() - copy header to hardware buffer according to
* base address and offset given.
* @base: dma base address
* @offset: offset from base address where the data will be copied
* @hdr: the header to be copied
* @hdr_len: the length of the header
*/
void ipahal_cp_hdr_to_hw_buff(void *base, u32 offset, u8 *hdr, u32 hdr_len);
/*
* ipahal_cp_proc_ctx_to_hw_buff() - copy processing context to
* base address and offset given.
* @type: type of header processing context
* @base: dma base address
* @offset: offset from base address where the data will be copied
* @hdr_len: the length of the header
* @is_hdr_proc_ctx: header is located in phys_base (true) or hdr_base_addr
* @phys_base: memory location in DDR
* @hdr_base_addr: base address in table
* @hdr_offset_entry: offset from hdr_base_addr in table
*/
int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type,
void *base, u32 offset, u32 hdr_len,
bool is_hdr_proc_ctx, dma_addr_t phys_base,
u32 hdr_base_addr, u32 hdr_offset_entry);
/*
* ipahal_get_proc_ctx_needed_len() - calculates the needed length for addition
* of header processing context according to the type of processing context
* @type: header processing context type (no processing context,
* IPA_HDR_PROC_ETHII_TO_ETHII etc.)
*/
int ipahal_get_proc_ctx_needed_len(enum ipa_hdr_proc_type type);
int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base);
void ipahal_destroy(void);

View file

@ -471,4 +471,75 @@ struct ipa_pkt_status_hw {
/* Size of H/W Packet Status */
#define IPA3_0_PKT_STATUS_SIZE 32
/* Headers and processing context H/W structures and definitions */
/* uCP command numbers */
#define IPA_HDR_UCP_802_3_TO_802_3 6
#define IPA_HDR_UCP_802_3_TO_ETHII 7
#define IPA_HDR_UCP_ETHII_TO_802_3 8
#define IPA_HDR_UCP_ETHII_TO_ETHII 9
/* Processing context TLV type */
#define IPA_PROC_CTX_TLV_TYPE_END 0
#define IPA_PROC_CTX_TLV_TYPE_HDR_ADD 1
#define IPA_PROC_CTX_TLV_TYPE_PROC_CMD 3
/**
* struct ipa_hw_hdr_proc_ctx_tlv -
* HW structure of IPA processing context header - TLV part
* @type: 0 - end type
* 1 - header addition type
* 3 - processing command type
* @length: number of bytes after tlv
* for type:
* 0 - needs to be 0
* 1 - header addition length
* 3 - number of 32B including type and length.
* @value: specific value for type
* for type:
* 0 - needs to be 0
* 1 - header length
* 3 - command ID (see IPA_HDR_UCP_* definitions)
*/
struct ipa_hw_hdr_proc_ctx_tlv {
u32 type:8;
u32 length:8;
u32 value:16;
};
/**
* struct ipa_hw_hdr_proc_ctx_hdr_add -
* HW structure of IPA processing context - add header tlv
* @tlv: IPA processing context TLV
* @hdr_addr: processing context header address
*/
struct ipa_hw_hdr_proc_ctx_hdr_add {
struct ipa_hw_hdr_proc_ctx_tlv tlv;
u32 hdr_addr;
};
/**
* struct ipa_hw_hdr_proc_ctx_add_hdr_seq -
* IPA processing context header - add header sequence
* @hdr_add: add header command
* @end: tlv end command (cmd.type must be 0)
*/
struct ipa_hw_hdr_proc_ctx_add_hdr_seq {
struct ipa_hw_hdr_proc_ctx_hdr_add hdr_add;
struct ipa_hw_hdr_proc_ctx_tlv end;
};
/**
* struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq -
* IPA processing context header - process command sequence
* @hdr_add: add header command
* @cmd: tlv processing command (cmd.type must be 3)
* @end: tlv end command (cmd.type must be 0)
*/
struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq {
struct ipa_hw_hdr_proc_ctx_hdr_add hdr_add;
struct ipa_hw_hdr_proc_ctx_tlv cmd;
struct ipa_hw_hdr_proc_ctx_tlv end;
};
#endif /* _IPAHAL_I_H_ */