diff options
Diffstat (limited to 'drivers/usb/atm/speedtch.c')
-rw-r--r-- | drivers/usb/atm/speedtch.c | 63 |
1 files changed, 31 insertions, 32 deletions
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index 6a6eaa2a3b1c..d0cbbb7f0385 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c | |||
@@ -100,6 +100,8 @@ struct speedtch_instance_data { | |||
100 | 100 | ||
101 | struct work_struct status_checker; | 101 | struct work_struct status_checker; |
102 | 102 | ||
103 | unsigned char last_status; | ||
104 | |||
103 | int poll_delay; /* milliseconds */ | 105 | int poll_delay; /* milliseconds */ |
104 | 106 | ||
105 | struct timer_list resubmit_timer; | 107 | struct timer_list resubmit_timer; |
@@ -423,52 +425,48 @@ static void speedtch_check_status(struct speedtch_instance_data *instance) | |||
423 | struct usbatm_data *usbatm = instance->usbatm; | 425 | struct usbatm_data *usbatm = instance->usbatm; |
424 | struct atm_dev *atm_dev = usbatm->atm_dev; | 426 | struct atm_dev *atm_dev = usbatm->atm_dev; |
425 | unsigned char *buf = instance->scratch_buffer; | 427 | unsigned char *buf = instance->scratch_buffer; |
426 | int ret; | 428 | int down_speed, up_speed, ret; |
429 | unsigned char status; | ||
427 | 430 | ||
428 | atm_dbg(usbatm, "%s entered\n", __func__); | 431 | atm_dbg(usbatm, "%s entered\n", __func__); |
429 | 432 | ||
430 | ret = speedtch_read_status(instance); | 433 | ret = speedtch_read_status(instance); |
431 | if (ret < 0) { | 434 | if (ret < 0) { |
432 | atm_warn(usbatm, "error %d fetching device status\n", ret); | 435 | atm_warn(usbatm, "error %d fetching device status\n", ret); |
433 | if (instance->poll_delay < MAX_POLL_DELAY) | 436 | instance->poll_delay = min(2 * instance->poll_delay, MAX_POLL_DELAY); |
434 | instance->poll_delay *= 2; | ||
435 | return; | 437 | return; |
436 | } | 438 | } |
437 | 439 | ||
438 | if (instance->poll_delay > MIN_POLL_DELAY) | 440 | instance->poll_delay = max(instance->poll_delay / 2, MIN_POLL_DELAY); |
439 | instance->poll_delay /= 2; | ||
440 | 441 | ||
441 | atm_dbg(usbatm, "%s: line state %02x\n", __func__, buf[OFFSET_7]); | 442 | status = buf[OFFSET_7]; |
442 | 443 | ||
443 | switch (buf[OFFSET_7]) { | 444 | atm_dbg(usbatm, "%s: line state %02x\n", __func__, status); |
444 | case 0: | 445 | |
445 | if (atm_dev->signal != ATM_PHY_SIG_LOST) { | 446 | if ((status != instance->last_status) || !status) { |
447 | switch (status) { | ||
448 | case 0: | ||
446 | atm_dev->signal = ATM_PHY_SIG_LOST; | 449 | atm_dev->signal = ATM_PHY_SIG_LOST; |
447 | atm_info(usbatm, "ADSL line is down\n"); | 450 | if (instance->last_status) |
448 | /* It'll never resync again unless we ask it to... */ | 451 | atm_info(usbatm, "ADSL line is down\n"); |
452 | /* It may never resync again unless we ask it to... */ | ||
449 | ret = speedtch_start_synchro(instance); | 453 | ret = speedtch_start_synchro(instance); |
450 | } | 454 | break; |
451 | break; | ||
452 | 455 | ||
453 | case 0x08: | 456 | case 0x08: |
454 | if (atm_dev->signal != ATM_PHY_SIG_UNKNOWN) { | ||
455 | atm_dev->signal = ATM_PHY_SIG_UNKNOWN; | 457 | atm_dev->signal = ATM_PHY_SIG_UNKNOWN; |
456 | atm_info(usbatm, "ADSL line is blocked?\n"); | 458 | atm_info(usbatm, "ADSL line is blocked?\n"); |
457 | } | 459 | break; |
458 | break; | ||
459 | 460 | ||
460 | case 0x10: | 461 | case 0x10: |
461 | if (atm_dev->signal != ATM_PHY_SIG_LOST) { | ||
462 | atm_dev->signal = ATM_PHY_SIG_LOST; | 462 | atm_dev->signal = ATM_PHY_SIG_LOST; |
463 | atm_info(usbatm, "ADSL line is synchronising\n"); | 463 | atm_info(usbatm, "ADSL line is synchronising\n"); |
464 | } | 464 | break; |
465 | break; | ||
466 | 465 | ||
467 | case 0x20: | 466 | case 0x20: |
468 | if (atm_dev->signal != ATM_PHY_SIG_FOUND) { | 467 | down_speed = buf[OFFSET_b] | (buf[OFFSET_b + 1] << 8) |
469 | int down_speed = buf[OFFSET_b] | (buf[OFFSET_b + 1] << 8) | ||
470 | | (buf[OFFSET_b + 2] << 16) | (buf[OFFSET_b + 3] << 24); | 468 | | (buf[OFFSET_b + 2] << 16) | (buf[OFFSET_b + 3] << 24); |
471 | int up_speed = buf[OFFSET_b + 4] | (buf[OFFSET_b + 5] << 8) | 469 | up_speed = buf[OFFSET_b + 4] | (buf[OFFSET_b + 5] << 8) |
472 | | (buf[OFFSET_b + 6] << 16) | (buf[OFFSET_b + 7] << 24); | 470 | | (buf[OFFSET_b + 6] << 16) | (buf[OFFSET_b + 7] << 24); |
473 | 471 | ||
474 | if (!(down_speed & 0x0000ffff) && !(up_speed & 0x0000ffff)) { | 472 | if (!(down_speed & 0x0000ffff) && !(up_speed & 0x0000ffff)) { |
@@ -480,17 +478,17 @@ static void speedtch_check_status(struct speedtch_instance_data *instance) | |||
480 | atm_dev->signal = ATM_PHY_SIG_FOUND; | 478 | atm_dev->signal = ATM_PHY_SIG_FOUND; |
481 | 479 | ||
482 | atm_info(usbatm, | 480 | atm_info(usbatm, |
483 | "ADSL line is up (%d Kib/s down | %d Kib/s up)\n", | 481 | "ADSL line is up (%d kb/s down | %d kb/s up)\n", |
484 | down_speed, up_speed); | 482 | down_speed, up_speed); |
485 | } | 483 | break; |
486 | break; | ||
487 | 484 | ||
488 | default: | 485 | default: |
489 | if (atm_dev->signal != ATM_PHY_SIG_UNKNOWN) { | ||
490 | atm_dev->signal = ATM_PHY_SIG_UNKNOWN; | 486 | atm_dev->signal = ATM_PHY_SIG_UNKNOWN; |
491 | atm_info(usbatm, "Unknown line state %02x\n", buf[OFFSET_7]); | 487 | atm_info(usbatm, "Unknown line state %02x\n", status); |
488 | break; | ||
492 | } | 489 | } |
493 | break; | 490 | |
491 | instance->last_status = status; | ||
494 | } | 492 | } |
495 | } | 493 | } |
496 | 494 | ||
@@ -730,6 +728,7 @@ static int speedtch_bind(struct usbatm_data *usbatm, | |||
730 | 728 | ||
731 | instance->status_checker.timer.function = speedtch_status_poll; | 729 | instance->status_checker.timer.function = speedtch_status_poll; |
732 | instance->status_checker.timer.data = (unsigned long)instance; | 730 | instance->status_checker.timer.data = (unsigned long)instance; |
731 | instance->last_status = 0xff; | ||
733 | instance->poll_delay = MIN_POLL_DELAY; | 732 | instance->poll_delay = MIN_POLL_DELAY; |
734 | 733 | ||
735 | init_timer(&instance->resubmit_timer); | 734 | init_timer(&instance->resubmit_timer); |