Loading drivers/usb/gadget/function/f_rndis.c +15 −0 Original line number Original line Diff line number Diff line Loading @@ -66,6 +66,8 @@ * - MS-Windows drivers sometimes emit undocumented requests. * - MS-Windows drivers sometimes emit undocumented requests. */ */ #define RNDIS_UL_MAX_PKT_PER_XFER 3 struct f_rndis { struct f_rndis { struct gether port; struct gether port; u8 ctrl_id, data_id; u8 ctrl_id, data_id; Loading Loading @@ -670,6 +672,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) struct usb_string *us; struct usb_string *us; int status; int status; struct usb_ep *ep; struct usb_ep *ep; unsigned int max; struct f_rndis_opts *rndis_opts; struct f_rndis_opts *rndis_opts; Loading Loading @@ -795,6 +798,11 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) rndis_set_param_medium(rndis->params, RNDIS_MEDIUM_802_3, 0); rndis_set_param_medium(rndis->params, RNDIS_MEDIUM_802_3, 0); rndis_set_host_mac(rndis->params, rndis->ethaddr); rndis_set_host_mac(rndis->params, rndis->ethaddr); max = gether_get_ul_max_pkts_per_xfer(rndis_opts->net); if (!max) max = RNDIS_UL_MAX_PKT_PER_XFER; rndis_set_max_pkt_xfer(rndis->params, max); if (rndis->manufacturer && rndis->vendorID && if (rndis->manufacturer && rndis->vendorID && rndis_set_param_vendor(rndis->params, rndis->vendorID, rndis_set_param_vendor(rndis->params, rndis->vendorID, Loading Loading @@ -875,6 +883,10 @@ USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, subclass); /* f_rndis_opts_protocol */ /* f_rndis_opts_protocol */ USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, protocol); USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, protocol); /* f_rndis_opts_ul_max_pkt_per_xfer */ USB_ETHER_CONFIGFS_ITEM_ATTR_UL_MAX_PKT_PER_XFER(rndis); static struct configfs_attribute *rndis_attrs[] = { static struct configfs_attribute *rndis_attrs[] = { &rndis_opts_attr_dev_addr, &rndis_opts_attr_dev_addr, &rndis_opts_attr_host_addr, &rndis_opts_attr_host_addr, Loading @@ -883,6 +895,7 @@ static struct configfs_attribute *rndis_attrs[] = { &rndis_opts_attr_class, &rndis_opts_attr_class, &rndis_opts_attr_subclass, &rndis_opts_attr_subclass, &rndis_opts_attr_protocol, &rndis_opts_attr_protocol, &rndis_opts_attr_ul_max_pkt_per_xfer, NULL, NULL, }; }; Loading Loading @@ -1004,6 +1017,8 @@ static struct usb_function *rndis_alloc(struct usb_function_instance *fi) rndis->port.header_len = sizeof(struct rndis_packet_msg_type); rndis->port.header_len = sizeof(struct rndis_packet_msg_type); rndis->port.wrap = rndis_add_header; rndis->port.wrap = rndis_add_header; rndis->port.unwrap = rndis_rm_hdr; rndis->port.unwrap = rndis_rm_hdr; if (!gether_get_ul_max_pkts_per_xfer(opts->net)) rndis->port.ul_max_pkts_per_xfer = RNDIS_UL_MAX_PKT_PER_XFER; rndis->port.func.name = "rndis"; rndis->port.func.name = "rndis"; /* descriptors are per-instance copies */ /* descriptors are per-instance copies */ Loading drivers/usb/gadget/function/rndis.c +65 −19 Original line number Original line Diff line number Diff line Loading @@ -39,7 +39,6 @@ #include "rndis.h" #include "rndis.h" /* The driver for your USB chip needs to support ep0 OUT to work with /* The driver for your USB chip needs to support ep0 OUT to work with * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional). * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional). * * Loading Loading @@ -574,12 +573,12 @@ static int rndis_init_response(struct rndis_params *params, resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION); resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION); resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS); resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS); resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3); resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3); resp->MaxPacketsPerTransfer = cpu_to_le32(1); resp->MaxPacketsPerTransfer = cpu_to_le32(params->max_pkt_per_xfer); resp->MaxTransferSize = cpu_to_le32( resp->MaxTransferSize = cpu_to_le32(params->max_pkt_per_xfer * params->dev->mtu (params->dev->mtu + sizeof(struct ethhdr) + sizeof(struct ethhdr) + sizeof(struct rndis_packet_msg_type) + sizeof(struct rndis_packet_msg_type) + 22); + 22)); resp->PacketAlignmentFactor = cpu_to_le32(0); resp->PacketAlignmentFactor = cpu_to_le32(0); resp->AFListOffset = cpu_to_le32(0); resp->AFListOffset = cpu_to_le32(0); resp->AFListSize = cpu_to_le32(0); resp->AFListSize = cpu_to_le32(0); Loading Loading @@ -993,6 +992,13 @@ int rndis_set_param_medium(struct rndis_params *params, u32 medium, u32 speed) } } EXPORT_SYMBOL_GPL(rndis_set_param_medium); EXPORT_SYMBOL_GPL(rndis_set_param_medium); void rndis_set_max_pkt_xfer(struct rndis_params *params, u8 max_pkt_per_xfer) { pr_debug("%s:\n", __func__); params->max_pkt_per_xfer = max_pkt_per_xfer; } void rndis_add_hdr(struct sk_buff *skb) void rndis_add_hdr(struct sk_buff *skb) { { struct rndis_packet_msg_type *header; struct rndis_packet_msg_type *header; Loading Loading @@ -1059,23 +1065,63 @@ int rndis_rm_hdr(struct gether *port, struct sk_buff *skb, struct sk_buff *skb, struct sk_buff_head *list) struct sk_buff_head *list) { { /* tmp points to a struct rndis_packet_msg_type */ while (skb->len) { __le32 *tmp = (void *)skb->data; struct rndis_packet_msg_type *hdr; struct sk_buff *skb2; u32 msg_len, data_offset, data_len; /* MessageType, MessageLength */ /* some rndis hosts send extra byte to avoid zlp, ignore it */ if (cpu_to_le32(RNDIS_MSG_PACKET) if (skb->len == 1) { != get_unaligned(tmp++)) { dev_kfree_skb_any(skb); return 0; } if (skb->len < sizeof(*hdr)) { pr_err("invalid rndis pkt: skblen:%u hdr_len:%lu\n", skb->len, sizeof(*hdr)); dev_kfree_skb_any(skb); dev_kfree_skb_any(skb); return -EINVAL; return -EINVAL; } } tmp++; /* DataOffset, DataLength */ hdr = (void *)skb->data; if (!skb_pull(skb, get_unaligned_le32(tmp++) + 8)) { msg_len = le32_to_cpu(hdr->MessageLength); data_offset = le32_to_cpu(hdr->DataOffset); data_len = le32_to_cpu(hdr->DataLength); if (skb->len < msg_len || ((data_offset + data_len + 8) > msg_len)) { pr_err("invalid rndis message: %d/%d/%d/%d, len:%d\n", le32_to_cpu(hdr->MessageType), msg_len, data_offset, data_len, skb->len); dev_kfree_skb_any(skb); dev_kfree_skb_any(skb); return -EOVERFLOW; return -EOVERFLOW; } } skb_trim(skb, get_unaligned_le32(tmp++)); if (le32_to_cpu(hdr->MessageType) != RNDIS_MSG_PACKET) { pr_err("invalid rndis message: %d/%d/%d/%d, len:%d\n", le32_to_cpu(hdr->MessageType), msg_len, data_offset, data_len, skb->len); dev_kfree_skb_any(skb); return -EINVAL; } skb_pull(skb, data_offset + 8); if (msg_len == skb->len) { skb_trim(skb, data_len); break; } skb2 = skb_clone(skb, GFP_ATOMIC); if (!skb2) { pr_err("%s:skb clone failed\n", __func__); dev_kfree_skb_any(skb); return -ENOMEM; } skb_pull(skb, msg_len - sizeof(*hdr)); skb_trim(skb2, data_len); skb_queue_tail(list, skb2); } skb_queue_tail(list, skb); skb_queue_tail(list, skb); return 0; return 0; Loading drivers/usb/gadget/function/rndis.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -170,6 +170,7 @@ typedef struct rndis_params { struct net_device *dev; struct net_device *dev; u32 vendorID; u32 vendorID; u8 max_pkt_per_xfer; const char *vendorDescr; const char *vendorDescr; void (*resp_avail)(void *v); void (*resp_avail)(void *v); void *v; void *v; Loading @@ -186,6 +187,7 @@ int rndis_set_param_vendor(struct rndis_params *params, u32 vendorID, const char *vendorDescr); const char *vendorDescr); int rndis_set_param_medium(struct rndis_params *params, u32 medium, int rndis_set_param_medium(struct rndis_params *params, u32 medium, u32 speed); u32 speed); void rndis_set_max_pkt_xfer(struct rndis_params *params, u8 max_pkt_per_xfer); void rndis_add_hdr(struct sk_buff *skb); void rndis_add_hdr(struct sk_buff *skb); int rndis_rm_hdr(struct gether *port, struct sk_buff *skb, int rndis_rm_hdr(struct gether *port, struct sk_buff *skb, struct sk_buff_head *list); struct sk_buff_head *list); Loading drivers/usb/gadget/function/u_ether.c +27 −0 Original line number Original line Diff line number Diff line Loading @@ -67,6 +67,7 @@ struct eth_dev { unsigned qmult; unsigned qmult; unsigned header_len; unsigned header_len; unsigned int ul_max_pkts_per_xfer; struct sk_buff *(*wrap)(struct gether *, struct sk_buff *skb); struct sk_buff *(*wrap)(struct gether *, struct sk_buff *skb); int (*unwrap)(struct gether *, int (*unwrap)(struct gether *, struct sk_buff *skb, struct sk_buff *skb, Loading Loading @@ -213,10 +214,14 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) size -= size % out->maxpacket; size -= size % out->maxpacket; } } if (dev->ul_max_pkts_per_xfer) size *= dev->ul_max_pkts_per_xfer; if (dev->port_usb->is_fixed) if (dev->port_usb->is_fixed) size = max_t(size_t, size, dev->port_usb->fixed_out_len); size = max_t(size_t, size, dev->port_usb->fixed_out_len); spin_unlock_irqrestore(&dev->lock, flags); spin_unlock_irqrestore(&dev->lock, flags); DBG(dev, "%s: size: %zd\n", __func__, size); skb = __netdev_alloc_skb(dev->net, size + NET_IP_ALIGN, gfp_flags); skb = __netdev_alloc_skb(dev->net, size + NET_IP_ALIGN, gfp_flags); if (skb == NULL) { if (skb == NULL) { DBG(dev, "no rx skb\n"); DBG(dev, "no rx skb\n"); Loading Loading @@ -1012,6 +1017,26 @@ int gether_get_ifname(struct net_device *net, char *name, int len) } } EXPORT_SYMBOL_GPL(gether_get_ifname); EXPORT_SYMBOL_GPL(gether_get_ifname); unsigned int gether_get_ul_max_pkts_per_xfer(struct net_device *net) { struct eth_dev *dev; dev = netdev_priv(net); return dev->ul_max_pkts_per_xfer; } EXPORT_SYMBOL(gether_get_ul_max_pkts_per_xfer); int gether_set_ul_max_pkts_per_xfer(struct net_device *net, unsigned int max) { struct eth_dev *dev; dev = netdev_priv(net); dev->ul_max_pkts_per_xfer = max; return 0; } EXPORT_SYMBOL(gether_set_ul_max_pkts_per_xfer); /** /** * gether_cleanup - remove Ethernet-over-USB device * gether_cleanup - remove Ethernet-over-USB device * Context: may sleep * Context: may sleep Loading Loading @@ -1081,6 +1106,8 @@ struct net_device *gether_connect(struct gether *link) dev->header_len = link->header_len; dev->header_len = link->header_len; dev->unwrap = link->unwrap; dev->unwrap = link->unwrap; dev->wrap = link->wrap; dev->wrap = link->wrap; if (!dev->ul_max_pkts_per_xfer) dev->ul_max_pkts_per_xfer = link->ul_max_pkts_per_xfer; spin_lock(&dev->lock); spin_lock(&dev->lock); dev->port_usb = link; dev->port_usb = link; Loading drivers/usb/gadget/function/u_ether.h +17 −0 Original line number Original line Diff line number Diff line Loading @@ -69,6 +69,10 @@ struct gether { bool is_fixed; bool is_fixed; u32 fixed_out_len; u32 fixed_out_len; u32 fixed_in_len; u32 fixed_in_len; unsigned int ul_max_pkts_per_xfer; /* Max number of SKB packets to be used to create Multi Packet RNDIS */ #define TX_SKB_HOLD_THRESHOLD 3 bool multi_pkt_xfer; bool supports_multi_frame; bool supports_multi_frame; struct sk_buff *(*wrap)(struct gether *port, struct sk_buff *(*wrap)(struct gether *port, struct sk_buff *skb); struct sk_buff *skb); Loading Loading @@ -244,6 +248,19 @@ unsigned gether_get_qmult(struct net_device *net); */ */ int gether_get_ifname(struct net_device *net, char *name, int len); int gether_get_ifname(struct net_device *net, char *name, int len); /** * gether_get_ul_max_pkts_per_xfer - get max pks/xfer for UL aggrregarion * @net: device representing this link */ unsigned int gether_get_ul_max_pkts_per_xfer(struct net_device *net); /** * gether_set_ul_max_pkts_per_xfer - set max pks/xfer for UL aggrregarion * @net: device representing this link * @max: max number of packets */ int gether_set_ul_max_pkts_per_xfer(struct net_device *net, unsigned int max); void gether_cleanup(struct eth_dev *dev); void gether_cleanup(struct eth_dev *dev); /* connect/disconnect is handled by individual functions */ /* connect/disconnect is handled by individual functions */ Loading Loading
drivers/usb/gadget/function/f_rndis.c +15 −0 Original line number Original line Diff line number Diff line Loading @@ -66,6 +66,8 @@ * - MS-Windows drivers sometimes emit undocumented requests. * - MS-Windows drivers sometimes emit undocumented requests. */ */ #define RNDIS_UL_MAX_PKT_PER_XFER 3 struct f_rndis { struct f_rndis { struct gether port; struct gether port; u8 ctrl_id, data_id; u8 ctrl_id, data_id; Loading Loading @@ -670,6 +672,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) struct usb_string *us; struct usb_string *us; int status; int status; struct usb_ep *ep; struct usb_ep *ep; unsigned int max; struct f_rndis_opts *rndis_opts; struct f_rndis_opts *rndis_opts; Loading Loading @@ -795,6 +798,11 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) rndis_set_param_medium(rndis->params, RNDIS_MEDIUM_802_3, 0); rndis_set_param_medium(rndis->params, RNDIS_MEDIUM_802_3, 0); rndis_set_host_mac(rndis->params, rndis->ethaddr); rndis_set_host_mac(rndis->params, rndis->ethaddr); max = gether_get_ul_max_pkts_per_xfer(rndis_opts->net); if (!max) max = RNDIS_UL_MAX_PKT_PER_XFER; rndis_set_max_pkt_xfer(rndis->params, max); if (rndis->manufacturer && rndis->vendorID && if (rndis->manufacturer && rndis->vendorID && rndis_set_param_vendor(rndis->params, rndis->vendorID, rndis_set_param_vendor(rndis->params, rndis->vendorID, Loading Loading @@ -875,6 +883,10 @@ USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, subclass); /* f_rndis_opts_protocol */ /* f_rndis_opts_protocol */ USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, protocol); USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, protocol); /* f_rndis_opts_ul_max_pkt_per_xfer */ USB_ETHER_CONFIGFS_ITEM_ATTR_UL_MAX_PKT_PER_XFER(rndis); static struct configfs_attribute *rndis_attrs[] = { static struct configfs_attribute *rndis_attrs[] = { &rndis_opts_attr_dev_addr, &rndis_opts_attr_dev_addr, &rndis_opts_attr_host_addr, &rndis_opts_attr_host_addr, Loading @@ -883,6 +895,7 @@ static struct configfs_attribute *rndis_attrs[] = { &rndis_opts_attr_class, &rndis_opts_attr_class, &rndis_opts_attr_subclass, &rndis_opts_attr_subclass, &rndis_opts_attr_protocol, &rndis_opts_attr_protocol, &rndis_opts_attr_ul_max_pkt_per_xfer, NULL, NULL, }; }; Loading Loading @@ -1004,6 +1017,8 @@ static struct usb_function *rndis_alloc(struct usb_function_instance *fi) rndis->port.header_len = sizeof(struct rndis_packet_msg_type); rndis->port.header_len = sizeof(struct rndis_packet_msg_type); rndis->port.wrap = rndis_add_header; rndis->port.wrap = rndis_add_header; rndis->port.unwrap = rndis_rm_hdr; rndis->port.unwrap = rndis_rm_hdr; if (!gether_get_ul_max_pkts_per_xfer(opts->net)) rndis->port.ul_max_pkts_per_xfer = RNDIS_UL_MAX_PKT_PER_XFER; rndis->port.func.name = "rndis"; rndis->port.func.name = "rndis"; /* descriptors are per-instance copies */ /* descriptors are per-instance copies */ Loading
drivers/usb/gadget/function/rndis.c +65 −19 Original line number Original line Diff line number Diff line Loading @@ -39,7 +39,6 @@ #include "rndis.h" #include "rndis.h" /* The driver for your USB chip needs to support ep0 OUT to work with /* The driver for your USB chip needs to support ep0 OUT to work with * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional). * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional). * * Loading Loading @@ -574,12 +573,12 @@ static int rndis_init_response(struct rndis_params *params, resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION); resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION); resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS); resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS); resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3); resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3); resp->MaxPacketsPerTransfer = cpu_to_le32(1); resp->MaxPacketsPerTransfer = cpu_to_le32(params->max_pkt_per_xfer); resp->MaxTransferSize = cpu_to_le32( resp->MaxTransferSize = cpu_to_le32(params->max_pkt_per_xfer * params->dev->mtu (params->dev->mtu + sizeof(struct ethhdr) + sizeof(struct ethhdr) + sizeof(struct rndis_packet_msg_type) + sizeof(struct rndis_packet_msg_type) + 22); + 22)); resp->PacketAlignmentFactor = cpu_to_le32(0); resp->PacketAlignmentFactor = cpu_to_le32(0); resp->AFListOffset = cpu_to_le32(0); resp->AFListOffset = cpu_to_le32(0); resp->AFListSize = cpu_to_le32(0); resp->AFListSize = cpu_to_le32(0); Loading Loading @@ -993,6 +992,13 @@ int rndis_set_param_medium(struct rndis_params *params, u32 medium, u32 speed) } } EXPORT_SYMBOL_GPL(rndis_set_param_medium); EXPORT_SYMBOL_GPL(rndis_set_param_medium); void rndis_set_max_pkt_xfer(struct rndis_params *params, u8 max_pkt_per_xfer) { pr_debug("%s:\n", __func__); params->max_pkt_per_xfer = max_pkt_per_xfer; } void rndis_add_hdr(struct sk_buff *skb) void rndis_add_hdr(struct sk_buff *skb) { { struct rndis_packet_msg_type *header; struct rndis_packet_msg_type *header; Loading Loading @@ -1059,23 +1065,63 @@ int rndis_rm_hdr(struct gether *port, struct sk_buff *skb, struct sk_buff *skb, struct sk_buff_head *list) struct sk_buff_head *list) { { /* tmp points to a struct rndis_packet_msg_type */ while (skb->len) { __le32 *tmp = (void *)skb->data; struct rndis_packet_msg_type *hdr; struct sk_buff *skb2; u32 msg_len, data_offset, data_len; /* MessageType, MessageLength */ /* some rndis hosts send extra byte to avoid zlp, ignore it */ if (cpu_to_le32(RNDIS_MSG_PACKET) if (skb->len == 1) { != get_unaligned(tmp++)) { dev_kfree_skb_any(skb); return 0; } if (skb->len < sizeof(*hdr)) { pr_err("invalid rndis pkt: skblen:%u hdr_len:%lu\n", skb->len, sizeof(*hdr)); dev_kfree_skb_any(skb); dev_kfree_skb_any(skb); return -EINVAL; return -EINVAL; } } tmp++; /* DataOffset, DataLength */ hdr = (void *)skb->data; if (!skb_pull(skb, get_unaligned_le32(tmp++) + 8)) { msg_len = le32_to_cpu(hdr->MessageLength); data_offset = le32_to_cpu(hdr->DataOffset); data_len = le32_to_cpu(hdr->DataLength); if (skb->len < msg_len || ((data_offset + data_len + 8) > msg_len)) { pr_err("invalid rndis message: %d/%d/%d/%d, len:%d\n", le32_to_cpu(hdr->MessageType), msg_len, data_offset, data_len, skb->len); dev_kfree_skb_any(skb); dev_kfree_skb_any(skb); return -EOVERFLOW; return -EOVERFLOW; } } skb_trim(skb, get_unaligned_le32(tmp++)); if (le32_to_cpu(hdr->MessageType) != RNDIS_MSG_PACKET) { pr_err("invalid rndis message: %d/%d/%d/%d, len:%d\n", le32_to_cpu(hdr->MessageType), msg_len, data_offset, data_len, skb->len); dev_kfree_skb_any(skb); return -EINVAL; } skb_pull(skb, data_offset + 8); if (msg_len == skb->len) { skb_trim(skb, data_len); break; } skb2 = skb_clone(skb, GFP_ATOMIC); if (!skb2) { pr_err("%s:skb clone failed\n", __func__); dev_kfree_skb_any(skb); return -ENOMEM; } skb_pull(skb, msg_len - sizeof(*hdr)); skb_trim(skb2, data_len); skb_queue_tail(list, skb2); } skb_queue_tail(list, skb); skb_queue_tail(list, skb); return 0; return 0; Loading
drivers/usb/gadget/function/rndis.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -170,6 +170,7 @@ typedef struct rndis_params { struct net_device *dev; struct net_device *dev; u32 vendorID; u32 vendorID; u8 max_pkt_per_xfer; const char *vendorDescr; const char *vendorDescr; void (*resp_avail)(void *v); void (*resp_avail)(void *v); void *v; void *v; Loading @@ -186,6 +187,7 @@ int rndis_set_param_vendor(struct rndis_params *params, u32 vendorID, const char *vendorDescr); const char *vendorDescr); int rndis_set_param_medium(struct rndis_params *params, u32 medium, int rndis_set_param_medium(struct rndis_params *params, u32 medium, u32 speed); u32 speed); void rndis_set_max_pkt_xfer(struct rndis_params *params, u8 max_pkt_per_xfer); void rndis_add_hdr(struct sk_buff *skb); void rndis_add_hdr(struct sk_buff *skb); int rndis_rm_hdr(struct gether *port, struct sk_buff *skb, int rndis_rm_hdr(struct gether *port, struct sk_buff *skb, struct sk_buff_head *list); struct sk_buff_head *list); Loading
drivers/usb/gadget/function/u_ether.c +27 −0 Original line number Original line Diff line number Diff line Loading @@ -67,6 +67,7 @@ struct eth_dev { unsigned qmult; unsigned qmult; unsigned header_len; unsigned header_len; unsigned int ul_max_pkts_per_xfer; struct sk_buff *(*wrap)(struct gether *, struct sk_buff *skb); struct sk_buff *(*wrap)(struct gether *, struct sk_buff *skb); int (*unwrap)(struct gether *, int (*unwrap)(struct gether *, struct sk_buff *skb, struct sk_buff *skb, Loading Loading @@ -213,10 +214,14 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) size -= size % out->maxpacket; size -= size % out->maxpacket; } } if (dev->ul_max_pkts_per_xfer) size *= dev->ul_max_pkts_per_xfer; if (dev->port_usb->is_fixed) if (dev->port_usb->is_fixed) size = max_t(size_t, size, dev->port_usb->fixed_out_len); size = max_t(size_t, size, dev->port_usb->fixed_out_len); spin_unlock_irqrestore(&dev->lock, flags); spin_unlock_irqrestore(&dev->lock, flags); DBG(dev, "%s: size: %zd\n", __func__, size); skb = __netdev_alloc_skb(dev->net, size + NET_IP_ALIGN, gfp_flags); skb = __netdev_alloc_skb(dev->net, size + NET_IP_ALIGN, gfp_flags); if (skb == NULL) { if (skb == NULL) { DBG(dev, "no rx skb\n"); DBG(dev, "no rx skb\n"); Loading Loading @@ -1012,6 +1017,26 @@ int gether_get_ifname(struct net_device *net, char *name, int len) } } EXPORT_SYMBOL_GPL(gether_get_ifname); EXPORT_SYMBOL_GPL(gether_get_ifname); unsigned int gether_get_ul_max_pkts_per_xfer(struct net_device *net) { struct eth_dev *dev; dev = netdev_priv(net); return dev->ul_max_pkts_per_xfer; } EXPORT_SYMBOL(gether_get_ul_max_pkts_per_xfer); int gether_set_ul_max_pkts_per_xfer(struct net_device *net, unsigned int max) { struct eth_dev *dev; dev = netdev_priv(net); dev->ul_max_pkts_per_xfer = max; return 0; } EXPORT_SYMBOL(gether_set_ul_max_pkts_per_xfer); /** /** * gether_cleanup - remove Ethernet-over-USB device * gether_cleanup - remove Ethernet-over-USB device * Context: may sleep * Context: may sleep Loading Loading @@ -1081,6 +1106,8 @@ struct net_device *gether_connect(struct gether *link) dev->header_len = link->header_len; dev->header_len = link->header_len; dev->unwrap = link->unwrap; dev->unwrap = link->unwrap; dev->wrap = link->wrap; dev->wrap = link->wrap; if (!dev->ul_max_pkts_per_xfer) dev->ul_max_pkts_per_xfer = link->ul_max_pkts_per_xfer; spin_lock(&dev->lock); spin_lock(&dev->lock); dev->port_usb = link; dev->port_usb = link; Loading
drivers/usb/gadget/function/u_ether.h +17 −0 Original line number Original line Diff line number Diff line Loading @@ -69,6 +69,10 @@ struct gether { bool is_fixed; bool is_fixed; u32 fixed_out_len; u32 fixed_out_len; u32 fixed_in_len; u32 fixed_in_len; unsigned int ul_max_pkts_per_xfer; /* Max number of SKB packets to be used to create Multi Packet RNDIS */ #define TX_SKB_HOLD_THRESHOLD 3 bool multi_pkt_xfer; bool supports_multi_frame; bool supports_multi_frame; struct sk_buff *(*wrap)(struct gether *port, struct sk_buff *(*wrap)(struct gether *port, struct sk_buff *skb); struct sk_buff *skb); Loading Loading @@ -244,6 +248,19 @@ unsigned gether_get_qmult(struct net_device *net); */ */ int gether_get_ifname(struct net_device *net, char *name, int len); int gether_get_ifname(struct net_device *net, char *name, int len); /** * gether_get_ul_max_pkts_per_xfer - get max pks/xfer for UL aggrregarion * @net: device representing this link */ unsigned int gether_get_ul_max_pkts_per_xfer(struct net_device *net); /** * gether_set_ul_max_pkts_per_xfer - set max pks/xfer for UL aggrregarion * @net: device representing this link * @max: max number of packets */ int gether_set_ul_max_pkts_per_xfer(struct net_device *net, unsigned int max); void gether_cleanup(struct eth_dev *dev); void gether_cleanup(struct eth_dev *dev); /* connect/disconnect is handled by individual functions */ /* connect/disconnect is handled by individual functions */ Loading