Loading drivers/soc/qcom/ipc_router_hsic_xprt.c +71 −26 Original line number Diff line number Diff line Loading @@ -213,6 +213,9 @@ static int msm_ipc_router_hsic_remote_write(void *data, struct ipc_bridge_platform_data *pdata; struct msm_ipc_router_hsic_xprt *hsic_xprtp; int ret; uint32_t bytes_written = 0; uint32_t bytes_to_write; unsigned char *tx_data; if (!pkt || pkt->length != len || !xprt) { IPC_RTR_ERR("%s: Invalid input parameters\n", __func__); Loading Loading @@ -247,9 +250,29 @@ static int msm_ipc_router_hsic_remote_write(void *data, return -EINVAL; } D("%s: About to write %d bytes\n", __func__, len); ret = pdata->write(hsic_xprtp->pdev, skb->data, skb->len); if (ret == skb->len) ret = len; while (bytes_written < len) { bytes_to_write = min_t(uint32_t, (skb->len - bytes_written), pdata->max_write_size); tx_data = skb->data + bytes_written; ret = pdata->write(hsic_xprtp->pdev, tx_data, bytes_to_write); if (ret < 0) { IPC_RTR_ERR("%s: Error writing data %d\n", __func__, ret); break; } if (ret != bytes_to_write) IPC_RTR_ERR("%s: Partial write %d < %d, retrying...\n", __func__, ret, bytes_to_write); bytes_written += bytes_to_write; } if (bytes_written == len) { ret = bytes_written; } else if (ret > 0 && bytes_written != len) { IPC_RTR_ERR("%s: Fault writing data %d != %d\n", __func__, bytes_written, len); ret = -EFAULT; } D("%s: Finished writing %d bytes\n", __func__, len); mutex_unlock(&hsic_xprtp->ss_reset_lock); return ret; Loading Loading @@ -294,7 +317,9 @@ static int msm_ipc_router_hsic_remote_close( */ static void hsic_xprt_read_data(struct work_struct *work) { int pkt_size; int bytes_to_read; int bytes_read; int skb_size; struct sk_buff *skb = NULL; struct ipc_bridge_platform_data *pdata; struct delayed_work *rwork = to_delayed_work(work); Loading @@ -319,33 +344,53 @@ static void hsic_xprt_read_data(struct work_struct *work) } D("%s: Allocated rr_packet\n", __func__); while (!skb) { skb = alloc_skb(pdata->max_read_size, GFP_KERNEL); bytes_to_read = 0; skb_size = pdata->max_read_size; do { do { skb = alloc_skb(skb_size, GFP_KERNEL); if (skb) break; IPC_RTR_ERR("%s: Couldn't alloc SKB\n", __func__); IPC_RTR_ERR("%s: Couldn't alloc SKB\n", __func__); msleep(100); } pkt_size = pdata->read(hsic_xprtp->pdev, skb->data, } while (!skb); bytes_read = pdata->read(hsic_xprtp->pdev, skb->data, pdata->max_read_size); if (pkt_size < 0) { if (bytes_read < 0) { IPC_RTR_ERR("%s: Error %d @ read operation\n", __func__, pkt_size); __func__, bytes_read); kfree_skb(skb); kfree(hsic_xprtp->in_pkt->pkt_fragment_q); kfree(hsic_xprtp->in_pkt); break; goto out_read_data; } if (!bytes_to_read) { bytes_to_read = ipc_router_peek_pkt_size( skb->data); if (bytes_to_read < 0) { IPC_RTR_ERR("%s: Invalid size %d\n", __func__, bytes_to_read); kfree_skb(skb); goto out_read_data; } } skb_put(skb, pkt_size); bytes_to_read -= bytes_read; skb_put(skb, bytes_read); skb_queue_tail(hsic_xprtp->in_pkt->pkt_fragment_q, skb); hsic_xprtp->in_pkt->length = pkt_size; D("%s: Packet size read %d\n", __func__, pkt_size); hsic_xprtp->in_pkt->length += bytes_read; skb_size = min_t(uint32_t, pdata->max_read_size, (uint32_t)bytes_to_read); } while (bytes_to_read > 0); D("%s: Packet size read %d\n", __func__, hsic_xprtp->in_pkt->length); msm_ipc_router_xprt_notify(&hsic_xprtp->xprt, IPC_ROUTER_XPRT_EVENT_DATA, (void *)hsic_xprtp->in_pkt); release_pkt(hsic_xprtp->in_pkt); hsic_xprtp->in_pkt = NULL; skb = NULL; } out_read_data: release_pkt(hsic_xprtp->in_pkt); hsic_xprtp->in_pkt = NULL; } /** Loading include/linux/ipc_router_xprt.h +12 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,18 @@ struct rr_packet *create_pkt(struct sk_buff_head *data); struct rr_packet *clone_pkt(struct rr_packet *pkt); void release_pkt(struct rr_packet *pkt); /** * ipc_router_peek_pkt_size() - Peek into the packet header to get potential packet size * @data: Starting address of the packet which points to router header. * * @returns: potential packet size on success, < 0 on error. * * This function is used by the underlying transport abstraction layer to * peek into the potential packet size of an incoming packet. This information * is used to perform link layer fragmentation and re-assembly */ int ipc_router_peek_pkt_size(char *data); #if defined CONFIG_MSM_IPC_ROUTER_SMD_XPRT extern void *msm_ipc_load_default_node(void); Loading net/ipc_router/ipc_router_core.c +33 −0 Original line number Diff line number Diff line Loading @@ -867,6 +867,39 @@ static int post_pkt_to_port(struct msm_ipc_port *port_ptr, return 0; } /** * ipc_router_peek_pkt_size() - Peek into the packet header to get potential packet size * @data: Starting address of the packet which points to router header. * * @returns: potential packet size on success, < 0 on error. * * This function is used by the underlying transport abstraction layer to * peek into the potential packet size of an incoming packet. This information * is used to perform link layer fragmentation and re-assembly */ int ipc_router_peek_pkt_size(char *data) { int size; if (!data) { pr_err("%s: NULL PKT\n", __func__); return -EINVAL; } /* FUTURE: Calculate optional header len in V2 header*/ if (data[0] == IPC_ROUTER_V1) size = ((struct rr_header_v1 *)data)->size + sizeof(struct rr_header_v1); else if (data[0] == IPC_ROUTER_V2) size = ((struct rr_header_v2 *)data)->size + sizeof(struct rr_header_v2); else return -EINVAL; size += ALIGN_SIZE(size); return size; } static int post_control_ports(struct rr_packet *pkt) { struct msm_ipc_port *port_ptr; Loading Loading
drivers/soc/qcom/ipc_router_hsic_xprt.c +71 −26 Original line number Diff line number Diff line Loading @@ -213,6 +213,9 @@ static int msm_ipc_router_hsic_remote_write(void *data, struct ipc_bridge_platform_data *pdata; struct msm_ipc_router_hsic_xprt *hsic_xprtp; int ret; uint32_t bytes_written = 0; uint32_t bytes_to_write; unsigned char *tx_data; if (!pkt || pkt->length != len || !xprt) { IPC_RTR_ERR("%s: Invalid input parameters\n", __func__); Loading Loading @@ -247,9 +250,29 @@ static int msm_ipc_router_hsic_remote_write(void *data, return -EINVAL; } D("%s: About to write %d bytes\n", __func__, len); ret = pdata->write(hsic_xprtp->pdev, skb->data, skb->len); if (ret == skb->len) ret = len; while (bytes_written < len) { bytes_to_write = min_t(uint32_t, (skb->len - bytes_written), pdata->max_write_size); tx_data = skb->data + bytes_written; ret = pdata->write(hsic_xprtp->pdev, tx_data, bytes_to_write); if (ret < 0) { IPC_RTR_ERR("%s: Error writing data %d\n", __func__, ret); break; } if (ret != bytes_to_write) IPC_RTR_ERR("%s: Partial write %d < %d, retrying...\n", __func__, ret, bytes_to_write); bytes_written += bytes_to_write; } if (bytes_written == len) { ret = bytes_written; } else if (ret > 0 && bytes_written != len) { IPC_RTR_ERR("%s: Fault writing data %d != %d\n", __func__, bytes_written, len); ret = -EFAULT; } D("%s: Finished writing %d bytes\n", __func__, len); mutex_unlock(&hsic_xprtp->ss_reset_lock); return ret; Loading Loading @@ -294,7 +317,9 @@ static int msm_ipc_router_hsic_remote_close( */ static void hsic_xprt_read_data(struct work_struct *work) { int pkt_size; int bytes_to_read; int bytes_read; int skb_size; struct sk_buff *skb = NULL; struct ipc_bridge_platform_data *pdata; struct delayed_work *rwork = to_delayed_work(work); Loading @@ -319,33 +344,53 @@ static void hsic_xprt_read_data(struct work_struct *work) } D("%s: Allocated rr_packet\n", __func__); while (!skb) { skb = alloc_skb(pdata->max_read_size, GFP_KERNEL); bytes_to_read = 0; skb_size = pdata->max_read_size; do { do { skb = alloc_skb(skb_size, GFP_KERNEL); if (skb) break; IPC_RTR_ERR("%s: Couldn't alloc SKB\n", __func__); IPC_RTR_ERR("%s: Couldn't alloc SKB\n", __func__); msleep(100); } pkt_size = pdata->read(hsic_xprtp->pdev, skb->data, } while (!skb); bytes_read = pdata->read(hsic_xprtp->pdev, skb->data, pdata->max_read_size); if (pkt_size < 0) { if (bytes_read < 0) { IPC_RTR_ERR("%s: Error %d @ read operation\n", __func__, pkt_size); __func__, bytes_read); kfree_skb(skb); kfree(hsic_xprtp->in_pkt->pkt_fragment_q); kfree(hsic_xprtp->in_pkt); break; goto out_read_data; } if (!bytes_to_read) { bytes_to_read = ipc_router_peek_pkt_size( skb->data); if (bytes_to_read < 0) { IPC_RTR_ERR("%s: Invalid size %d\n", __func__, bytes_to_read); kfree_skb(skb); goto out_read_data; } } skb_put(skb, pkt_size); bytes_to_read -= bytes_read; skb_put(skb, bytes_read); skb_queue_tail(hsic_xprtp->in_pkt->pkt_fragment_q, skb); hsic_xprtp->in_pkt->length = pkt_size; D("%s: Packet size read %d\n", __func__, pkt_size); hsic_xprtp->in_pkt->length += bytes_read; skb_size = min_t(uint32_t, pdata->max_read_size, (uint32_t)bytes_to_read); } while (bytes_to_read > 0); D("%s: Packet size read %d\n", __func__, hsic_xprtp->in_pkt->length); msm_ipc_router_xprt_notify(&hsic_xprtp->xprt, IPC_ROUTER_XPRT_EVENT_DATA, (void *)hsic_xprtp->in_pkt); release_pkt(hsic_xprtp->in_pkt); hsic_xprtp->in_pkt = NULL; skb = NULL; } out_read_data: release_pkt(hsic_xprtp->in_pkt); hsic_xprtp->in_pkt = NULL; } /** Loading
include/linux/ipc_router_xprt.h +12 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,18 @@ struct rr_packet *create_pkt(struct sk_buff_head *data); struct rr_packet *clone_pkt(struct rr_packet *pkt); void release_pkt(struct rr_packet *pkt); /** * ipc_router_peek_pkt_size() - Peek into the packet header to get potential packet size * @data: Starting address of the packet which points to router header. * * @returns: potential packet size on success, < 0 on error. * * This function is used by the underlying transport abstraction layer to * peek into the potential packet size of an incoming packet. This information * is used to perform link layer fragmentation and re-assembly */ int ipc_router_peek_pkt_size(char *data); #if defined CONFIG_MSM_IPC_ROUTER_SMD_XPRT extern void *msm_ipc_load_default_node(void); Loading
net/ipc_router/ipc_router_core.c +33 −0 Original line number Diff line number Diff line Loading @@ -867,6 +867,39 @@ static int post_pkt_to_port(struct msm_ipc_port *port_ptr, return 0; } /** * ipc_router_peek_pkt_size() - Peek into the packet header to get potential packet size * @data: Starting address of the packet which points to router header. * * @returns: potential packet size on success, < 0 on error. * * This function is used by the underlying transport abstraction layer to * peek into the potential packet size of an incoming packet. This information * is used to perform link layer fragmentation and re-assembly */ int ipc_router_peek_pkt_size(char *data) { int size; if (!data) { pr_err("%s: NULL PKT\n", __func__); return -EINVAL; } /* FUTURE: Calculate optional header len in V2 header*/ if (data[0] == IPC_ROUTER_V1) size = ((struct rr_header_v1 *)data)->size + sizeof(struct rr_header_v1); else if (data[0] == IPC_ROUTER_V2) size = ((struct rr_header_v2 *)data)->size + sizeof(struct rr_header_v2); else return -EINVAL; size += ALIGN_SIZE(size); return size; } static int post_control_ports(struct rr_packet *pkt) { struct msm_ipc_port *port_ptr; Loading