commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=3ff499101e882b2cf6367cf448a1cf4018f00459 branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk
Signed-off-by: Steven Miao <[email protected]> --- drivers/staging/icc/core/protocol.c | 50 ++++++++++++++++++++++++++++++++-- drivers/staging/icc/include/icc.h | 12 ++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/drivers/staging/icc/core/protocol.c b/drivers/staging/icc/core/protocol.c index 321d61a..9b77fbf 100644 --- a/drivers/staging/icc/core/protocol.c +++ b/drivers/staging/icc/core/protocol.c @@ -84,7 +84,7 @@ static struct sm_icc_desc *get_icc_peer(struct sm_msg *msg) BUG_ON(!msg); for (i = 0; i < bfin_icc->peer_count; i++) { if (((uint32_t)icc_info[i].icc_high_queue < msg_addr) && - (msg_addr < (uint32_t)icc_info[i].icc_high_queue + 4 * sizeof(struct sm_message_queue))) + (msg_addr < (uint32_t)icc_info[i].icc_high_queue + MSGQ_SIZE)) break; } @@ -93,6 +93,28 @@ static struct sm_icc_desc *get_icc_peer(struct sm_msg *msg) return &icc_info[i]; } +static int sm_get_icc_queue_attribute(uint32_t cpu, uint32_t type, uint32_t *attribute) +{ + if (cpu > bfin_icc->peer_count) + return -EINVAL; + if (type >= ICC_QUEUE_ATTR_MAX) + return -EINVAL; + if (!attribute) + return -EINVAL; + *attribute = *(bfin_icc->icc_info[cpu - 1].icc_queue_attribute + type); + return 0; +} + +static int sm_set_icc_queue_attribute(uint32_t cpu, uint32_t type, uint32_t attribute) +{ + if (cpu > bfin_icc->peer_count) + return -EINVAL; + if (type >= ICC_QUEUE_ATTR_MAX) + return -EINVAL; + *(bfin_icc->icc_info[cpu - 1].icc_queue_attribute + type) = attribute; + return 0; +} + static struct sm_message_queue *sm_find_queue(struct sm_message *message, struct sm_session *session) { uint16_t dst = message->dst; @@ -551,6 +573,7 @@ sm_send_packet(uint32_t session_idx, uint32_t dst_ep, uint32_t dst_cpu, struct sm_message *m; void *payload_buf = NULL; int ret = -EAGAIN; + uint32_t queue_status; if (session_idx < 0 || session_idx >= MAX_SESSIONS) return -EINVAL; session = sm_index_to_session(session_idx); @@ -618,8 +641,14 @@ retry: sm_debug("<<<<wakeup send queue\n"); goto retry; } else { - if (session->type == SP_TASK_MANAGER) + if (session->type == SP_TASK_MANAGER) { + while (!sm_get_icc_queue_attribute(m->dst, + ICC_QUEUE_ATTR_STATUS, &queue_status)) { + if (queue_status == ICC_QUEUE_READY) + break; + } kfree(m); + } goto out; } @@ -881,6 +910,7 @@ static int sm_destroy_session(uint32_t session_idx) struct sm_msg *msg; struct sm_session *session; struct sm_session_table *table = bfin_icc->sessions_table; + session = sm_index_to_session(session_idx); if (!session) return -EINVAL; @@ -1403,6 +1433,7 @@ static int sm_task_sendmsg(struct sm_message *message, struct sm_session *sessio { struct sm_msg *msg = &message->msg; struct sm_task *task; + if (msg->length >= sizeof(struct sm_task)) msg->type = SM_TASK_RUN; else @@ -1413,6 +1444,11 @@ static int sm_task_sendmsg(struct sm_message *message, struct sm_session *sessio flush_dcache_range(_ramend, physical_mem_end - _ramend); task = (struct sm_task *)msg->payload; sm_debug("%s init addr%p\n", __func__, task->task_init); + sm_set_icc_queue_attribute(message->dst, ICC_QUEUE_ATTR_STATUS, ICC_QUEUE_STOP); + mutex_lock(&bfin_icc->sessions_table->lock); + list_add_tail(&message->next, &session->tx_messages); + session->n_uncompleted++; + mutex_unlock(&bfin_icc->sessions_table->lock); break; case SM_TASK_KILL: break; @@ -1424,10 +1460,15 @@ static int sm_task_sendmsg(struct sm_message *message, struct sm_session *sessio static int sm_task_recvmsg(struct sm_msg *msg, struct sm_session *session) { + struct sm_message *message; sm_debug("%s msg type %x\n", __func__, (uint32_t)msg->type); switch (msg->type) { case SM_TASK_RUN_ACK: sm_debug("%s free %x\n", __func__, (uint32_t)msg->payload); + message = list_first_entry(&session->tx_messages, + struct sm_message, next); + list_del(&message->next); + kfree((void *)msg->payload); break; case SM_TASK_KILL_ACK: @@ -1725,7 +1766,10 @@ static int __devinit bfin_icc_probe(struct platform_device *pdev) /* icc_queue[0] is rx queue, icc_queue[1] is tx queue. */ icc_info->icc_high_queue = (struct sm_message_queue *)icc_data->peer_info[i].phy_peer_mem; icc_info->icc_queue = (struct sm_message_queue *)icc_info->icc_high_queue + 2; - memset(icc_info->icc_high_queue, 0, sizeof(struct sm_message_queue) * SM_MSGQ_NUM); + memset(icc_info->icc_high_queue, 0, MSGQ_SIZE); + icc_info->icc_queue_attribute = (uint32_t *)((uint32_t) + icc_info->icc_high_queue + MSGQ_SIZE); + memset(icc_info->icc_queue_attribute, 0, 4 * ICC_QUEUE_ATTR_MAX); init_waitqueue_head(&icc_info->iccq_tx_wait); icc_info->iccq_thread = kthread_run(message_queue_thread, diff --git a/drivers/staging/icc/include/icc.h b/drivers/staging/icc/include/icc.h index 344d81a..1a86d4d 100644 --- a/drivers/staging/icc/include/icc.h +++ b/drivers/staging/icc/include/icc.h @@ -37,6 +37,17 @@ enum { SP_MAX, }; +enum icc_queue_attr { + ICC_QUEUE_ATTR_STATUS = 0, + ICC_QUEUE_ATTR_MAX, +}; + +enum icc_queue_status { + ICC_QUEUE_STOP = 0, + ICC_QUEUE_INIT, + ICC_QUEUE_READY, + ICC_QUEUE_STATUS_MAX, +}; #define SM_UNCONNECT 0 #define SM_CONNECT 0x1 @@ -162,6 +173,7 @@ struct sm_icc_desc { uint32_t peer_cpu; struct sm_message_queue *icc_queue; struct sm_message_queue *icc_high_queue; + uint32_t *icc_queue_attribute; struct task_struct *iccq_thread; wait_queue_head_t iccq_tx_wait; uint32_t irq;
_______________________________________________ Linux-kernel-commits mailing list [email protected] https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits
