Revert "Revert "(CR):f_usbnet:Handle the rx error conditions""
This reverts commit e8fa083c2ddc3f6bba3655f19c606efdbb91654d. After fixed the factory connection issue after factory-kill disabled Reapply the stability improvement patch Mot-CRs-Fixed:(CR) Change-Id: Ica5a371f2e30cc97d2e4de0ce22467ab89edb2af Signed-off-by: William Liu <a17671@motorola.com> Reviewed-on: https://gerrit.mot.com/2399176 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yuecai Liu <liuyc20@motorola.com> Reviewed-by: Yonghua Yan <yanyh2@motorola.com> Reviewed-by: Yeqing Wang <wangyq13@motorola.com> Reviewed-by: Xiangpo Zhao <zhaoxp3@motorola.com> Submit-Approved: Jira Key
This commit is contained in:
1 parent
3489d559a2
commit
0d35abcfbf
1 file changed
+83
-20
@@ -50,11 +50,14 @@
|
||||
|
||||
/* Linux Network Interface */
|
||||
#define USB_MTU 15360
|
||||
#define CURRENT_MTU 15000
|
||||
#define MAX_BULK_TX_REQ_NUM 80
|
||||
#define MAX_BULK_RX_REQ_NUM 80
|
||||
#define MAX_INTR_RX_REQ_NUM 80
|
||||
#define INTERFACE_STRING_INDEX 0
|
||||
|
||||
#define WORK_RX_MEMORY 0
|
||||
|
||||
struct usbnet_context {
|
||||
spinlock_t lock; /* For RX/TX list */
|
||||
struct net_device *dev;
|
||||
@@ -76,6 +79,8 @@ struct usbnet_context {
|
||||
u32 router_ip;
|
||||
u32 iff_flag;
|
||||
struct socket *socket;
|
||||
struct work_struct work;
|
||||
unsigned long todo;
|
||||
};
|
||||
|
||||
|
||||
@@ -252,6 +257,46 @@ static struct usb_descriptor_header *ss_function[] = {
|
||||
|
||||
static const char *usb_description = "Motorola BLAN Interface";
|
||||
|
||||
static int ether_queue_out(struct usb_request *req ,
|
||||
struct usbnet_context *context);
|
||||
struct usb_request *usb_get_recv_request(struct usbnet_context *context);
|
||||
static void defer_kevent(struct usbnet_context *context, int flag);
|
||||
static void eth_work(struct work_struct *work);
|
||||
static void rx_fill(struct usbnet_context *context)
|
||||
{
|
||||
struct usb_request *req;
|
||||
|
||||
/* fill unused rxq slots with some skb */
|
||||
while ((req = usb_get_recv_request(context))) {
|
||||
if (ether_queue_out(req,context) < 0) {
|
||||
defer_kevent(context, WORK_RX_MEMORY);
|
||||
USBNETDBG(context,"rx_fill failed, defer_kevent\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void eth_work(struct work_struct *work)
|
||||
{
|
||||
struct usbnet_context *context;
|
||||
|
||||
context= container_of(work, struct usbnet_context, work);
|
||||
if (test_and_clear_bit(WORK_RX_MEMORY, &context->todo)) {
|
||||
if (netif_running(context->dev))
|
||||
rx_fill(context);
|
||||
}
|
||||
if (context->todo)
|
||||
USBNETDBG(context,"work done, flags = 0x%lx\n", context->todo);
|
||||
}
|
||||
|
||||
static void defer_kevent(struct usbnet_context *context, int flag)
|
||||
{
|
||||
if (test_and_set_bit(flag, &context->todo))
|
||||
return;
|
||||
if (!schedule_work(&context->work))
|
||||
USBNETDBG(context, "kevent %d may have been dropped\n", flag);
|
||||
USBNETDBG(context, "kevent %d schedule done\n", flag);
|
||||
}
|
||||
static ssize_t usbnet_desc_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buff)
|
||||
{
|
||||
@@ -349,9 +394,16 @@ static int ether_queue_out(struct usb_request *req ,
|
||||
ret = usb_ep_queue(context->bulk_out, req, GFP_KERNEL);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
else
|
||||
kfree_skb(skb);
|
||||
if (ret == -ENOMEM){
|
||||
USBNETDBG(context, "%s: failed to enqueue nomem\n", __func__);
|
||||
fail:
|
||||
defer_kevent(context, WORK_RX_MEMORY);
|
||||
}
|
||||
if (ret) {
|
||||
USBNETDBG(context, "ether_queue_out --> %d\n", ret);
|
||||
if (skb)
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
spin_lock_irqsave(&context->lock, flags);
|
||||
list_add_tail(&req->list, &context->rx_reqs);
|
||||
spin_unlock_irqrestore(&context->lock, flags);
|
||||
@@ -577,6 +629,7 @@ static void usbnet_cleanup(struct usbnet_device *dev)
|
||||
if (context) {
|
||||
device_remove_file(&(context->dev->dev), &dev_attr_description);
|
||||
unregister_netdev(context->dev);
|
||||
flush_work(&context->work);
|
||||
free_netdev(context->dev);
|
||||
dev->net_ctxt = NULL;
|
||||
}
|
||||
@@ -620,13 +673,28 @@ static void ether_out_complete(struct usb_ep *ep, struct usb_request *req)
|
||||
{
|
||||
struct sk_buff *skb = req->context;
|
||||
struct usbnet_context *context = ep->driver_data;
|
||||
struct net_device *net_dev = context->dev;
|
||||
int status;
|
||||
|
||||
if (req->status == 0) {
|
||||
skb_put(skb, req->actual);
|
||||
skb->protocol = eth_type_trans(skb, context->dev);
|
||||
context->stats.rx_packets++;
|
||||
context->stats.rx_bytes += req->actual;
|
||||
netif_rx(skb);
|
||||
if( ETH_HLEN > skb->len
|
||||
|| skb->len > CURRENT_MTU) {
|
||||
USBNETDBG(context, "rx length not right %d\n", skb->len);
|
||||
context->stats.rx_errors++;
|
||||
dev_kfree_skb_any(skb);
|
||||
} else {
|
||||
status = netif_rx(skb);
|
||||
if (status < 0) {
|
||||
USBNETDBG(context, "netif_rx failed %d\n", status);
|
||||
context->stats.rx_errors++;
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
dev_kfree_skb_any(skb);
|
||||
context->stats.rx_errors++;
|
||||
@@ -635,10 +703,15 @@ static void ether_out_complete(struct usb_ep *ep, struct usb_request *req)
|
||||
/* don't bother requeuing if we just went offline */
|
||||
if ((req->status == -ENODEV) || (req->status == -ESHUTDOWN)) {
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&context->lock, flags);
|
||||
list_add_tail(&req->list, &context->rx_reqs);
|
||||
spin_unlock_irqrestore(&context->lock, flags);
|
||||
} else {
|
||||
if(!netif_running(net_dev)){
|
||||
spin_lock_irqsave(&context->lock, flags);
|
||||
list_add_tail(&req->list, &context->rx_reqs);
|
||||
spin_unlock_irqrestore(&context->lock, flags);
|
||||
}
|
||||
} else if (req->status == -ECONNABORTED){ /* endpoint reset */
|
||||
USBNETDBG(context,"rx %s reset\n", ep->name);
|
||||
defer_kevent(context, WORK_RX_MEMORY);
|
||||
}else {
|
||||
if (ether_queue_out(req, context))
|
||||
USBNETDBG(context, "ether_out: cannot requeue\n");
|
||||
}
|
||||
@@ -786,7 +859,6 @@ static void do_set_config(struct usb_function *f, u16 new_config)
|
||||
struct usbnet_context *context = dev->net_ctxt;
|
||||
struct usb_composite_dev *cdev = f->config->cdev;
|
||||
int result = 0;
|
||||
struct usb_request *req;
|
||||
|
||||
USBNETDBG(context, "do_set_config ep %s\n",
|
||||
context->bulk_in->name);
|
||||
@@ -850,17 +922,7 @@ static void do_set_config(struct usb_function *f, u16 new_config)
|
||||
}
|
||||
|
||||
context->intr_out->driver_data = context;
|
||||
|
||||
/* we're online -- get all rx requests queued */
|
||||
while ((req = usb_get_recv_request(context))) {
|
||||
if (ether_queue_out(req, context)) {
|
||||
USBNETDBG(context,
|
||||
"%s: ether_queue_out failed\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rx_fill(context);
|
||||
} else {/* Disable Endpoints */
|
||||
if (context->bulk_in)
|
||||
usb_ep_disable(context->bulk_in);
|
||||
@@ -1093,7 +1155,7 @@ static struct usb_function_instance *usbnet_alloc_inst(void)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
net_dev->mtu = 15000;
|
||||
net_dev->mtu = CURRENT_MTU;
|
||||
ret = register_netdev(net_dev);
|
||||
if (ret) {
|
||||
pr_err("%s: register_netdev error\n", __func__);
|
||||
@@ -1128,6 +1190,7 @@ static struct usb_function_instance *usbnet_alloc_inst(void)
|
||||
context->socket->sk->sk_user_data = context;
|
||||
|
||||
INIT_WORK(&context->usbnet_config_wq, usbnet_if_config);
|
||||
INIT_WORK(&context->work, eth_work);
|
||||
context->config = 0;
|
||||
dev->net_ctxt = context;
|
||||
spin_lock_init(&context->lock);
|
||||
|
||||
Reference in new issue
Block a user