Loading drivers/usb/gadget/f_rndis.c +29 −7 Original line number Diff line number Diff line Loading @@ -405,14 +405,36 @@ static struct sk_buff *rndis_add_header(struct gether *port, struct sk_buff *skb) { struct sk_buff *skb2; skb2 = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type)); struct rndis_packet_msg_type *header = NULL; struct f_rndis *rndis = func_to_rndis(&port->func); if (rndis->port.multi_pkt_xfer) { if (port->header) { header = port->header; memset(header, 0, sizeof(*header)); header->MessageType = cpu_to_le32(RNDIS_MSG_PACKET); header->MessageLength = cpu_to_le32(skb->len + sizeof(*header)); header->DataOffset = cpu_to_le32(36); header->DataLength = cpu_to_le32(skb->len); pr_debug("MessageLength:%d DataLength:%d\n", header->MessageLength, header->DataLength); return skb; } else { pr_err("RNDIS header is NULL.\n"); return NULL; } } else { skb2 = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type)); if (skb2) rndis_add_hdr(skb2); dev_kfree_skb_any(skb); return skb2; } } static void rndis_response_available(void *_rndis) { Loading drivers/usb/gadget/u_ether.c +58 −23 Original line number Diff line number Diff line Loading @@ -229,6 +229,7 @@ static void defer_kevent(struct eth_dev *dev, int flag) } static void rx_complete(struct usb_ep *ep, struct usb_request *req); static void tx_complete(struct usb_ep *ep, struct usb_request *req); static int rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) Loading Loading @@ -295,7 +296,6 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) req->buf = skb->data; req->length = size; req->complete = rx_complete; req->context = skb; retval = usb_ep_queue(out, req, gfp_flags); Loading Loading @@ -388,6 +388,7 @@ static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n) { unsigned i; struct usb_request *req; bool usb_in; if (!n) return -ENOMEM; Loading @@ -398,10 +399,22 @@ static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n) if (i-- == 0) goto extra; } if (ep->desc->bEndpointAddress & USB_DIR_IN) usb_in = true; else usb_in = false; while (i--) { req = usb_ep_alloc_request(ep, GFP_ATOMIC); if (!req) return list_empty(list) ? -ENOMEM : 0; /* update completion handler */ if (usb_in) req->complete = tx_complete; else req->complete = rx_complete; list_add(&req->list, list); } return 0; Loading Loading @@ -545,7 +558,7 @@ static void eth_work(struct work_struct *work) static void tx_complete(struct usb_ep *ep, struct usb_request *req) { struct sk_buff *skb = req->context; struct sk_buff *skb; struct eth_dev *dev; struct net_device *net; struct usb_request *new_req; Loading Loading @@ -619,7 +632,6 @@ static void tx_complete(struct usb_ep *ep, struct usb_request *req) } new_req->length = length; new_req->complete = tx_complete; retval = usb_ep_queue(in, new_req, GFP_ATOMIC); switch (retval) { default: Loading Loading @@ -651,6 +663,7 @@ static void tx_complete(struct usb_ep *ep, struct usb_request *req) spin_unlock(&dev->req_lock); } } else { skb = req->context; spin_unlock(&dev->req_lock); dev_kfree_skb_any(skb); } Loading Loading @@ -679,7 +692,7 @@ static int alloc_tx_buffer(struct eth_dev *dev) list_for_each(act, &dev->tx_reqs) { req = container_of(act, struct usb_request, list); if (!req->buf) req->buf = kmalloc(dev->tx_req_bufsize, req->buf = kzalloc(dev->tx_req_bufsize, GFP_ATOMIC); if (!req->buf) goto free_buf; Loading Loading @@ -784,28 +797,37 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, * or the hardware can't use skb buffers. * or there's not enough space for extra headers we need */ if (dev->wrap) { unsigned long flags; spin_lock_irqsave(&dev->lock, flags); if (dev->wrap) { if (dev->port_usb) skb = dev->wrap(dev->port_usb, skb); if (!skb) { spin_unlock_irqrestore(&dev->lock, flags); if (!skb) goto drop; } spin_lock_irqsave(&dev->req_lock, flags); dev->tx_skb_hold_count++; spin_unlock_irqrestore(&dev->req_lock, flags); } if (multi_pkt_xfer) { pr_debug("req->length:%d header_len:%u\n" "skb->len:%d skb->data_len:%d\n", req->length, dev->header_len, skb->len, skb->data_len); /* Add RNDIS Header */ memcpy(req->buf + req->length, dev->port_usb->header, dev->header_len); /* Increment req length by header size */ req->length += dev->header_len; spin_unlock_irqrestore(&dev->lock, flags); /* Copy received IP data from SKB */ memcpy(req->buf + req->length, skb->data, skb->len); req->length = req->length + skb->len; /* Increment req length by skb data length */ req->length += skb->len; length = req->length; dev_kfree_skb_any(skb); spin_lock_irqsave(&dev->req_lock, flags); dev->tx_skb_hold_count++; if (dev->tx_skb_hold_count < dev->dl_max_pkts_per_xfer) { if (dev->no_tx_req_used > TX_REQ_THRESHOLD) { list_add(&req->list, &dev->tx_reqs); Loading @@ -815,19 +837,15 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, } dev->no_tx_req_used++; spin_unlock_irqrestore(&dev->req_lock, flags); spin_lock_irqsave(&dev->lock, flags); dev->tx_skb_hold_count = 0; spin_unlock_irqrestore(&dev->lock, flags); spin_unlock_irqrestore(&dev->req_lock, flags); } else { spin_unlock_irqrestore(&dev->lock, flags); length = skb->len; req->buf = skb->data; req->context = skb; } req->complete = tx_complete; /* NCM requires no zlp if transfer is dwNtbInMaxSize */ if (dev->port_usb->is_fixed && length == dev->port_usb->fixed_in_len && Loading Loading @@ -880,7 +898,7 @@ drop: spin_lock_irqsave(&dev->req_lock, flags); if (list_empty(&dev->tx_reqs)) netif_start_queue(net); list_add(&req->list, &dev->tx_reqs); list_add_tail(&req->list, &dev->tx_reqs); spin_unlock_irqrestore(&dev->req_lock, flags); } success: Loading Loading @@ -1240,6 +1258,14 @@ struct net_device *gether_connect(struct gether *link) if (!dev) return ERR_PTR(-EINVAL); link->header = kzalloc(sizeof(struct rndis_packet_msg_type), GFP_ATOMIC); if (!link->header) { pr_err("RNDIS header memory allocation failed.\n"); result = -ENOMEM; goto fail; } link->in_ep->driver_data = dev; result = usb_ep_enable(link->in_ep); if (result != 0) { Loading @@ -1260,6 +1286,7 @@ struct net_device *gether_connect(struct gether *link) result = alloc_requests(dev, link, qlen(dev->gadget)); if (result == 0) { dev->zlp = link->is_zlp_ok; DBG(dev, "qlen %d\n", qlen(dev->gadget)); Loading Loading @@ -1298,10 +1325,15 @@ struct net_device *gether_connect(struct gether *link) fail1: (void) usb_ep_disable(link->in_ep); } fail0: /* caller is responsible for cleanup on error */ if (result < 0) if (result < 0) { fail0: kfree(link->header); fail: return ERR_PTR(result); } return dev->net; } Loading Loading @@ -1348,6 +1380,9 @@ void gether_disconnect(struct gether *link) usb_ep_free_request(link->in_ep, req); spin_lock(&dev->req_lock); } /* Free rndis header buffer memory */ kfree(link->header); link->header = NULL; spin_unlock(&dev->req_lock); link->in_ep->driver_data = NULL; link->in_ep->desc = NULL; Loading drivers/usb/gadget/u_ether.h +2 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,8 @@ struct gether { /* called on network open/close */ void (*open)(struct gether *); void (*close)(struct gether *); struct rndis_packet_msg_type *header; }; #define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ Loading Loading
drivers/usb/gadget/f_rndis.c +29 −7 Original line number Diff line number Diff line Loading @@ -405,14 +405,36 @@ static struct sk_buff *rndis_add_header(struct gether *port, struct sk_buff *skb) { struct sk_buff *skb2; skb2 = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type)); struct rndis_packet_msg_type *header = NULL; struct f_rndis *rndis = func_to_rndis(&port->func); if (rndis->port.multi_pkt_xfer) { if (port->header) { header = port->header; memset(header, 0, sizeof(*header)); header->MessageType = cpu_to_le32(RNDIS_MSG_PACKET); header->MessageLength = cpu_to_le32(skb->len + sizeof(*header)); header->DataOffset = cpu_to_le32(36); header->DataLength = cpu_to_le32(skb->len); pr_debug("MessageLength:%d DataLength:%d\n", header->MessageLength, header->DataLength); return skb; } else { pr_err("RNDIS header is NULL.\n"); return NULL; } } else { skb2 = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type)); if (skb2) rndis_add_hdr(skb2); dev_kfree_skb_any(skb); return skb2; } } static void rndis_response_available(void *_rndis) { Loading
drivers/usb/gadget/u_ether.c +58 −23 Original line number Diff line number Diff line Loading @@ -229,6 +229,7 @@ static void defer_kevent(struct eth_dev *dev, int flag) } static void rx_complete(struct usb_ep *ep, struct usb_request *req); static void tx_complete(struct usb_ep *ep, struct usb_request *req); static int rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) Loading Loading @@ -295,7 +296,6 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) req->buf = skb->data; req->length = size; req->complete = rx_complete; req->context = skb; retval = usb_ep_queue(out, req, gfp_flags); Loading Loading @@ -388,6 +388,7 @@ static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n) { unsigned i; struct usb_request *req; bool usb_in; if (!n) return -ENOMEM; Loading @@ -398,10 +399,22 @@ static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n) if (i-- == 0) goto extra; } if (ep->desc->bEndpointAddress & USB_DIR_IN) usb_in = true; else usb_in = false; while (i--) { req = usb_ep_alloc_request(ep, GFP_ATOMIC); if (!req) return list_empty(list) ? -ENOMEM : 0; /* update completion handler */ if (usb_in) req->complete = tx_complete; else req->complete = rx_complete; list_add(&req->list, list); } return 0; Loading Loading @@ -545,7 +558,7 @@ static void eth_work(struct work_struct *work) static void tx_complete(struct usb_ep *ep, struct usb_request *req) { struct sk_buff *skb = req->context; struct sk_buff *skb; struct eth_dev *dev; struct net_device *net; struct usb_request *new_req; Loading Loading @@ -619,7 +632,6 @@ static void tx_complete(struct usb_ep *ep, struct usb_request *req) } new_req->length = length; new_req->complete = tx_complete; retval = usb_ep_queue(in, new_req, GFP_ATOMIC); switch (retval) { default: Loading Loading @@ -651,6 +663,7 @@ static void tx_complete(struct usb_ep *ep, struct usb_request *req) spin_unlock(&dev->req_lock); } } else { skb = req->context; spin_unlock(&dev->req_lock); dev_kfree_skb_any(skb); } Loading Loading @@ -679,7 +692,7 @@ static int alloc_tx_buffer(struct eth_dev *dev) list_for_each(act, &dev->tx_reqs) { req = container_of(act, struct usb_request, list); if (!req->buf) req->buf = kmalloc(dev->tx_req_bufsize, req->buf = kzalloc(dev->tx_req_bufsize, GFP_ATOMIC); if (!req->buf) goto free_buf; Loading Loading @@ -784,28 +797,37 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, * or the hardware can't use skb buffers. * or there's not enough space for extra headers we need */ if (dev->wrap) { unsigned long flags; spin_lock_irqsave(&dev->lock, flags); if (dev->wrap) { if (dev->port_usb) skb = dev->wrap(dev->port_usb, skb); if (!skb) { spin_unlock_irqrestore(&dev->lock, flags); if (!skb) goto drop; } spin_lock_irqsave(&dev->req_lock, flags); dev->tx_skb_hold_count++; spin_unlock_irqrestore(&dev->req_lock, flags); } if (multi_pkt_xfer) { pr_debug("req->length:%d header_len:%u\n" "skb->len:%d skb->data_len:%d\n", req->length, dev->header_len, skb->len, skb->data_len); /* Add RNDIS Header */ memcpy(req->buf + req->length, dev->port_usb->header, dev->header_len); /* Increment req length by header size */ req->length += dev->header_len; spin_unlock_irqrestore(&dev->lock, flags); /* Copy received IP data from SKB */ memcpy(req->buf + req->length, skb->data, skb->len); req->length = req->length + skb->len; /* Increment req length by skb data length */ req->length += skb->len; length = req->length; dev_kfree_skb_any(skb); spin_lock_irqsave(&dev->req_lock, flags); dev->tx_skb_hold_count++; if (dev->tx_skb_hold_count < dev->dl_max_pkts_per_xfer) { if (dev->no_tx_req_used > TX_REQ_THRESHOLD) { list_add(&req->list, &dev->tx_reqs); Loading @@ -815,19 +837,15 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, } dev->no_tx_req_used++; spin_unlock_irqrestore(&dev->req_lock, flags); spin_lock_irqsave(&dev->lock, flags); dev->tx_skb_hold_count = 0; spin_unlock_irqrestore(&dev->lock, flags); spin_unlock_irqrestore(&dev->req_lock, flags); } else { spin_unlock_irqrestore(&dev->lock, flags); length = skb->len; req->buf = skb->data; req->context = skb; } req->complete = tx_complete; /* NCM requires no zlp if transfer is dwNtbInMaxSize */ if (dev->port_usb->is_fixed && length == dev->port_usb->fixed_in_len && Loading Loading @@ -880,7 +898,7 @@ drop: spin_lock_irqsave(&dev->req_lock, flags); if (list_empty(&dev->tx_reqs)) netif_start_queue(net); list_add(&req->list, &dev->tx_reqs); list_add_tail(&req->list, &dev->tx_reqs); spin_unlock_irqrestore(&dev->req_lock, flags); } success: Loading Loading @@ -1240,6 +1258,14 @@ struct net_device *gether_connect(struct gether *link) if (!dev) return ERR_PTR(-EINVAL); link->header = kzalloc(sizeof(struct rndis_packet_msg_type), GFP_ATOMIC); if (!link->header) { pr_err("RNDIS header memory allocation failed.\n"); result = -ENOMEM; goto fail; } link->in_ep->driver_data = dev; result = usb_ep_enable(link->in_ep); if (result != 0) { Loading @@ -1260,6 +1286,7 @@ struct net_device *gether_connect(struct gether *link) result = alloc_requests(dev, link, qlen(dev->gadget)); if (result == 0) { dev->zlp = link->is_zlp_ok; DBG(dev, "qlen %d\n", qlen(dev->gadget)); Loading Loading @@ -1298,10 +1325,15 @@ struct net_device *gether_connect(struct gether *link) fail1: (void) usb_ep_disable(link->in_ep); } fail0: /* caller is responsible for cleanup on error */ if (result < 0) if (result < 0) { fail0: kfree(link->header); fail: return ERR_PTR(result); } return dev->net; } Loading Loading @@ -1348,6 +1380,9 @@ void gether_disconnect(struct gether *link) usb_ep_free_request(link->in_ep, req); spin_lock(&dev->req_lock); } /* Free rndis header buffer memory */ kfree(link->header); link->header = NULL; spin_unlock(&dev->req_lock); link->in_ep->driver_data = NULL; link->in_ep->desc = NULL; Loading
drivers/usb/gadget/u_ether.h +2 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,8 @@ struct gether { /* called on network open/close */ void (*open)(struct gether *); void (*close)(struct gether *); struct rndis_packet_msg_type *header; }; #define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ Loading