Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(420)

Side by Side Diff: drivers/net/usb/gobi/qcusbnet.c

Issue 6913008: CHROMIUM: gobi: Remove worker.exit hack. (Closed) Base URL: ssh://gitrw.chromium.org:9222/kernel.git@0.12.433.B
Patch Set: Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | drivers/net/usb/gobi/structs.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* qcusbnet.c - gobi network device 1 /* qcusbnet.c - gobi network device
2 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. 2 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
3 3
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and 5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation. 6 * only version 2 as published by the Free Software Foundation.
7 7
8 * This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 if (entry == key) { 61 if (entry == key) {
62 kref_get(&entry->refcount); 62 kref_get(&entry->refcount);
63 mutex_unlock(&qcusbnet_lock); 63 mutex_unlock(&qcusbnet_lock);
64 return entry; 64 return entry;
65 } 65 }
66 } 66 }
67 mutex_unlock(&qcusbnet_lock); 67 mutex_unlock(&qcusbnet_lock);
68 return NULL; 68 return NULL;
69 } 69 }
70 70
71 static void wake_worker(struct worker *worker)
72 {
73 atomic_inc(&worker->work_count);
74 wake_up(&worker->waitq);
75 }
76
71 int qc_suspend(struct usb_interface *iface, pm_message_t event) 77 int qc_suspend(struct usb_interface *iface, pm_message_t event)
72 { 78 {
73 struct usbnet *usbnet; 79 struct usbnet *usbnet;
74 struct qcusbnet *dev; 80 struct qcusbnet *dev;
75 81
76 if (!iface) 82 if (!iface)
77 return -ENOMEM; 83 return -ENOMEM;
78 84
79 usbnet = usb_get_intfdata(iface); 85 usbnet = usb_get_intfdata(iface);
80 86
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 DBG("usbnet_resume error %d\n", ret); 149 DBG("usbnet_resume error %d\n", ret);
144 return ret; 150 return ret;
145 } 151 }
146 152
147 ret = qc_startread(dev); 153 ret = qc_startread(dev);
148 if (ret) { 154 if (ret) {
149 DBG("qc_startread error %d\n", ret); 155 DBG("qc_startread error %d\n", ret);
150 return ret; 156 return ret;
151 } 157 }
152 158
153 » » complete(&dev->worker.work); 159 » » wake_worker(&dev->worker);
154 } else { 160 } else {
155 DBG("nothing to resume\n"); 161 DBG("nothing to resume\n");
156 return 0; 162 return 0;
157 } 163 }
158 164
159 return ret; 165 return ret;
160 } 166 }
161 167
162 static int qcnet_bind(struct usbnet *usbnet, struct usb_interface *iface) 168 static int qcnet_bind(struct usbnet *usbnet, struct usb_interface *iface)
163 { 169 {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 } 245 }
240 246
241 if (urb->status) { 247 if (urb->status) {
242 DBG("urb finished with error %d\n", urb->status); 248 DBG("urb finished with error %d\n", urb->status);
243 } 249 }
244 250
245 spin_lock_irqsave(&worker->active_lock, flags); 251 spin_lock_irqsave(&worker->active_lock, flags);
246 worker->active = ERR_PTR(-EAGAIN); 252 worker->active = ERR_PTR(-EAGAIN);
247 spin_unlock_irqrestore(&worker->active_lock, flags); 253 spin_unlock_irqrestore(&worker->active_lock, flags);
248 /* XXX-fix race against qcnet_stop()? */ 254 /* XXX-fix race against qcnet_stop()? */
249 » complete(&worker->work); 255 » wake_worker(worker);
250 usb_free_urb(urb); 256 usb_free_urb(urb);
251 } 257 }
252 258
253 static void qcnet_txtimeout(struct net_device *netdev) 259 static void qcnet_txtimeout(struct net_device *netdev)
254 { 260 {
255 struct list_head *node, *tmp; 261 struct list_head *node, *tmp;
256 struct qcusbnet *dev; 262 struct qcusbnet *dev;
257 struct worker *worker; 263 struct worker *worker;
258 struct urbreq *req; 264 struct urbreq *req;
259 unsigned long activeflags, listflags; 265 unsigned long activeflags, listflags;
(...skipping 20 matching lines...) Expand all
280 286
281 spin_lock_irqsave(&worker->urbs_lock, listflags); 287 spin_lock_irqsave(&worker->urbs_lock, listflags);
282 list_for_each_safe(node, tmp, &worker->urbs) { 288 list_for_each_safe(node, tmp, &worker->urbs) {
283 req = list_entry(node, struct urbreq, node); 289 req = list_entry(node, struct urbreq, node);
284 usb_free_urb(req->urb); 290 usb_free_urb(req->urb);
285 list_del(&req->node); 291 list_del(&req->node);
286 kfree(req); 292 kfree(req);
287 } 293 }
288 spin_unlock_irqrestore(&worker->urbs_lock, listflags); 294 spin_unlock_irqrestore(&worker->urbs_lock, listflags);
289 295
290 » complete(&worker->work); 296 » wake_worker(worker);
297 }
298
299 static int worker_should_wake(struct worker *worker)
300 {
301 » if (kthread_should_stop())
302 » » return 1;
303 » /* This is safe only because we are the only place that decrements this
304 » * counter. */
305 » if (atomic_read(&worker->work_count))
306 » » return 1;
307 » return 0;
291 } 308 }
292 309
293 static int qcnet_worker(void *arg) 310 static int qcnet_worker(void *arg)
294 { 311 {
295 struct list_head *node, *tmp; 312 struct list_head *node, *tmp;
296 unsigned long activeflags, listflags; 313 unsigned long activeflags, listflags;
297 struct urbreq *req; 314 struct urbreq *req;
298 int status; 315 int status;
299 struct usb_device *usbdev; 316 struct usb_device *usbdev;
300 struct worker *worker = arg; 317 struct worker *worker = arg;
301 if (!worker) { 318 if (!worker) {
302 DBG("passed null pointer\n"); 319 DBG("passed null pointer\n");
303 return -EINVAL; 320 return -EINVAL;
304 } 321 }
305 322
306 usbdev = interface_to_usbdev(worker->iface); 323 usbdev = interface_to_usbdev(worker->iface);
307 324
308 DBG("traffic thread started\n"); 325 DBG("traffic thread started\n");
309 326
310 » while (!worker->exit && !kthread_should_stop()) { 327 » while (!kthread_should_stop()) {
311 » » wait_for_completion_interruptible(&worker->work); 328 » » wait_event(worker->waitq, worker_should_wake(worker));
312 329
313 » » if (worker->exit || kthread_should_stop()) { 330 » » if (kthread_should_stop())
314 » » » spin_lock_irqsave(&worker->active_lock, activeflags);
315 » » » if (worker->active) {
316 » » » » usb_kill_urb(worker->active);
317 » » » }
318 » » » spin_unlock_irqrestore(&worker->active_lock, activeflags );
319
320 » » » spin_lock_irqsave(&worker->urbs_lock, listflags);
321 » » » list_for_each_safe(node, tmp, &worker->urbs) {
322 » » » » req = list_entry(node, struct urbreq, node);
323 » » » » usb_free_urb(req->urb);
324 » » » » list_del(&req->node);
325 » » » » kfree(req);
326 » » » }
327 » » » spin_unlock_irqrestore(&worker->urbs_lock, listflags);
328
329 break; 331 break;
330 » » } 332 » » atomic_dec(&worker->work_count);
331 333
332 spin_lock_irqsave(&worker->active_lock, activeflags); 334 spin_lock_irqsave(&worker->active_lock, activeflags);
333 if (IS_ERR(worker->active) && PTR_ERR(worker->active) == -EAGAIN ) { 335 if (IS_ERR(worker->active) && PTR_ERR(worker->active) == -EAGAIN ) {
334 worker->active = NULL; 336 worker->active = NULL;
335 spin_unlock_irqrestore(&worker->active_lock, activeflags ); 337 spin_unlock_irqrestore(&worker->active_lock, activeflags );
336 usb_autopm_put_interface(worker->iface); 338 usb_autopm_put_interface(worker->iface);
337 spin_lock_irqsave(&worker->active_lock, activeflags); 339 spin_lock_irqsave(&worker->active_lock, activeflags);
338 } 340 }
339 341
340 if (worker->active) { 342 if (worker->active) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 } 377 }
376 378
377 status = usb_submit_urb(worker->active, GFP_KERNEL); 379 status = usb_submit_urb(worker->active, GFP_KERNEL);
378 if (status < 0) { 380 if (status < 0) {
379 DBG("Failed to submit URB: %d. Packet dropped\n", statu s); 381 DBG("Failed to submit URB: %d. Packet dropped\n", statu s);
380 spin_lock_irqsave(&worker->active_lock, activeflags); 382 spin_lock_irqsave(&worker->active_lock, activeflags);
381 usb_free_urb(worker->active); 383 usb_free_urb(worker->active);
382 worker->active = NULL; 384 worker->active = NULL;
383 spin_unlock_irqrestore(&worker->active_lock, activeflags ); 385 spin_unlock_irqrestore(&worker->active_lock, activeflags );
384 usb_autopm_put_interface(worker->iface); 386 usb_autopm_put_interface(worker->iface);
385 » » » complete(&worker->work); 387 » » » wake_worker(worker);
386 } 388 }
387 389
388 kfree(req); 390 kfree(req);
389 } 391 }
390 392
393 spin_lock_irqsave(&worker->active_lock, activeflags);
394 if (worker->active) {
395 usb_kill_urb(worker->active);
396 }
397 spin_unlock_irqrestore(&worker->active_lock, activeflags);
398
399 spin_lock_irqsave(&worker->urbs_lock, listflags);
400 list_for_each_safe(node, tmp, &worker->urbs) {
401 req = list_entry(node, struct urbreq, node);
402 usb_free_urb(req->urb);
403 list_del(&req->node);
404 kfree(req);
405 }
406 spin_unlock_irqrestore(&worker->urbs_lock, listflags);
407
391 DBG("traffic thread exiting\n"); 408 DBG("traffic thread exiting\n");
392 worker->thread = NULL; 409 worker->thread = NULL;
393 return 0; 410 return 0;
394 } 411 }
395 412
396 static int qcnet_startxmit(struct sk_buff *skb, struct net_device *netdev) 413 static int qcnet_startxmit(struct sk_buff *skb, struct net_device *netdev)
397 { 414 {
398 unsigned long listflags; 415 unsigned long listflags;
399 struct qcusbnet *dev; 416 struct qcusbnet *dev;
400 struct worker *worker; 417 struct worker *worker;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 } 462 }
446 memcpy(data, skb->data, skb->len); 463 memcpy(data, skb->data, skb->len);
447 464
448 usb_fill_bulk_urb(req->urb, dev->usbnet->udev, dev->usbnet->out, 465 usb_fill_bulk_urb(req->urb, dev->usbnet->udev, dev->usbnet->out,
449 data, skb->len, qcnet_urbhook, worker); 466 data, skb->len, qcnet_urbhook, worker);
450 467
451 spin_lock_irqsave(&worker->urbs_lock, listflags); 468 spin_lock_irqsave(&worker->urbs_lock, listflags);
452 list_add_tail(&req->node, &worker->urbs); 469 list_add_tail(&req->node, &worker->urbs);
453 spin_unlock_irqrestore(&worker->urbs_lock, listflags); 470 spin_unlock_irqrestore(&worker->urbs_lock, listflags);
454 471
455 » complete(&worker->work); 472 » wake_worker(worker);
456 473
457 netdev->trans_start = jiffies; 474 netdev->trans_start = jiffies;
458 dev_kfree_skb_any(skb); 475 dev_kfree_skb_any(skb);
459 476
460 return NETDEV_TX_OK; 477 return NETDEV_TX_OK;
461 } 478 }
462 479
463 static int qcnet_open(struct net_device *netdev) 480 static int qcnet_open(struct net_device *netdev)
464 { 481 {
465 int status = 0; 482 int status = 0;
(...skipping 11 matching lines...) Expand all
477 return -ENXIO; 494 return -ENXIO;
478 } 495 }
479 496
480 DBG("\n"); 497 DBG("\n");
481 498
482 dev->worker.iface = dev->iface; 499 dev->worker.iface = dev->iface;
483 INIT_LIST_HEAD(&dev->worker.urbs); 500 INIT_LIST_HEAD(&dev->worker.urbs);
484 dev->worker.active = NULL; 501 dev->worker.active = NULL;
485 spin_lock_init(&dev->worker.urbs_lock); 502 spin_lock_init(&dev->worker.urbs_lock);
486 spin_lock_init(&dev->worker.active_lock); 503 spin_lock_init(&dev->worker.active_lock);
487 » init_completion(&dev->worker.work); 504 » atomic_set(&dev->worker.work_count, 0);
505 » init_waitqueue_head(&dev->worker.waitq);
488 506
489 dev->worker.exit = 0;
490 dev->worker.thread = kthread_run(qcnet_worker, &dev->worker, "qcnet_work er"); 507 dev->worker.thread = kthread_run(qcnet_worker, &dev->worker, "qcnet_work er");
491 if (IS_ERR(dev->worker.thread)) { 508 if (IS_ERR(dev->worker.thread)) {
492 DBG("AutoPM thread creation error\n"); 509 DBG("AutoPM thread creation error\n");
493 return PTR_ERR(dev->worker.thread); 510 return PTR_ERR(dev->worker.thread);
494 } 511 }
495 512
496 qc_cleardown(dev, DOWN_NET_IFACE_STOPPED); 513 qc_cleardown(dev, DOWN_NET_IFACE_STOPPED);
497 if (dev->open) { 514 if (dev->open) {
498 status = dev->open(netdev); 515 status = dev->open(netdev);
499 if (status == 0) { 516 if (status == 0) {
(...skipping 16 matching lines...) Expand all
516 return -ENXIO; 533 return -ENXIO;
517 } 534 }
518 535
519 dev = (struct qcusbnet *)usbnet->data[0]; 536 dev = (struct qcusbnet *)usbnet->data[0];
520 if (!dev) { 537 if (!dev) {
521 DBG("failed to get QMIDevice\n"); 538 DBG("failed to get QMIDevice\n");
522 return -ENXIO; 539 return -ENXIO;
523 } 540 }
524 541
525 qc_setdown(dev, DOWN_NET_IFACE_STOPPED); 542 qc_setdown(dev, DOWN_NET_IFACE_STOPPED);
526 dev->worker.exit = 1;
527 complete(&dev->worker.work);
528 kthread_stop(dev->worker.thread); 543 kthread_stop(dev->worker.thread);
529 DBG("thread stopped\n"); 544 DBG("thread stopped\n");
530 545
531 if (dev->stop != NULL) 546 if (dev->stop != NULL)
532 return dev->stop(netdev); 547 return dev->stop(netdev);
533 return 0; 548 return 0;
534 } 549 }
535 550
536 static const struct driver_info qc_netinfo = { 551 static const struct driver_info qc_netinfo = {
537 .description = "QCUSBNet Ethernet Device", 552 .description = "QCUSBNet Ethernet Device",
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 memset(&(dev->meid), '0', 14); 661 memset(&(dev->meid), '0', 14);
647 662
648 dev->valid = false; 663 dev->valid = false;
649 memset(&dev->qmi, 0, sizeof(dev->qmi)); 664 memset(&dev->qmi, 0, sizeof(dev->qmi));
650 665
651 dev->qmi.devclass = devclass; 666 dev->qmi.devclass = devclass;
652 667
653 kref_init(&dev->refcount); 668 kref_init(&dev->refcount);
654 INIT_LIST_HEAD(&dev->node); 669 INIT_LIST_HEAD(&dev->node);
655 INIT_LIST_HEAD(&dev->qmi.clients); 670 INIT_LIST_HEAD(&dev->qmi.clients);
656 » init_completion(&dev->worker.work); 671 » atomic_set(&dev->worker.work_count, 0);
672 » init_waitqueue_head(&dev->worker.waitq);
657 spin_lock_init(&dev->qmi.clients_lock); 673 spin_lock_init(&dev->qmi.clients_lock);
658 674
659 dev->down = 0; 675 dev->down = 0;
660 qc_setdown(dev, DOWN_NO_NDIS_CONNECTION); 676 qc_setdown(dev, DOWN_NO_NDIS_CONNECTION);
661 qc_setdown(dev, DOWN_NET_IFACE_STOPPED); 677 qc_setdown(dev, DOWN_NET_IFACE_STOPPED);
662 678
663 status = qc_register(dev); 679 status = qc_register(dev);
664 if (status) { 680 if (status) {
665 qc_deregister(dev); 681 qc_deregister(dev);
666 } else { 682 } else {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 } 726 }
711 module_exit(modexit); 727 module_exit(modexit);
712 728
713 MODULE_VERSION(DRIVER_VERSION); 729 MODULE_VERSION(DRIVER_VERSION);
714 MODULE_AUTHOR(DRIVER_AUTHOR); 730 MODULE_AUTHOR(DRIVER_AUTHOR);
715 MODULE_DESCRIPTION(DRIVER_DESC); 731 MODULE_DESCRIPTION(DRIVER_DESC);
716 MODULE_LICENSE("Dual BSD/GPL"); 732 MODULE_LICENSE("Dual BSD/GPL");
717 733
718 module_param(qcusbnet_debug, bool, S_IRUGO | S_IWUSR); 734 module_param(qcusbnet_debug, bool, S_IRUGO | S_IWUSR);
719 MODULE_PARM_DESC(qcusbnet_debug, "Debugging enabled or not"); 735 MODULE_PARM_DESC(qcusbnet_debug, "Debugging enabled or not");
OLDNEW
« no previous file with comments | « no previous file | drivers/net/usb/gobi/structs.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698