Merge "mhi: uci: Fix a bug related to split transfer packets"
This commit is contained in:
commit
f687374863
1 changed files with 35 additions and 78 deletions
|
@ -326,73 +326,6 @@ static int mhi_init_inbound(struct uci_client *client_handle)
|
||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mhi_uci_send_packet(struct mhi_client_handle **client_handle,
|
|
||||||
void *buf,
|
|
||||||
u32 size)
|
|
||||||
{
|
|
||||||
u32 nr_avail_trbs = 0;
|
|
||||||
u32 i = 0;
|
|
||||||
void *data_loc = NULL;
|
|
||||||
unsigned long memcpy_result = 0;
|
|
||||||
int data_left_to_insert = 0;
|
|
||||||
size_t data_to_insert_now = 0;
|
|
||||||
u32 data_inserted_so_far = 0;
|
|
||||||
int ret_val = 0;
|
|
||||||
struct uci_client *uci_handle;
|
|
||||||
struct uci_buf *uci_buf;
|
|
||||||
|
|
||||||
uci_handle = container_of(client_handle, struct uci_client,
|
|
||||||
out_attr.mhi_handle);
|
|
||||||
|
|
||||||
nr_avail_trbs = atomic_read(&uci_handle->out_attr.avail_pkts);
|
|
||||||
data_left_to_insert = size;
|
|
||||||
|
|
||||||
for (i = 0; i < nr_avail_trbs; ++i) {
|
|
||||||
data_to_insert_now = min_t(size_t, data_left_to_insert,
|
|
||||||
uci_handle->out_attr.max_packet_size);
|
|
||||||
data_loc = kmalloc(data_to_insert_now + sizeof(*uci_buf),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!data_loc) {
|
|
||||||
uci_log(uci_handle->uci_ipc_log, UCI_DBG_VERBOSE,
|
|
||||||
"Failed to allocate memory 0x%zx\n",
|
|
||||||
data_to_insert_now);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
uci_buf = data_loc + data_to_insert_now;
|
|
||||||
uci_buf->data = data_loc;
|
|
||||||
uci_buf->pkt_id = uci_handle->out_attr.pkt_count++;
|
|
||||||
memcpy_result = copy_from_user(uci_buf->data,
|
|
||||||
buf + data_inserted_so_far,
|
|
||||||
data_to_insert_now);
|
|
||||||
if (memcpy_result)
|
|
||||||
goto error_xfer;
|
|
||||||
|
|
||||||
uci_log(uci_handle->uci_ipc_log, UCI_DBG_VERBOSE,
|
|
||||||
"At trb i = %d/%d, size = %lu, id %llu chan %d\n",
|
|
||||||
i, nr_avail_trbs, data_to_insert_now, uci_buf->pkt_id,
|
|
||||||
uci_handle->out_attr.chan_id);
|
|
||||||
ret_val = mhi_queue_xfer(*client_handle, uci_buf->data,
|
|
||||||
data_to_insert_now, MHI_EOT);
|
|
||||||
if (ret_val) {
|
|
||||||
goto error_xfer;
|
|
||||||
} else {
|
|
||||||
data_left_to_insert -= data_to_insert_now;
|
|
||||||
data_inserted_so_far += data_to_insert_now;
|
|
||||||
atomic_inc(&uci_handle->out_pkt_pend_ack);
|
|
||||||
atomic_dec(&uci_handle->out_attr.avail_pkts);
|
|
||||||
list_add_tail(&uci_buf->node,
|
|
||||||
&uci_handle->out_attr.buf_head);
|
|
||||||
}
|
|
||||||
if (!data_left_to_insert)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return data_inserted_so_far;
|
|
||||||
|
|
||||||
error_xfer:
|
|
||||||
kfree(uci_buf->data);
|
|
||||||
return data_inserted_so_far;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mhi_uci_send_status_cmd(struct uci_client *client)
|
static int mhi_uci_send_status_cmd(struct uci_client *client)
|
||||||
{
|
{
|
||||||
void *buf = NULL;
|
void *buf = NULL;
|
||||||
|
@ -963,18 +896,11 @@ static ssize_t mhi_uci_client_write(struct file *file,
|
||||||
goto sys_interrupt;
|
goto sys_interrupt;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (bytes_transferrd != count) {
|
while (count) {
|
||||||
ret_val = mhi_uci_send_packet(&chan_attr->mhi_handle,
|
size_t xfer_size;
|
||||||
(void *)buf, count);
|
void *data_loc = NULL;
|
||||||
if (ret_val < 0)
|
struct uci_buf *uci_buf;
|
||||||
goto sys_interrupt;
|
|
||||||
|
|
||||||
bytes_transferrd += ret_val;
|
|
||||||
if (bytes_transferrd == count)
|
|
||||||
break;
|
|
||||||
uci_log(uci_handle->uci_ipc_log, UCI_DBG_VERBOSE,
|
|
||||||
"No descriptors available, did we poll, chan %d?\n",
|
|
||||||
chan);
|
|
||||||
mutex_unlock(&chan_attr->chan_lock);
|
mutex_unlock(&chan_attr->chan_lock);
|
||||||
ret_val = wait_event_interruptible(chan_attr->wq,
|
ret_val = wait_event_interruptible(chan_attr->wq,
|
||||||
(atomic_read(&chan_attr->avail_pkts) ||
|
(atomic_read(&chan_attr->avail_pkts) ||
|
||||||
|
@ -991,6 +917,37 @@ static ssize_t mhi_uci_client_write(struct file *file,
|
||||||
ret_val = -ERESTARTSYS;
|
ret_val = -ERESTARTSYS;
|
||||||
goto sys_interrupt;
|
goto sys_interrupt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xfer_size = min_t(size_t, count, chan_attr->max_packet_size);
|
||||||
|
data_loc = kmalloc(xfer_size + sizeof(*uci_buf), GFP_KERNEL);
|
||||||
|
if (!data_loc) {
|
||||||
|
uci_log(uci_handle->uci_ipc_log, UCI_DBG_VERBOSE,
|
||||||
|
"Failed to allocate memory %lu\n", xfer_size);
|
||||||
|
ret_val = -ENOMEM;
|
||||||
|
goto sys_interrupt;
|
||||||
|
}
|
||||||
|
|
||||||
|
uci_buf = data_loc + xfer_size;
|
||||||
|
uci_buf->data = data_loc;
|
||||||
|
uci_buf->pkt_id = uci_handle->out_attr.pkt_count++;
|
||||||
|
ret_val = copy_from_user(uci_buf->data, buf, xfer_size);
|
||||||
|
if (unlikely(ret_val)) {
|
||||||
|
kfree(uci_buf->data);
|
||||||
|
goto sys_interrupt;
|
||||||
|
}
|
||||||
|
ret_val = mhi_queue_xfer(chan_attr->mhi_handle, uci_buf->data,
|
||||||
|
xfer_size, MHI_EOT);
|
||||||
|
if (unlikely(ret_val)) {
|
||||||
|
kfree(uci_buf->data);
|
||||||
|
goto sys_interrupt;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_transferrd += xfer_size;
|
||||||
|
count -= xfer_size;
|
||||||
|
buf += xfer_size;
|
||||||
|
atomic_inc(&uci_handle->out_pkt_pend_ack);
|
||||||
|
atomic_dec(&uci_handle->out_attr.avail_pkts);
|
||||||
|
list_add_tail(&uci_buf->node, &uci_handle->out_attr.buf_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&chan_attr->chan_lock);
|
mutex_unlock(&chan_attr->chan_lock);
|
||||||
|
|
Loading…
Add table
Reference in a new issue