1191 lines
34 KiB
C
1191 lines
34 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (C) 2019 MediaTek Inc.
|
|
*/
|
|
#include <linux/kthread.h>
|
|
#include "ccci_bm.h"
|
|
#include "port_proxy.h"
|
|
#include "port_udc.h"
|
|
#include "port_smem.h"
|
|
|
|
extern atomic_t udc_status;
|
|
|
|
#define MAX_QUEUE_LENGTH 16
|
|
|
|
#define Min(a, b) (a < b ? a : b)
|
|
#if (MD_GENERATION >= 6295)
|
|
#define MAX_PACKET_SIZE 1277936 /* (2.4375*1024*1024 -32)/2 */
|
|
#define COMP_DATA_OFFSET (0xC00000 + 32)
|
|
#define RW_INDEX_OFFSET 0xC00000
|
|
#define UDC_UNCMP_CACHE_BUF_SZ 0x64000 /* 400k */
|
|
#define rslt_entry 2048
|
|
#elif (MD_GENERATION == 6293)
|
|
#define MAX_PACKET_SIZE 1048576 /* 2*1024*1024/2 */
|
|
#define COMP_DATA_OFFSET 0x570000
|
|
#define RW_INDEX_OFFSET 0x568000
|
|
#define UDC_UNCMP_CACHE_BUF_SZ 0xC000 /* 48k */
|
|
#define rslt_entry 1024
|
|
#endif
|
|
/*kernel 4.14 diff kernel 4.19
|
|
|
|
In kernel4.19:
|
|
GEN93 : MT6761 MT6765
|
|
GEN95 : MT6779
|
|
|
|
#define MAX_PACKET_SIZE 2555872 // 2.4375*1024*1024 -32
|
|
#define COMP_DATA_OFFSET (0x500000+32)
|
|
#define RW_INDEX_OFFSET 0x500000
|
|
#define UDC_UNCMP_CACHE_BUF_SZ 0xC000 // 48k
|
|
|
|
In kernel4.14:
|
|
#if (MD_GENERATION >= 6295)
|
|
#define MAX_PACKET_SIZE 1277936 // (2.4375*1024*1024 -32)/2
|
|
#define COMP_DATA_OFFSET (0xC00000 + 32)
|
|
#define RW_INDEX_OFFSET 0xC00000
|
|
#define UDC_UNCMP_CACHE_BUF_SZ 0x64000 // 400k
|
|
#define rslt_entry 2048
|
|
#elif (MD_GENERATION == 6293)
|
|
#define MAX_PACKET_SIZE 1048576 // 2*1024*1024/2
|
|
#define COMP_DATA_OFFSET 0x570000
|
|
#define RW_INDEX_OFFSET 0x568000
|
|
#define UDC_UNCMP_CACHE_BUF_SZ 0xC000 // 48k
|
|
#define rslt_entry 1024
|
|
#endif
|
|
*/
|
|
|
|
struct ap_md_rw_index *rw_index;
|
|
unsigned char *comp_data_buf_base, *uncomp_data_buf_base;
|
|
unsigned char *uncomp_cache_data_base;
|
|
struct udc_comp_req_t *req_des_0_base, *req_des_1_base;
|
|
struct udc_comp_rslt_t *rslt_des_0_base, *rslt_des_1_base;
|
|
static unsigned int total_comp_size;
|
|
|
|
void set_udc_status(struct sk_buff *skb)
|
|
{
|
|
struct ccci_udc_cmd_rsp_t *udc_cmd_rsp =
|
|
(struct ccci_udc_cmd_rsp_t *)skb->data;
|
|
|
|
if (udc_cmd_rsp->udc_inst_id == 0 &&
|
|
udc_cmd_rsp->udc_cmd == UDC_CMD_KICK)
|
|
atomic_set(&udc_status, UDC_HighKick);
|
|
if (udc_cmd_rsp->udc_cmd == UDC_CMD_DEACTV)
|
|
atomic_set(&udc_status, UDC_DEACTV);
|
|
if (udc_cmd_rsp->udc_cmd == UDC_CMD_DISC)
|
|
atomic_set(&udc_status, UDC_DISCARD);
|
|
}
|
|
|
|
int udc_resp_msg_to_md(struct port_t *port,
|
|
struct sk_buff *skb, int handle_udc_ret)
|
|
{
|
|
int md_id = port->md_id;
|
|
int data_len, ret;
|
|
struct ccci_udc_cmd_rsp_t *udc_cmd_rsp =
|
|
(struct ccci_udc_cmd_rsp_t *)skb->data;
|
|
|
|
/* write back to modem */
|
|
/* update message */
|
|
udc_cmd_rsp->udc_cmd |= UDC_API_RESP_ID;
|
|
data_len = sizeof(*udc_cmd_rsp);
|
|
if (handle_udc_ret < 0) {
|
|
udc_cmd_rsp->rslt = UDC_CMD_RSLT_ERROR;
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"rsp ins%d cmd:0x%x,rslt:%d\n",
|
|
udc_cmd_rsp->udc_inst_id,
|
|
udc_cmd_rsp->udc_cmd, udc_cmd_rsp->rslt);
|
|
} else
|
|
udc_cmd_rsp->rslt = UDC_CMD_RSLT_OK;
|
|
|
|
/* resize skb */
|
|
CCCI_DEBUG_LOG(md_id, UDC,
|
|
"data_len:%d,skb->len:%d\n", data_len, skb->len);
|
|
if (data_len > skb->len)
|
|
skb_put(skb, data_len - skb->len);
|
|
else if (data_len < skb->len)
|
|
skb_trim(skb, data_len);
|
|
/* update CCCI header */
|
|
udc_cmd_rsp->header.channel = CCCI_UDC_TX;
|
|
udc_cmd_rsp->header.data[1] = data_len;
|
|
CCCI_DEBUG_LOG(md_id, UDC,
|
|
"Write %d/%d, %08X, %08X, %08X, %08X, op_id=0x%x\n",
|
|
skb->len, data_len, udc_cmd_rsp->header.data[0],
|
|
udc_cmd_rsp->header.data[1], udc_cmd_rsp->header.channel,
|
|
udc_cmd_rsp->header.reserved, udc_cmd_rsp->udc_cmd);
|
|
/* switch to Tx request */
|
|
ret = port_send_skb_to_md(port, skb, 1);
|
|
|
|
CCCI_DEBUG_LOG(md_id, UDC,
|
|
"send_skb_to_md:%d,rsp ins%d cmd:0x%x,rslt:%d\n",
|
|
ret, udc_cmd_rsp->udc_inst_id,
|
|
udc_cmd_rsp->udc_cmd, udc_cmd_rsp->rslt);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void udc_cmd_check(struct port_t *port,
|
|
struct sk_buff **skb_tmp, struct sk_buff **skb,
|
|
u32 inst_id, struct udc_state_ctl *ctl)
|
|
{
|
|
int md_id = port->md_id;
|
|
unsigned long flags;
|
|
struct ccci_udc_deactv_param_t *ccci_udc_deactv;
|
|
struct ccci_udc_actv_param_t *ccci_udc_actv;
|
|
int skb_len, skb_tmp_len, skb_tmp1_len;
|
|
struct sk_buff *skb_tmp1 = NULL;
|
|
u32 ins_id_tmp;
|
|
|
|
ctl->last_state = ctl->curr_state;
|
|
ctl->curr_state = atomic_read(&udc_status);
|
|
|
|
switch (ctl->curr_state) {
|
|
case UDC_DEACTV_DONE:
|
|
case UDC_DISC_DONE:
|
|
atomic_set(&udc_status, UDC_IDLE);
|
|
ctl->curr_state = UDC_IDLE;
|
|
break;
|
|
case UDC_IDLE:
|
|
case UDC_HandleHighKick:
|
|
case UDC_KICKDEACTV:
|
|
break;
|
|
case UDC_HighKick:
|
|
{
|
|
if (inst_id == 0) {
|
|
atomic_set(&udc_status, UDC_IDLE);
|
|
ctl->curr_state = UDC_IDLE;
|
|
break;
|
|
}
|
|
CCCI_DEBUG_LOG(md_id, UDC,
|
|
"high prio kick0 come in\n");
|
|
if (!skb_queue_empty(&port->rx_skb_list)) {
|
|
skb_len = (*skb)->len;
|
|
skb_tmp_len = (*skb_tmp)->len;
|
|
/* resize skb */
|
|
CCCI_DEBUG_LOG(md_id, UDC,
|
|
"skb_len:%d,skb_tmp_len:%d\n",
|
|
skb_len, skb_tmp_len);
|
|
if (skb_len > skb_tmp_len)
|
|
skb_put(*skb_tmp, skb_len - skb_tmp_len);
|
|
else if (skb_len < skb_tmp_len)
|
|
skb_trim(*skb_tmp, skb_len);
|
|
|
|
/* backup skb to skb_tmp */
|
|
skb_copy_to_linear_data(*skb_tmp,
|
|
(*skb)->data, skb_len);
|
|
spin_lock_irqsave(&port->rx_skb_list.lock, flags);
|
|
*skb = __skb_dequeue(&port->rx_skb_list);
|
|
spin_unlock_irqrestore(&port->rx_skb_list.lock, flags);
|
|
ctl->last_state = ctl->curr_state;
|
|
atomic_set(&udc_status, UDC_HandleHighKick);
|
|
ctl->curr_state = UDC_HandleHighKick;
|
|
} else
|
|
goto err;
|
|
break;
|
|
}
|
|
case UDC_DEACTV:
|
|
{
|
|
if (!skb_queue_empty(&port->rx_skb_list)) {
|
|
if (ctl->last_state == UDC_HandleHighKick) {
|
|
skb_tmp1 = ccci_alloc_skb(
|
|
sizeof(*ccci_udc_actv), 1, 1);
|
|
if (unlikely(!skb_tmp1)) {
|
|
CCCI_ERROR_LOG(md_id, UDC,
|
|
"alloc skb_tmp1 fail\n");
|
|
return;
|
|
}
|
|
/* backup skb_tmp to skb_tmp1 */
|
|
skb_copy_to_linear_data(skb_tmp1,
|
|
(*skb_tmp)->data, (*skb_tmp)->len);
|
|
skb_put(skb_tmp1, (*skb_tmp)->len);
|
|
}
|
|
skb_len = (*skb)->len;
|
|
skb_tmp_len = (*skb_tmp)->len;
|
|
/* resize skb */
|
|
CCCI_DEBUG_LOG(md_id, UDC,
|
|
"skb_len:%d,skb_tmp_len:%d\n",
|
|
skb_len, skb_tmp_len);
|
|
if (skb_len > skb_tmp_len)
|
|
skb_put(*skb_tmp, skb_len - skb_tmp_len);
|
|
else if (skb_len < skb_tmp_len)
|
|
skb_trim(*skb_tmp, skb_len);
|
|
|
|
/* backup skb to skb_tmp */
|
|
skb_copy_to_linear_data(*skb_tmp,
|
|
(*skb)->data, skb_len);
|
|
spin_lock_irqsave(&port->rx_skb_list.lock, flags);
|
|
/* dequeue */
|
|
*skb = __skb_dequeue(&port->rx_skb_list);
|
|
if ((*skb) == NULL) {
|
|
CCCI_ERROR_LOG(md_id, UDC,
|
|
"%s:__skb_dequeue fail\n", __func__);
|
|
spin_unlock_irqrestore(&port->rx_skb_list.lock, flags);
|
|
return;
|
|
}
|
|
spin_unlock_irqrestore(&port->rx_skb_list.lock, flags);
|
|
ccci_udc_deactv
|
|
= (struct ccci_udc_deactv_param_t *)
|
|
(*skb)->data;
|
|
ins_id_tmp = ccci_udc_deactv->udc_inst_id;
|
|
if (ctl->last_state == UDC_HandleHighKick) {
|
|
if (ins_id_tmp == 0) {
|
|
skb_tmp_len = (*skb_tmp)->len;
|
|
skb_tmp1_len = skb_tmp1->len;
|
|
if (skb_tmp_len > skb_tmp1_len)
|
|
skb_put(*skb_tmp,
|
|
skb_tmp_len - skb_tmp1_len);
|
|
else if (skb_tmp_len < skb_tmp1_len)
|
|
skb_trim(*skb_tmp, skb_tmp_len);
|
|
|
|
skb_copy_to_linear_data(*skb_tmp,
|
|
skb_tmp1->data, skb_tmp1_len);
|
|
}
|
|
ccci_free_skb(skb_tmp1);
|
|
ctl->last_state = ctl->curr_state;
|
|
atomic_set(&udc_status, UDC_KICKDEACTV);
|
|
ctl->curr_state = UDC_KICKDEACTV;
|
|
} else {
|
|
if (ins_id_tmp == inst_id) {
|
|
ctl->last_state = ctl->curr_state;
|
|
atomic_set(&udc_status,
|
|
UDC_DEACTV_DONE);
|
|
ctl->curr_state = UDC_DEACTV_DONE;
|
|
} else {
|
|
ctl->last_state = ctl->curr_state;
|
|
atomic_set(&udc_status, UDC_KICKDEACTV);
|
|
ctl->curr_state = UDC_KICKDEACTV;
|
|
}
|
|
}
|
|
} else
|
|
goto err;
|
|
break;
|
|
}
|
|
case UDC_DISCARD:
|
|
{
|
|
if (!skb_queue_empty(&port->rx_skb_list)) {
|
|
skb_len = (*skb)->len;
|
|
skb_tmp_len = (*skb_tmp)->len;
|
|
/* resize skb */
|
|
CCCI_DEBUG_LOG(md_id, UDC,
|
|
"skb_len:%d,skb_tmp_len:%d\n",
|
|
skb_len, skb_tmp_len);
|
|
if (skb_len > skb_tmp_len)
|
|
skb_put(*skb_tmp, skb_len - skb_tmp_len);
|
|
else if (skb_len < skb_tmp_len)
|
|
skb_trim(*skb_tmp, skb_len);
|
|
|
|
/* backup skb to skb_tmp */
|
|
skb_copy_to_linear_data(*skb_tmp,
|
|
(*skb)->data, skb_len);
|
|
spin_lock_irqsave(&port->rx_skb_list.lock, flags);
|
|
/* dequeue */
|
|
*skb = __skb_dequeue(&port->rx_skb_list);
|
|
spin_unlock_irqrestore(&port->rx_skb_list.lock, flags);
|
|
|
|
ctl->last_state = ctl->curr_state;
|
|
atomic_set(&udc_status, UDC_DISC_DONE);
|
|
ctl->curr_state = UDC_DISC_DONE;
|
|
} else
|
|
goto err;
|
|
break;
|
|
}
|
|
default:
|
|
CCCI_ERROR_LOG(md_id, UDC,
|
|
"[Error]Unknown UDC STATUS (0x%08X)\n",
|
|
atomic_read(&udc_status));
|
|
break;
|
|
}
|
|
if (ctl->last_state != ctl->curr_state)
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"udc_status:from %d to %d by %s\n",
|
|
ctl->last_state, ctl->curr_state, __func__);
|
|
return;
|
|
err:
|
|
CCCI_ERROR_LOG(md_id, UDC,
|
|
"udc_status%d:skb list is empty\n", ctl->curr_state);
|
|
atomic_set(&udc_status, UDC_IDLE);
|
|
ctl->curr_state = UDC_IDLE;
|
|
}
|
|
|
|
int udc_actv_handler(struct z_stream_s *zcpr, enum udc_dict_opt_e dic_option,
|
|
unsigned int buffer_size, u32 inst_id)
|
|
{
|
|
int ret = 0;
|
|
static struct udc_private_data my_param0, my_param1;
|
|
|
|
if (inst_id == 0)
|
|
ret = udc_init(zcpr, &my_param0);
|
|
else if (inst_id == 1)
|
|
ret = udc_init(zcpr, &my_param1);
|
|
|
|
ret |= deflateInit2_cb(zcpr, Z_DEFAULT_COMPRESSION,
|
|
Z_DEFLATED, buffer_size, 8, Z_FIXED);
|
|
|
|
if (ret < 0) {
|
|
CCCI_ERROR_LOG(-1, UDC,
|
|
"ins%d deflateInit2 fail ret:%d\n", inst_id, ret);
|
|
return ret;
|
|
}
|
|
if (dic_option == UDC_DICT_STD_FOR_SIP) {
|
|
ret |= deflateSetDictionary_cb(zcpr,
|
|
get_dictionary_content(dic_option),
|
|
UDC_DICTIONARY_LENGTH);
|
|
if (ret < 0) {
|
|
CCCI_ERROR_LOG(-1, UDC,
|
|
"ins%d deflateSetDictionary fail ret:%d\n",
|
|
inst_id, ret);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* phase out:when ap recevice deflateEnd cmd, call deflateEnd_cb directly */
|
|
int udc_deactv_handler(struct z_stream_s *zcpr, u32 inst_id)
|
|
{
|
|
int deflate_end_flag = 0;
|
|
struct udc_comp_req_t *req_des;
|
|
struct udc_comp_rslt_t *rslt_des;
|
|
unsigned int ap_read = 0, ap_write = 0, md_write = 0, md_read = 0;
|
|
struct udc_comp_req_t *req_des_base = NULL;
|
|
struct udc_comp_rslt_t *rslt_des_base = NULL;
|
|
|
|
if (inst_id == 0) {
|
|
req_des_base = req_des_0_base;
|
|
rslt_des_base = rslt_des_0_base;
|
|
ap_read = rw_index->md_des_ins0.read;
|
|
md_write = rw_index->md_des_ins0.write;
|
|
md_read = rw_index->ap_resp_ins0.read;
|
|
} else if (inst_id == 1) {
|
|
req_des_base = req_des_1_base;
|
|
rslt_des_base = rslt_des_1_base;
|
|
ap_read = rw_index->md_des_ins1.read;
|
|
md_write = rw_index->md_des_ins1.write;
|
|
md_read = rw_index->ap_resp_ins1.read;
|
|
}
|
|
|
|
while (ap_read != md_write) {
|
|
if (inst_id == 0) {
|
|
ap_read = rw_index->md_des_ins0.read;
|
|
ap_write = rw_index->ap_resp_ins0.write;
|
|
md_write = rw_index->md_des_ins0.write;
|
|
md_read = rw_index->ap_resp_ins0.read;
|
|
} else if (inst_id == 1) {
|
|
ap_read = rw_index->md_des_ins1.read;
|
|
ap_write = rw_index->ap_resp_ins1.write;
|
|
md_write = rw_index->md_des_ins1.write;
|
|
md_read = rw_index->ap_resp_ins1.read;
|
|
}
|
|
|
|
/* req_des table is only 4kb */
|
|
req_des = req_des_base + ap_read;
|
|
/* md_write must be <=511 */
|
|
ap_read = (ap_read + 1) % 512;
|
|
/* dump req_des */
|
|
CCCI_NORMAL_LOG(-1, UDC,
|
|
"deactv req%d:sdu_idx(%d),sit_type(%d),rst(%d),ap_r(%d),md_w(%d),req_des(%p)\n",
|
|
inst_id, req_des->sdu_idx, req_des->sit_type,
|
|
req_des->rst, ap_read, md_write, req_des);
|
|
if (req_des->con == 0) {
|
|
if ((ap_write+1) == md_read) {
|
|
CCCI_ERROR_LOG(-1, UDC,
|
|
"%s:cmp_rslt table is full\n",
|
|
__func__);
|
|
CCCI_ERROR_LOG(-1, UDC,
|
|
"%s:ins%d md r:%d,md w:%d,ap r:%d,ap w:%d\n",
|
|
__func__, inst_id, ap_read,
|
|
md_write, md_read, ap_write);
|
|
break;
|
|
}
|
|
rslt_des = rslt_des_base + ap_write;
|
|
rslt_des->sdu_idx = req_des->sdu_idx;
|
|
rslt_des->sit_type = req_des->sit_type;
|
|
rslt_des->udc = 0;
|
|
|
|
ap_write = (ap_write + 1) % 512;
|
|
/* insure sequential execution */
|
|
mb();
|
|
if (inst_id == 0) {
|
|
rw_index->md_des_ins0.read = ap_read;
|
|
rw_index->ap_resp_ins0.write = ap_write;
|
|
} else if (inst_id == 1) {
|
|
rw_index->md_des_ins1.read = ap_read;
|
|
rw_index->ap_resp_ins1.write = ap_write;
|
|
}
|
|
CCCI_NORMAL_LOG(-1, UDC,
|
|
"deactv rslt%d:sdu_idx(%d),sit_type(%d),udc(%d),rst(%d)\n",
|
|
inst_id, rslt_des->sdu_idx, rslt_des->sit_type,
|
|
rslt_des->udc, rslt_des->rst);
|
|
} else {
|
|
if (inst_id == 0)
|
|
rw_index->md_des_ins0.read = ap_read;
|
|
else if (inst_id == 1)
|
|
rw_index->md_des_ins1.read = ap_read;
|
|
}
|
|
}
|
|
deflate_end_flag = deflateEnd_cb(zcpr);
|
|
udc_deinit(zcpr);
|
|
|
|
CCCI_NORMAL_LOG(-1, UDC, "deflateEnd_ins%d,ret:%d\n",
|
|
inst_id, deflate_end_flag);
|
|
if (deflate_end_flag < 0) {
|
|
/* the continuous input is unprocessed,
|
|
*it maybe return -3
|
|
*/
|
|
if (deflate_end_flag == -3)
|
|
return 0;
|
|
else
|
|
return deflate_end_flag;
|
|
}
|
|
return deflate_end_flag;
|
|
}
|
|
|
|
static void ccci_udc_req_data_dump(u32 inst_id,
|
|
unsigned char *uncomp_data, unsigned int uncomp_len)
|
|
{
|
|
#ifdef UDC_DATA_DUMP
|
|
int j = 0;
|
|
|
|
CCCI_HISTORY_TAG_LOG(-1, UDC,
|
|
"req%d:uncomp_data:%p\n", inst_id, uncomp_data);
|
|
for (j = 0; j < 16; j++) {
|
|
if (j % 16 == 0)
|
|
CCCI_HISTORY_LOG(-1, UDC, "%04X:", j);
|
|
CCCI_MEM_LOG(-1, UDC, " %02X", uncomp_data[j]);
|
|
if (j == 15)
|
|
CCCI_HISTORY_LOG(-1, UDC, "\n");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void ccci_udc_rslt_data_dump(u32 inst_id,
|
|
unsigned char *comp_data, unsigned int comp_len)
|
|
{
|
|
#ifdef UDC_DATA_DUMP
|
|
unsigned int ap_read, ap_write, md_read, md_write;
|
|
unsigned int j = 0;
|
|
|
|
if (inst_id == 0) {
|
|
ap_read = rw_index->md_des_ins0.read;
|
|
ap_write = rw_index->ap_resp_ins0.write;
|
|
md_read = rw_index->ap_resp_ins0.read;
|
|
md_write = rw_index->md_des_ins0.write;
|
|
} else if (inst_id == 1) {
|
|
ap_read = rw_index->md_des_ins1.read;
|
|
ap_write = rw_index->ap_resp_ins1.write;
|
|
md_read = rw_index->ap_resp_ins1.read;
|
|
md_write = rw_index->md_des_ins1.write;
|
|
}
|
|
|
|
CCCI_HISTORY_TAG_LOG(-1, UDC,
|
|
"rst%d:comp_len:%d,comp_data:%p\n",
|
|
inst_id, comp_len, comp_data);
|
|
CCCI_HISTORY_TAG_LOG(-1, UDC,
|
|
"ins%d:md r:%d,md w:%d,ap r:%d,ap w:%d\n",
|
|
inst_id, ap_read, md_write, md_read, ap_write);
|
|
|
|
for (j = 0; j < comp_len; j++) {
|
|
if (j % 16 == 0) {
|
|
if (j > 0)
|
|
CCCI_HISTORY_LOG(-1, UDC, "\n%04X:", j);
|
|
else
|
|
CCCI_HISTORY_LOG(-1, UDC, "%04X:", j);
|
|
}
|
|
CCCI_HISTORY_LOG(-1, UDC, " %02X", *(comp_data + j));
|
|
if (j == (comp_len - 1))
|
|
CCCI_HISTORY_LOG(-1, UDC, "\n");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* <0:full 0:not full */
|
|
static int check_cmp_buf(u32 inst_id,
|
|
int max_output_size)
|
|
{
|
|
unsigned int ap_read = 0, ap_write = 0, md_read = 0, md_read_len = 0;
|
|
struct udc_comp_req_t *req_des, *req_des_base = NULL;
|
|
struct udc_comp_rslt_t *rslt_des, *rslt_des_base = NULL;
|
|
|
|
if (inst_id == 0) {
|
|
req_des_base = req_des_0_base;
|
|
rslt_des_base = rslt_des_0_base;
|
|
ap_read = rw_index->md_des_ins0.read;
|
|
ap_write = rw_index->ap_resp_ins0.write;
|
|
md_read = rw_index->ap_resp_ins0.read;
|
|
} else if (inst_id == 1) {
|
|
req_des_base = req_des_1_base;
|
|
rslt_des_base = rslt_des_1_base;
|
|
ap_read = rw_index->md_des_ins1.read;
|
|
ap_write = rw_index->ap_resp_ins1.write;
|
|
md_read = rw_index->ap_resp_ins1.read;
|
|
} else {
|
|
CCCI_ERROR_LOG(-1, UDC,
|
|
"inst_id is error,rslt_des_base maybe null\n");
|
|
return -1;
|
|
}
|
|
|
|
md_read_len = (rslt_des_base + md_read)->cmp_addr
|
|
+ (rslt_des_base + md_read)->cmp_len;
|
|
if (total_comp_size < md_read_len) {
|
|
if ((total_comp_size + max_output_size)
|
|
>= md_read_len) {
|
|
CCCI_NORMAL_LOG(-1, UDC,
|
|
"%s:ins%d cmp_buf full,ap_w:%d,ap_r:%d\n",
|
|
__func__, inst_id, ap_write, md_read);
|
|
CCCI_NORMAL_LOG(-1, UDC,
|
|
"(total_comp_size:%d+max_output_size:%d)>md_read_len:%d\n",
|
|
total_comp_size, max_output_size, md_read_len);
|
|
req_des = req_des_base + ap_read;
|
|
rslt_des = rslt_des_base + ap_write;
|
|
|
|
rslt_des->sdu_idx = req_des->sdu_idx;
|
|
rslt_des->sit_type = req_des->sit_type;
|
|
rslt_des->udc = 0;
|
|
|
|
/* insure sequential execution */
|
|
mb();
|
|
/* update ap write index */
|
|
ap_write = (ap_write + 1) % 512;
|
|
if (inst_id == 0)
|
|
rw_index->ap_resp_ins0.write = ap_write;
|
|
else if (inst_id == 1)
|
|
rw_index->ap_resp_ins1.write = ap_write;
|
|
return -CMP_BUF_FULL;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int cal_udc_param(struct z_stream_s *zcpr, u32 inst_id,
|
|
int *max_output_size, int *udc_chksum)
|
|
{
|
|
struct udc_comp_req_t *req_des_tmp = NULL, *req_des_base = NULL;
|
|
unsigned int ap_read = 0, md_write = 0;
|
|
unsigned int uncomp_len_total = 0;
|
|
int j = 0;
|
|
|
|
if (inst_id == 0) {
|
|
req_des_base = req_des_0_base;
|
|
ap_read = rw_index->md_des_ins0.read;
|
|
md_write = rw_index->md_des_ins0.write;
|
|
} else if (inst_id == 1) {
|
|
req_des_base = req_des_1_base;
|
|
ap_read = rw_index->md_des_ins1.read;
|
|
md_write = rw_index->md_des_ins1.write;
|
|
} else {
|
|
CCCI_ERROR_LOG(-1, UDC,
|
|
"inst_id is error\n");
|
|
return -1;
|
|
}
|
|
|
|
if (*max_output_size == 0) {
|
|
req_des_tmp = req_des_base + ap_read;
|
|
if (!req_des_tmp) {
|
|
CCCI_ERROR_LOG(-1, UDC,
|
|
"%s:req_des_base&ap_read is null\n",
|
|
__func__);
|
|
return -1;
|
|
}
|
|
if (req_des_tmp->con == 0)
|
|
*max_output_size = deflateBound_cb(zcpr,
|
|
req_des_tmp->seg_len);
|
|
else if (req_des_tmp->con == 1) {
|
|
for (j = 0; ap_read != md_write; j++) {
|
|
req_des_tmp = req_des_base + (ap_read+j)%512;
|
|
uncomp_len_total += req_des_tmp->seg_len;
|
|
if (req_des_tmp->con == 0)
|
|
break;
|
|
}
|
|
*max_output_size =
|
|
deflateBound_cb(zcpr, uncomp_len_total);
|
|
CCCI_DEBUG_LOG(-1, UDC,
|
|
"req_des%d:deflateBound uncomp_len_total:%d,packet_count:%d\n",
|
|
inst_id, uncomp_len_total, j+1);
|
|
/* packet_count > 2*/
|
|
if (j > 1)
|
|
CCCI_ERROR_LOG(-1, UDC,
|
|
"req_des%d:packet_count:%d,md_r:%d,md_w:%d\n",
|
|
inst_id, j+1, ap_read, md_write);
|
|
}
|
|
/* calc chksum before call deflate */
|
|
*udc_chksum = udc_chksum_cb(zcpr);
|
|
CCCI_DEBUG_LOG(-1, UDC,
|
|
"ins%d:max_output_size:%d udc_chksum:%d\n",
|
|
inst_id, *max_output_size, *udc_chksum);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int udc_deflate(struct z_stream_s *zcpr, u32 inst_id, u32 con,
|
|
unsigned char *uncomp_data, unsigned int uncomp_len,
|
|
unsigned char *comp_data, unsigned int remain_len)
|
|
{
|
|
unsigned long bytes_processed, prev_bytes_processed;
|
|
int deflate_st;
|
|
int comp_len = 0;
|
|
|
|
(*zcpr).next_in = uncomp_data;
|
|
(*zcpr).next_out = comp_data;
|
|
(*zcpr).avail_in = uncomp_len;
|
|
(*zcpr).avail_out = remain_len;
|
|
|
|
prev_bytes_processed = (*zcpr).total_in;
|
|
deflate_st = deflate_cb(zcpr,
|
|
con ? Z_NO_FLUSH : Z_SYNC_FLUSH);
|
|
if (deflate_st < 0) {
|
|
CCCI_ERROR_LOG(-1, UDC,
|
|
"ins%d:deflate_st:%d\n", inst_id, deflate_st);
|
|
if (deflate_st == Z_BUF_ERROR)
|
|
CCCI_ERROR_LOG(-1, UDC,
|
|
"ins%d zcpr.avail_in:%d,zcpr.avail_out:%d\n",
|
|
inst_id, (*zcpr).avail_in, (*zcpr).avail_out);
|
|
return deflate_st;
|
|
}
|
|
if ((*zcpr).avail_in > 0)
|
|
CCCI_ERROR_LOG(-1, UDC,
|
|
"%d input bytes not processed!\n",
|
|
(*zcpr).avail_in);
|
|
bytes_processed = (*zcpr).total_in - prev_bytes_processed;
|
|
if (bytes_processed != uncomp_len)
|
|
CCCI_ERROR_LOG(-1, UDC,
|
|
"input %d bytes, only process %lu bytes\n",
|
|
uncomp_len, bytes_processed);
|
|
comp_len = udc_GetCmpLen_cb(zcpr, comp_data, (*zcpr).next_out);
|
|
total_comp_size += (*zcpr).next_out - comp_data;
|
|
CCCI_DEBUG_LOG(-1, UDC,
|
|
"ins%d total_comp_size:%d\n",
|
|
inst_id, total_comp_size);
|
|
|
|
return comp_len;
|
|
}
|
|
|
|
int udc_kick_handler(struct port_t *port, struct z_stream_s *zcpr,
|
|
u32 inst_id, unsigned char **comp_data)
|
|
{
|
|
int md_id = port->md_id;
|
|
int ret = 0;
|
|
static int max_output_size;
|
|
int max_packet_size = MAX_PACKET_SIZE;
|
|
static unsigned int udc_chksum;
|
|
static unsigned int is_rst;
|
|
unsigned int ap_read = 0, ap_write = 0, md_read = 0, md_write = 0;
|
|
struct udc_comp_req_t *req_des = NULL, *req_des_base = NULL;
|
|
struct udc_comp_rslt_t *rslt_des = NULL, *rslt_des_base = NULL;
|
|
unsigned int uncomp_len, comp_len = 0;
|
|
unsigned int remain_len;
|
|
unsigned char *uncomp_data = NULL;
|
|
/* reserved 8k for reduce memcpy op */
|
|
unsigned int rsvd_len = MAX_PACKET_SIZE - 8*1024;
|
|
|
|
if (inst_id == 0) {
|
|
req_des_base = req_des_0_base;
|
|
rslt_des_base = rslt_des_0_base;
|
|
ap_read = rw_index->md_des_ins0.read;
|
|
ap_write = rw_index->ap_resp_ins0.write;
|
|
md_read = rw_index->ap_resp_ins0.read;
|
|
md_write = rw_index->md_des_ins0.write;
|
|
} else if (inst_id == 1) {
|
|
req_des_base = req_des_1_base;
|
|
rslt_des_base = rslt_des_1_base;
|
|
ap_read = rw_index->md_des_ins1.read;
|
|
ap_write = rw_index->ap_resp_ins1.write;
|
|
md_read = rw_index->ap_resp_ins1.read;
|
|
md_write = rw_index->md_des_ins1.write;
|
|
} else {
|
|
CCCI_ERROR_LOG(md_id, UDC,
|
|
"inst_id is error\n");
|
|
return -1;
|
|
}
|
|
|
|
/* check if cmp_rslt table is full */
|
|
if ((ap_write+1) == md_read) {
|
|
CCCI_ERROR_LOG(md_id, UDC,
|
|
"cmp_rslt table is full\n");
|
|
CCCI_ERROR_LOG(md_id, UDC,
|
|
"ins%d:md r:%d,md w:%d,ap r:%d,ap w:%d\n",
|
|
inst_id, ap_read, md_write, md_read, ap_write);
|
|
return -CMP_RSLT_FULL;
|
|
}
|
|
/* req_des table is only 4kb */
|
|
req_des = req_des_base + ap_read;
|
|
if (req_des == NULL) {
|
|
CCCI_ERROR_LOG(md_id, UDC, "invalid req_des");
|
|
return -CMP_INST_ID_ERR;
|
|
}
|
|
/* dump req_des */
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"req%d:sdu_idx(%d),buf_type(%d),seg_len(%d),phy_offset(%#x)\n",
|
|
inst_id, req_des->sdu_idx, req_des->buf_type,
|
|
req_des->seg_len, req_des->seg_phy_addr);
|
|
uncomp_len = req_des->seg_len;
|
|
if (req_des->buf_type == 0)
|
|
uncomp_data = (unsigned char *)
|
|
((unsigned long)uncomp_data_buf_base +
|
|
req_des->seg_phy_addr);
|
|
else if (req_des->buf_type == 1)
|
|
uncomp_data = (unsigned char *)
|
|
((unsigned long)uncomp_cache_data_base +
|
|
req_des->seg_phy_addr);
|
|
|
|
ccci_udc_req_data_dump(inst_id, uncomp_data, uncomp_len);
|
|
|
|
if (req_des->rst == 1) {
|
|
is_rst = 1;
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"kick req%d:rst(%d),sdu_idx(%d),md r(%d)\n",
|
|
inst_id, req_des->rst, req_des->sdu_idx, ap_read);
|
|
deflateReset_cb(zcpr);
|
|
}
|
|
|
|
/* check max_output_size&udc_chksum */
|
|
cal_udc_param(zcpr, inst_id, &max_output_size, &udc_chksum);
|
|
|
|
/* md_write must be <=511 */
|
|
ap_read = (ap_read + 1) % 512;
|
|
|
|
if (inst_id == 0)
|
|
rw_index->md_des_ins0.read = ap_read;
|
|
else if (inst_id == 1)
|
|
rw_index->md_des_ins1.read = ap_read;
|
|
|
|
/* deinit comp_data to reduce memcpy */
|
|
if (total_comp_size >= rsvd_len ||
|
|
(total_comp_size + max_output_size) > max_packet_size) {
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"ins%d total_cmp_size:%d,deflateBound:%d,rsvd_len:%d\n",
|
|
inst_id, total_comp_size, max_output_size, rsvd_len);
|
|
*comp_data = comp_data_buf_base;
|
|
total_comp_size = 0;
|
|
}
|
|
/* cal md_read_len for check if cmp_buf is full or not */
|
|
ret = check_cmp_buf(inst_id, max_output_size);
|
|
if (ret == -CMP_BUF_FULL)
|
|
return ret;
|
|
remain_len = Min(max_output_size,
|
|
max_packet_size - total_comp_size);
|
|
|
|
ret = udc_deflate(zcpr, inst_id, req_des->con,
|
|
uncomp_data, uncomp_len, *comp_data, remain_len);
|
|
if (ret < 0)
|
|
return ret;
|
|
comp_len += ret;
|
|
|
|
if (req_des->con == 0) {
|
|
rslt_des = rslt_des_base + ap_write;
|
|
rslt_des->sdu_idx = req_des->sdu_idx;
|
|
rslt_des->sit_type = req_des->sit_type;
|
|
rslt_des->udc = 1;
|
|
rslt_des->rst = is_rst;
|
|
rslt_des->cksm = udc_chksum;
|
|
rslt_des->cmp_addr = *comp_data - comp_data_buf_base;
|
|
rslt_des->cmp_len = comp_len;
|
|
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"rslt%d:sdu_idx(%d),rst(%d),comp_len(%d),offset(%d),chsm(%d),ap_write(%d)\n",
|
|
inst_id, rslt_des->sdu_idx, rslt_des->rst,
|
|
comp_len, rslt_des->cmp_addr, rslt_des->cksm, ap_write);
|
|
|
|
if (comp_len == 0) {
|
|
/* if no check comp_len,ke will happen */
|
|
CCCI_ERROR_LOG(md_id, UDC,
|
|
"kick%d comp_len = 0\n", inst_id);
|
|
return -CMP_ZERO_LEN;
|
|
}
|
|
|
|
comp_len = 0;
|
|
is_rst = 0;
|
|
max_output_size = 0;
|
|
/* update ap write index */
|
|
ap_write = (ap_write + 1) % 512;
|
|
/* insure sequential execution */
|
|
mb();
|
|
if (inst_id == 0)
|
|
rw_index->ap_resp_ins0.write = ap_write;
|
|
else if (inst_id == 1)
|
|
rw_index->ap_resp_ins1.write = ap_write;
|
|
ccci_udc_rslt_data_dump(inst_id,
|
|
*comp_data, rslt_des->cmp_len);
|
|
}
|
|
*comp_data = (*zcpr).next_out;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int udc_restore_skb(struct port_t *port,
|
|
struct udc_state_ctl *ctl,
|
|
struct sk_buff **skb_tmp, struct sk_buff **skb)
|
|
{
|
|
struct ccci_udc_actv_param_t *ccci_udc_actv;
|
|
int ret = 0;
|
|
int md_id = port->md_id;
|
|
|
|
ctl->last_state = ctl->curr_state;
|
|
/* ctl->curr_state = atomic_read(&udc_status); */
|
|
|
|
switch (ctl->curr_state) {
|
|
case UDC_HandleHighKick:
|
|
case UDC_DISC_DONE:
|
|
case UDC_KICKDEACTV:
|
|
case UDC_DEACTV_DONE:
|
|
{
|
|
*skb = ccci_alloc_skb(sizeof(*ccci_udc_actv), 1, 1);
|
|
if (unlikely(!(*skb))) {
|
|
CCCI_ERROR_LOG(md_id, UDC,
|
|
"%s:alloc skb fail\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
skb_copy_to_linear_data(*skb,
|
|
(*skb_tmp)->data, (*skb_tmp)->len);
|
|
skb_put(*skb, (*skb_tmp)->len);
|
|
|
|
ctl->last_state = ctl->curr_state;
|
|
atomic_set(&udc_status, UDC_IDLE);
|
|
ctl->curr_state = UDC_IDLE;
|
|
ret = 1;
|
|
break;
|
|
}
|
|
case UDC_IDLE:
|
|
case UDC_HighKick:
|
|
case UDC_DISCARD:
|
|
case UDC_DEACTV:
|
|
break;
|
|
default:
|
|
CCCI_ERROR_LOG(md_id, UDC,
|
|
"[Error]%s:Unknown UDC STATUS (0x%08X)\n",
|
|
__func__, atomic_read(&udc_status));
|
|
break;
|
|
}
|
|
if (ctl->last_state != ctl->curr_state)
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"udc_status:from %d to %d by %s\n",
|
|
ctl->last_state, ctl->curr_state, __func__);
|
|
return ret;
|
|
}
|
|
|
|
void udc_cmd_handler(struct port_t *port, struct sk_buff *skb)
|
|
{
|
|
int md_id = port->md_id;
|
|
struct ccci_smem_region *region;
|
|
int ret = 0;
|
|
unsigned int udc_cmd = 0;
|
|
struct udc_state_ctl *ctl;
|
|
static unsigned char *comp_data;
|
|
struct ccci_udc_deactv_param_t *ccci_udc_deactv;
|
|
struct ccci_udc_disc_param_t *ccci_udc_disc;
|
|
struct sk_buff *skb_tmp;
|
|
struct ccci_udc_actv_param_t *ccci_udc_actv;
|
|
static struct z_stream_s zcpr0, zcpr1;
|
|
int deflate_end_flag = 0;
|
|
unsigned int md_write = 0, ap_read = 0;
|
|
|
|
skb_tmp = ccci_alloc_skb(sizeof(*ccci_udc_actv), 1, 1);
|
|
if (!skb_tmp) {
|
|
CCCI_ERROR_LOG(md_id, UDC,
|
|
"%s:alloc skb_tmp fail\n", __func__);
|
|
return;
|
|
}
|
|
|
|
ctl = kzalloc(sizeof(struct udc_state_ctl), GFP_KERNEL);
|
|
if (ctl == NULL) {
|
|
CCCI_ERROR_LOG(md_id, UDC,
|
|
"%s:kzalloc ctl fail\n", __func__);
|
|
return;
|
|
}
|
|
|
|
ccci_udc_actv = (struct ccci_udc_actv_param_t *)skb->data;
|
|
udc_cmd = ccci_udc_actv->udc_cmd;
|
|
CCCI_DEBUG_LOG(md_id, UDC,
|
|
"%s++ udc_cmd:%d\n", __func__, udc_cmd);
|
|
|
|
switch (udc_cmd) {
|
|
case UDC_CMD_ACTV:
|
|
{
|
|
unsigned int buffer_size = ccci_udc_actv->buf_sz;
|
|
enum udc_dict_opt_e dic_option = ccci_udc_actv->dict_opt;
|
|
unsigned int inst_id = ccci_udc_actv->udc_inst_id;
|
|
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"udc_actv ins%d:cmd:%d,buf_sz:%d,dict_opt:%d\n",
|
|
inst_id, udc_cmd, buffer_size, dic_option);
|
|
|
|
if (inst_id == 0)
|
|
ret = udc_actv_handler(&zcpr0, dic_option,
|
|
buffer_size, inst_id);
|
|
else if (inst_id == 1)
|
|
ret = udc_actv_handler(&zcpr1, dic_option,
|
|
buffer_size, inst_id);
|
|
if (ret < 0)
|
|
goto end;
|
|
/* get sharememory info */
|
|
region = ccci_md_get_smem_by_user_id(md_id,
|
|
SMEM_USER_RAW_UDC_DATA);
|
|
if (region) {
|
|
uncomp_data_buf_base = (unsigned char *)
|
|
region->base_ap_view_vir;
|
|
comp_data_buf_base = (unsigned char *)
|
|
(region->base_ap_view_vir + COMP_DATA_OFFSET);
|
|
rw_index = (struct ap_md_rw_index *)
|
|
(region->base_ap_view_vir + 0x500000);
|
|
comp_data = comp_data_buf_base;
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"base_md_view_phy:0x%lx,base_ap_view_phy:0x%lx\n",
|
|
(unsigned long)region->base_md_view_phy,
|
|
(unsigned long)region->base_ap_view_phy);
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"uncomp_base:%p,comp_base:%p\n",
|
|
uncomp_data_buf_base, comp_data_buf_base);
|
|
} else
|
|
CCCI_ERROR_LOG(md_id, UDC,
|
|
"can not find region:SMEM_USER_RAW_UDC_DATA\n");
|
|
|
|
region = ccci_md_get_smem_by_user_id(md_id,
|
|
SMEM_USER_RAW_UDC_DESCTAB);
|
|
if (region) {
|
|
uncomp_cache_data_base =
|
|
(unsigned char *)region->base_ap_view_vir;
|
|
/* cmp_req and cmp_rslt offset:48k */
|
|
req_des_0_base = (struct udc_comp_req_t *)
|
|
(region->base_ap_view_vir + UDC_UNCMP_CACHE_BUF_SZ);
|
|
rslt_des_0_base = (struct udc_comp_rslt_t *)
|
|
(region->base_ap_view_vir + UDC_UNCMP_CACHE_BUF_SZ + 0x1000);
|
|
req_des_1_base = (struct udc_comp_req_t *)
|
|
(region->base_ap_view_vir + UDC_UNCMP_CACHE_BUF_SZ + 0x2000);
|
|
rslt_des_1_base = (struct udc_comp_rslt_t *)
|
|
(region->base_ap_view_vir + UDC_UNCMP_CACHE_BUF_SZ + 0x3000);
|
|
CCCI_NORMAL_LOG(md_id, UDC, "uncomp_cache_base:%p\n",
|
|
uncomp_cache_data_base);
|
|
} else
|
|
CCCI_ERROR_LOG(md_id, UDC,
|
|
"can not find region:SMEM_USER_RAW_UDC_DESCTAB\n");
|
|
break;
|
|
}
|
|
case UDC_CMD_DEACTV:
|
|
{
|
|
unsigned int inst_id;
|
|
|
|
deactive_exit:
|
|
ccci_udc_deactv =
|
|
(struct ccci_udc_deactv_param_t *)skb->data;
|
|
|
|
udc_cmd = ccci_udc_deactv->udc_cmd;
|
|
inst_id = ccci_udc_deactv->udc_inst_id;
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"deactv ins%d:udc_cmd:%d\n",
|
|
inst_id, udc_cmd);
|
|
|
|
if (inst_id == 0) {
|
|
/* ret = udc_deactv_handler(&zcpr0, inst_id); */
|
|
deflate_end_flag = deflateEnd_cb(&zcpr0);
|
|
udc_deinit(&zcpr0);
|
|
|
|
} else if (inst_id == 1) {
|
|
/* ret = udc_deactv_handler(&zcpr1, inst_id); */
|
|
deflate_end_flag = deflateEnd_cb(&zcpr1);
|
|
udc_deinit(&zcpr1);
|
|
}
|
|
|
|
/* the continuous input is unprocessed, it maybe return -3 */
|
|
if (deflate_end_flag < 0 && deflate_end_flag != -3) {
|
|
ret = deflate_end_flag;
|
|
CCCI_ERROR_LOG(md_id, UDC, "deflateEnd_ins%d,ret:%d\n",
|
|
inst_id, deflate_end_flag);
|
|
}
|
|
|
|
ctl->curr_state = atomic_read(&udc_status);
|
|
if (ctl->curr_state == UDC_DEACTV ||
|
|
ctl->curr_state == UDC_DEACTV_DONE) {
|
|
atomic_set(&udc_status, UDC_IDLE);
|
|
ctl->last_state = ctl->curr_state;
|
|
ctl->curr_state = UDC_IDLE;
|
|
}
|
|
break;
|
|
}
|
|
case UDC_CMD_DISC:
|
|
{
|
|
unsigned int inst_id;
|
|
unsigned int new_req_r;
|
|
|
|
discard_req:
|
|
ccci_udc_disc =
|
|
(struct ccci_udc_disc_param_t *)skb->data;
|
|
udc_cmd = ccci_udc_disc->udc_cmd;
|
|
new_req_r = ccci_udc_disc->new_req_r;
|
|
inst_id = ccci_udc_disc->udc_inst_id;
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"disc ins%d:udc_cmd:%d,new_req_r:%d\n",
|
|
inst_id, udc_cmd, new_req_r);
|
|
|
|
if (inst_id == 0) {
|
|
ap_read = rw_index->md_des_ins0.read;
|
|
rw_index->md_des_ins0.read =
|
|
ccci_udc_disc->new_req_r;
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"ins%d update ap read:from %d to %d\n",
|
|
inst_id, ap_read, rw_index->md_des_ins0.read);
|
|
} else if (inst_id == 1) {
|
|
ap_read = rw_index->md_des_ins1.read;
|
|
rw_index->md_des_ins1.read =
|
|
ccci_udc_disc->new_req_r;
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"ins%d update ap read:from %d to %d\n",
|
|
inst_id, ap_read, rw_index->md_des_ins1.read);
|
|
}
|
|
ctl->curr_state = atomic_read(&udc_status);
|
|
if (ctl->curr_state == UDC_DISCARD) {
|
|
atomic_set(&udc_status, UDC_IDLE);
|
|
ctl->last_state = ctl->curr_state;
|
|
ctl->curr_state = UDC_IDLE;
|
|
}
|
|
break;
|
|
}
|
|
case UDC_CMD_KICK:
|
|
{
|
|
unsigned int inst_id, exp_timer;
|
|
struct udc_comp_req_t *req_des, *req_des_base;
|
|
struct ccci_udc_kick_param_t *ccci_udc_kick;
|
|
|
|
retry_kick:
|
|
ccci_udc_kick =
|
|
(struct ccci_udc_kick_param_t *)skb->data;
|
|
inst_id = ccci_udc_kick->udc_inst_id;
|
|
udc_cmd = ccci_udc_kick->udc_cmd;
|
|
/* to do exp_timer does not work now */
|
|
exp_timer = ccci_udc_kick->exp_tmr;
|
|
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"kick ins%d:udc_cmd:%d,exp_timer:%d\n",
|
|
inst_id, udc_cmd, exp_timer);
|
|
if (inst_id == 0) {
|
|
req_des_base = req_des_0_base;
|
|
ap_read = rw_index->md_des_ins0.read;
|
|
md_write = rw_index->md_des_ins0.write;
|
|
} else if (inst_id == 1) {
|
|
req_des_base = req_des_1_base;
|
|
ap_read = rw_index->md_des_ins1.read;
|
|
md_write = rw_index->md_des_ins1.write;
|
|
}
|
|
ctl->curr_state = atomic_read(&udc_status);
|
|
|
|
while (ap_read != md_write) {
|
|
if (inst_id == 0) {
|
|
req_des = req_des_base + ap_read;
|
|
ret = udc_kick_handler(port, &zcpr0,
|
|
inst_id, &comp_data);
|
|
if (ret < 0) {
|
|
CCCI_ERROR_LOG(port->md_id, UDC,
|
|
"udc kick fail ret:%d!!\n", ret);
|
|
goto end;
|
|
}
|
|
if (req_des->con == 0) {
|
|
udc_cmd_check(port, &skb_tmp,
|
|
&skb, inst_id, ctl);
|
|
if (ctl->curr_state ==
|
|
UDC_DEACTV_DONE ||
|
|
ctl->curr_state ==
|
|
UDC_KICKDEACTV) {
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"ins%d:goto deactive_exit\n",
|
|
inst_id);
|
|
goto deactive_exit;
|
|
} else if (ctl->curr_state ==
|
|
UDC_DISC_DONE) {
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"ins%d:goto discard_req\n",
|
|
inst_id);
|
|
goto discard_req;
|
|
}
|
|
}
|
|
/* insure sequential execution */
|
|
/* mb(); */
|
|
ap_read = rw_index->md_des_ins0.read;
|
|
md_write = rw_index->md_des_ins0.write;
|
|
} else if (inst_id == 1) {
|
|
req_des = req_des_base + ap_read;
|
|
ret = udc_kick_handler(port, &zcpr1,
|
|
inst_id, &comp_data);
|
|
if (ret < 0) {
|
|
CCCI_ERROR_LOG(port->md_id, UDC,
|
|
"udc kick fail ret:%d!!\n", ret);
|
|
goto end;
|
|
}
|
|
if (req_des->con == 0) {
|
|
udc_cmd_check(port, &skb_tmp,
|
|
&skb, inst_id, ctl);
|
|
if (ctl->curr_state ==
|
|
UDC_HandleHighKick) {
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"ins%d:goto retry_kick\n",
|
|
inst_id);
|
|
goto retry_kick;
|
|
} else if (ctl->curr_state ==
|
|
UDC_DEACTV_DONE ||
|
|
ctl->curr_state ==
|
|
UDC_KICKDEACTV) {
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"ins%d:goto deactive_exit\n",
|
|
inst_id);
|
|
goto deactive_exit;
|
|
} else if (ctl->curr_state ==
|
|
UDC_DISC_DONE) {
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"ins%d:goto discard_req\n",
|
|
inst_id);
|
|
goto discard_req;
|
|
}
|
|
}
|
|
|
|
/* insure sequential execution */
|
|
/* mb(); */
|
|
ap_read = rw_index->md_des_ins1.read;
|
|
md_write = rw_index->md_des_ins1.write;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
CCCI_ERROR_LOG(md_id, UDC,
|
|
"[Error]Unknown Operation ID (0x%08X)\n",
|
|
ccci_udc_actv->udc_cmd);
|
|
break;
|
|
}
|
|
end:
|
|
/* resp_to_md */
|
|
ret = udc_resp_msg_to_md(port, skb, ret);
|
|
if (ret < 0)
|
|
CCCI_ERROR_LOG(port->md_id, UDC,
|
|
"send udc msg to md fail ret:%d!!\n", ret);
|
|
CCCI_DEBUG_LOG(md_id, UDC,
|
|
"%s-- udc_cmd:%d\n", __func__, udc_cmd);
|
|
/* dump read write index */
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"ins0:md rw:%d %d,ap rw:%d %d,ins1:md rw:%d %d,ap rw:%d %d\n",
|
|
rw_index->md_des_ins0.read, rw_index->md_des_ins0.write,
|
|
rw_index->ap_resp_ins0.read, rw_index->ap_resp_ins0.write,
|
|
rw_index->md_des_ins1.read, rw_index->md_des_ins1.write,
|
|
rw_index->ap_resp_ins1.read, rw_index->ap_resp_ins1.write);
|
|
if (udc_restore_skb(port, ctl, &skb_tmp, &skb)) {
|
|
CCCI_NORMAL_LOG(md_id, UDC,
|
|
"restore_skb:goto retry_kick\n");
|
|
goto retry_kick;
|
|
}
|
|
ccci_free_skb(skb_tmp);
|
|
kfree(ctl);
|
|
}
|
|
|
|
static int port_udc_init(struct port_t *port)
|
|
{
|
|
CCCI_DEBUG_LOG(port->md_id, PORT,
|
|
"kernel port %s is initializing\n", port->name);
|
|
port->skb_handler = &udc_cmd_handler;
|
|
port->private_data = kthread_run(port_kthread_handler,
|
|
port, "%s", port->name);
|
|
port->rx_length_th = MAX_QUEUE_LENGTH;
|
|
port->skb_from_pool = 1;
|
|
return 0;
|
|
}
|
|
|
|
struct port_ops ccci_udc_port_ops = {
|
|
.init = &port_udc_init,
|
|
.recv_skb = &port_recv_skb,
|
|
};
|
|
|