aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/gigaset/usb-gigaset.c
diff options
context:
space:
mode:
authorTilman Schmidt <tilman@imap.cc>2006-04-11 01:55:16 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-11 09:18:50 -0400
commit69049cc87dccb1e6fb54aa25c63033efac805dbd (patch)
tree9db1953a831091335b98f8749865f4c8b410ff9b /drivers/isdn/gigaset/usb-gigaset.c
parent27d1ac2ef7d0b9250ca9fd2ef506e12866ce8fdf (diff)
[PATCH] isdn4linux: Siemens Gigaset drivers: make some variables non-atomic
With Hansjoerg Lipp <hjlipp@web.de> Replace some atomic_t variables in the Gigaset drivers by non-atomic ones, using spinlocks instead to assure atomicity, as proposed in discussions on the linux-kernel mailing list. Signed-off-by: Hansjoerg Lipp <hjlipp@web.de> Signed-off-by: Tilman Schmidt <tilman@imap.cc> Cc: Karsten Keil <kkeil@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/isdn/gigaset/usb-gigaset.c')
-rw-r--r--drivers/isdn/gigaset/usb-gigaset.c86
1 files changed, 52 insertions, 34 deletions
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index fe8435b8fa97..bfb73fd5077e 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -371,13 +371,14 @@ static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs)
371 int r; 371 int r;
372 unsigned numbytes; 372 unsigned numbytes;
373 unsigned char *src; 373 unsigned char *src;
374 374 unsigned long flags;
375 if (!atomic_read(&cs->connected)) {
376 err("%s: disconnected", __func__);
377 return;
378 }
379 375
380 if (!urb->status) { 376 if (!urb->status) {
377 if (!cs->connected) {
378 err("%s: disconnected", __func__); /* should never happen */
379 return;
380 }
381
381 numbytes = urb->actual_length; 382 numbytes = urb->actual_length;
382 383
383 if (numbytes) { 384 if (numbytes) {
@@ -399,12 +400,19 @@ static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs)
399 /* The urb might have been killed. */ 400 /* The urb might have been killed. */
400 gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d", 401 gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d",
401 __func__, urb->status); 402 __func__, urb->status);
402 if (urb->status != -ENOENT) /* not killed */ 403 if (urb->status != -ENOENT) { /* not killed */
404 if (!cs->connected) {
405 err("%s: disconnected", __func__); /* should never happen */
406 return;
407 }
403 resubmit = 1; 408 resubmit = 1;
409 }
404 } 410 }
405 411
406 if (resubmit) { 412 if (resubmit) {
407 r = usb_submit_urb(urb, SLAB_ATOMIC); 413 spin_lock_irqsave(&cs->lock, flags);
414 r = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV;
415 spin_unlock_irqrestore(&cs->lock, flags);
408 if (r) 416 if (r)
409 dev_err(cs->dev, "error %d when resubmitting urb.\n", 417 dev_err(cs->dev, "error %d when resubmitting urb.\n",
410 -r); 418 -r);
@@ -416,21 +424,22 @@ static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs)
416static void gigaset_write_bulk_callback(struct urb *urb, struct pt_regs *regs) 424static void gigaset_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
417{ 425{
418 struct cardstate *cs = urb->context; 426 struct cardstate *cs = urb->context;
427 unsigned long flags;
419 428
420#ifdef CONFIG_GIGASET_DEBUG
421 if (!atomic_read(&cs->connected)) {
422 err("%s: not connected", __func__);
423 return;
424 }
425#endif
426 if (urb->status) 429 if (urb->status)
427 dev_err(cs->dev, "bulk transfer failed (status %d)\n", 430 dev_err(cs->dev, "bulk transfer failed (status %d)\n",
428 -urb->status); 431 -urb->status);
429 /* That's all we can do. Communication problems 432 /* That's all we can do. Communication problems
430 are handled by timeouts or network protocols. */ 433 are handled by timeouts or network protocols. */
431 434
432 atomic_set(&cs->hw.usb->busy, 0); 435 spin_lock_irqsave(&cs->lock, flags);
433 tasklet_schedule(&cs->write_tasklet); 436 if (!cs->connected) {
437 err("%s: not connected", __func__);
438 } else {
439 atomic_set(&cs->hw.usb->busy, 0);
440 tasklet_schedule(&cs->write_tasklet);
441 }
442 spin_unlock_irqrestore(&cs->lock, flags);
434} 443}
435 444
436static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) 445static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
@@ -465,6 +474,8 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
465 } 474 }
466 if (cb) { 475 if (cb) {
467 count = min(cb->len, ucs->bulk_out_size); 476 count = min(cb->len, ucs->bulk_out_size);
477 gig_dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count);
478
468 usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, 479 usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
469 usb_sndbulkpipe(ucs->udev, 480 usb_sndbulkpipe(ucs->udev,
470 ucs->bulk_out_endpointAddr & 0x0f), 481 ucs->bulk_out_endpointAddr & 0x0f),
@@ -474,14 +485,15 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
474 cb->offset += count; 485 cb->offset += count;
475 cb->len -= count; 486 cb->len -= count;
476 atomic_set(&ucs->busy, 1); 487 atomic_set(&ucs->busy, 1);
477 gig_dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count);
478 488
479 status = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC); 489 spin_lock_irqsave(&cs->lock, flags);
490 status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC) : -ENODEV;
491 spin_unlock_irqrestore(&cs->lock, flags);
492
480 if (status) { 493 if (status) {
481 atomic_set(&ucs->busy, 0); 494 atomic_set(&ucs->busy, 0);
482 dev_err(cs->dev, 495 err("could not submit urb (error %d)\n",
483 "could not submit urb (error %d)\n", 496 -status);
484 -status);
485 cb->len = 0; /* skip urb => remove cb+wakeup 497 cb->len = 0; /* skip urb => remove cb+wakeup
486 in next loop cycle */ 498 in next loop cycle */
487 } 499 }
@@ -502,11 +514,6 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
502 DEBUG_TRANSCMD : DEBUG_LOCKCMD, 514 DEBUG_TRANSCMD : DEBUG_LOCKCMD,
503 "CMD Transmit", len, buf); 515 "CMD Transmit", len, buf);
504 516
505 if (!atomic_read(&cs->connected)) {
506 err("%s: not connected", __func__);
507 return -ENODEV;
508 }
509
510 if (len <= 0) 517 if (len <= 0)
511 return 0; 518 return 0;
512 519
@@ -533,7 +540,10 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
533 cs->lastcmdbuf = cb; 540 cs->lastcmdbuf = cb;
534 spin_unlock_irqrestore(&cs->cmdlock, flags); 541 spin_unlock_irqrestore(&cs->cmdlock, flags);
535 542
536 tasklet_schedule(&cs->write_tasklet); 543 spin_lock_irqsave(&cs->lock, flags);
544 if (cs->connected)
545 tasklet_schedule(&cs->write_tasklet);
546 spin_unlock_irqrestore(&cs->lock, flags);
537 return len; 547 return len;
538} 548}
539 549
@@ -629,6 +639,7 @@ static int write_modem(struct cardstate *cs)
629 int count; 639 int count;
630 struct bc_state *bcs = &cs->bcs[0]; /* only one channel */ 640 struct bc_state *bcs = &cs->bcs[0]; /* only one channel */
631 struct usb_cardstate *ucs = cs->hw.usb; 641 struct usb_cardstate *ucs = cs->hw.usb;
642 unsigned long flags;
632 643
633 gig_dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len); 644 gig_dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len);
634 645
@@ -644,20 +655,27 @@ static int write_modem(struct cardstate *cs)
644 count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); 655 count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size);
645 memcpy(ucs->bulk_out_buffer, bcs->tx_skb->data, count); 656 memcpy(ucs->bulk_out_buffer, bcs->tx_skb->data, count);
646 skb_pull(bcs->tx_skb, count); 657 skb_pull(bcs->tx_skb, count);
647
648 usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
649 usb_sndbulkpipe(ucs->udev,
650 ucs->bulk_out_endpointAddr & 0x0f),
651 ucs->bulk_out_buffer, count,
652 gigaset_write_bulk_callback, cs);
653 atomic_set(&ucs->busy, 1); 658 atomic_set(&ucs->busy, 1);
654 gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); 659 gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count);
655 660
656 ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC); 661 spin_lock_irqsave(&cs->lock, flags);
662 if (cs->connected) {
663 usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
664 usb_sndbulkpipe(ucs->udev,
665 ucs->bulk_out_endpointAddr & 0x0f),
666 ucs->bulk_out_buffer, count,
667 gigaset_write_bulk_callback, cs);
668 ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC);
669 } else {
670 ret = -ENODEV;
671 }
672 spin_unlock_irqrestore(&cs->lock, flags);
673
657 if (ret) { 674 if (ret) {
658 dev_err(cs->dev, "could not submit urb (error %d)\n", -ret); 675 err("could not submit urb (error %d)\n", -ret);
659 atomic_set(&ucs->busy, 0); 676 atomic_set(&ucs->busy, 0);
660 } 677 }
678
661 if (!bcs->tx_skb->len) { 679 if (!bcs->tx_skb->len) {
662 /* skb sent completely */ 680 /* skb sent completely */
663 gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0? 681 gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0?