diff options
Diffstat (limited to 'drivers/ieee1394/sbp2.c')
| -rw-r--r-- | drivers/ieee1394/sbp2.c | 107 |
1 files changed, 65 insertions, 42 deletions
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index de88218ef7cc..12cec7c4a342 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c | |||
| @@ -97,16 +97,18 @@ static char version[] __devinitdata = | |||
| 97 | */ | 97 | */ |
| 98 | static int max_speed = IEEE1394_SPEED_MAX; | 98 | static int max_speed = IEEE1394_SPEED_MAX; |
| 99 | module_param(max_speed, int, 0644); | 99 | module_param(max_speed, int, 0644); |
| 100 | MODULE_PARM_DESC(max_speed, "Force max speed (3 = 800mb, 2 = 400mb default, 1 = 200mb, 0 = 100mb)"); | 100 | MODULE_PARM_DESC(max_speed, "Force max speed (3 = 800mb, 2 = 400mb, 1 = 200mb, 0 = 100mb)"); |
| 101 | 101 | ||
| 102 | /* | 102 | /* |
| 103 | * Set serialize_io to 1 if you'd like only one scsi command sent | 103 | * Set serialize_io to 1 if you'd like only one scsi command sent |
| 104 | * down to us at a time (debugging). This might be necessary for very | 104 | * down to us at a time (debugging). This might be necessary for very |
| 105 | * badly behaved sbp2 devices. | 105 | * badly behaved sbp2 devices. |
| 106 | * | ||
| 107 | * TODO: Make this configurable per device. | ||
| 106 | */ | 108 | */ |
| 107 | static int serialize_io; | 109 | static int serialize_io = 1; |
| 108 | module_param(serialize_io, int, 0444); | 110 | module_param(serialize_io, int, 0444); |
| 109 | MODULE_PARM_DESC(serialize_io, "Serialize all I/O coming down from the scsi drivers (default = 0)"); | 111 | MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers (default = 1, faster = 0)"); |
| 110 | 112 | ||
| 111 | /* | 113 | /* |
| 112 | * Bump up max_sectors if you'd like to support very large sized | 114 | * Bump up max_sectors if you'd like to support very large sized |
| @@ -596,6 +598,14 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i | |||
| 596 | spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); | 598 | spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); |
| 597 | } | 599 | } |
| 598 | 600 | ||
| 601 | /* | ||
| 602 | * Is scsi_id valid? Is the 1394 node still present? | ||
| 603 | */ | ||
| 604 | static inline int sbp2util_node_is_available(struct scsi_id_instance_data *scsi_id) | ||
| 605 | { | ||
| 606 | return scsi_id && scsi_id->ne && !scsi_id->ne->in_limbo; | ||
| 607 | } | ||
| 608 | |||
| 599 | 609 | ||
| 600 | 610 | ||
| 601 | /********************************************* | 611 | /********************************************* |
| @@ -631,11 +641,23 @@ static int sbp2_remove(struct device *dev) | |||
| 631 | { | 641 | { |
| 632 | struct unit_directory *ud; | 642 | struct unit_directory *ud; |
| 633 | struct scsi_id_instance_data *scsi_id; | 643 | struct scsi_id_instance_data *scsi_id; |
| 644 | struct scsi_device *sdev; | ||
| 634 | 645 | ||
| 635 | SBP2_DEBUG("sbp2_remove"); | 646 | SBP2_DEBUG("sbp2_remove"); |
| 636 | 647 | ||
| 637 | ud = container_of(dev, struct unit_directory, device); | 648 | ud = container_of(dev, struct unit_directory, device); |
| 638 | scsi_id = ud->device.driver_data; | 649 | scsi_id = ud->device.driver_data; |
| 650 | if (!scsi_id) | ||
| 651 | return 0; | ||
| 652 | |||
| 653 | /* Trigger shutdown functions in scsi's highlevel. */ | ||
| 654 | if (scsi_id->scsi_host) | ||
| 655 | scsi_unblock_requests(scsi_id->scsi_host); | ||
| 656 | sdev = scsi_id->sdev; | ||
| 657 | if (sdev) { | ||
| 658 | scsi_id->sdev = NULL; | ||
| 659 | scsi_remove_device(sdev); | ||
| 660 | } | ||
| 639 | 661 | ||
| 640 | sbp2_logout_device(scsi_id); | 662 | sbp2_logout_device(scsi_id); |
| 641 | sbp2_remove_device(scsi_id); | 663 | sbp2_remove_device(scsi_id); |
| @@ -2473,37 +2495,26 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
| 2473 | struct scsi_id_instance_data *scsi_id = | 2495 | struct scsi_id_instance_data *scsi_id = |
| 2474 | (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; | 2496 | (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; |
| 2475 | struct sbp2scsi_host_info *hi; | 2497 | struct sbp2scsi_host_info *hi; |
| 2498 | int result = DID_NO_CONNECT << 16; | ||
| 2476 | 2499 | ||
| 2477 | SBP2_DEBUG("sbp2scsi_queuecommand"); | 2500 | SBP2_DEBUG("sbp2scsi_queuecommand"); |
| 2478 | 2501 | ||
| 2479 | /* | 2502 | if (!sbp2util_node_is_available(scsi_id)) |
| 2480 | * If scsi_id is null, it means there is no device in this slot, | 2503 | goto done; |
| 2481 | * so we should return selection timeout. | ||
| 2482 | */ | ||
| 2483 | if (!scsi_id) { | ||
| 2484 | SCpnt->result = DID_NO_CONNECT << 16; | ||
| 2485 | done (SCpnt); | ||
| 2486 | return 0; | ||
| 2487 | } | ||
| 2488 | 2504 | ||
| 2489 | hi = scsi_id->hi; | 2505 | hi = scsi_id->hi; |
| 2490 | 2506 | ||
| 2491 | if (!hi) { | 2507 | if (!hi) { |
| 2492 | SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!"); | 2508 | SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!"); |
| 2493 | SCpnt->result = DID_NO_CONNECT << 16; | 2509 | goto done; |
| 2494 | done (SCpnt); | ||
| 2495 | return(0); | ||
| 2496 | } | 2510 | } |
| 2497 | 2511 | ||
| 2498 | /* | 2512 | /* |
| 2499 | * Until we handle multiple luns, just return selection time-out | 2513 | * Until we handle multiple luns, just return selection time-out |
| 2500 | * to any IO directed at non-zero LUNs | 2514 | * to any IO directed at non-zero LUNs |
| 2501 | */ | 2515 | */ |
| 2502 | if (SCpnt->device->lun) { | 2516 | if (SCpnt->device->lun) |
| 2503 | SCpnt->result = DID_NO_CONNECT << 16; | 2517 | goto done; |
| 2504 | done (SCpnt); | ||
| 2505 | return(0); | ||
| 2506 | } | ||
| 2507 | 2518 | ||
| 2508 | /* | 2519 | /* |
| 2509 | * Check for request sense command, and handle it here | 2520 | * Check for request sense command, and handle it here |
| @@ -2514,7 +2525,7 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
| 2514 | memcpy(SCpnt->request_buffer, SCpnt->sense_buffer, SCpnt->request_bufflen); | 2525 | memcpy(SCpnt->request_buffer, SCpnt->sense_buffer, SCpnt->request_bufflen); |
| 2515 | memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); | 2526 | memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); |
| 2516 | sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_GOOD, SCpnt, done); | 2527 | sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_GOOD, SCpnt, done); |
| 2517 | return(0); | 2528 | return 0; |
| 2518 | } | 2529 | } |
| 2519 | 2530 | ||
| 2520 | /* | 2531 | /* |
| @@ -2522,9 +2533,8 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
| 2522 | */ | 2533 | */ |
| 2523 | if (!hpsb_node_entry_valid(scsi_id->ne)) { | 2534 | if (!hpsb_node_entry_valid(scsi_id->ne)) { |
| 2524 | SBP2_ERR("Bus reset in progress - rejecting command"); | 2535 | SBP2_ERR("Bus reset in progress - rejecting command"); |
| 2525 | SCpnt->result = DID_BUS_BUSY << 16; | 2536 | result = DID_BUS_BUSY << 16; |
| 2526 | done (SCpnt); | 2537 | goto done; |
| 2527 | return(0); | ||
| 2528 | } | 2538 | } |
| 2529 | 2539 | ||
| 2530 | /* | 2540 | /* |
| @@ -2535,8 +2545,12 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
| 2535 | sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT, | 2545 | sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT, |
| 2536 | SCpnt, done); | 2546 | SCpnt, done); |
| 2537 | } | 2547 | } |
| 2548 | return 0; | ||
| 2538 | 2549 | ||
| 2539 | return(0); | 2550 | done: |
| 2551 | SCpnt->result = result; | ||
| 2552 | done(SCpnt); | ||
| 2553 | return 0; | ||
| 2540 | } | 2554 | } |
| 2541 | 2555 | ||
| 2542 | /* | 2556 | /* |
| @@ -2683,14 +2697,27 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, | |||
| 2683 | } | 2697 | } |
| 2684 | 2698 | ||
| 2685 | 2699 | ||
| 2686 | static int sbp2scsi_slave_configure (struct scsi_device *sdev) | 2700 | static int sbp2scsi_slave_alloc(struct scsi_device *sdev) |
| 2687 | { | 2701 | { |
| 2688 | blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); | 2702 | ((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = sdev; |
| 2703 | return 0; | ||
| 2704 | } | ||
| 2705 | |||
| 2689 | 2706 | ||
| 2707 | static int sbp2scsi_slave_configure(struct scsi_device *sdev) | ||
| 2708 | { | ||
| 2709 | blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); | ||
| 2690 | return 0; | 2710 | return 0; |
| 2691 | } | 2711 | } |
| 2692 | 2712 | ||
| 2693 | 2713 | ||
| 2714 | static void sbp2scsi_slave_destroy(struct scsi_device *sdev) | ||
| 2715 | { | ||
| 2716 | ((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = NULL; | ||
| 2717 | return; | ||
| 2718 | } | ||
| 2719 | |||
| 2720 | |||
| 2694 | /* | 2721 | /* |
| 2695 | * Called by scsi stack when something has really gone wrong. Usually | 2722 | * Called by scsi stack when something has really gone wrong. Usually |
| 2696 | * called when a command has timed-out for some reason. | 2723 | * called when a command has timed-out for some reason. |
| @@ -2705,7 +2732,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) | |||
| 2705 | SBP2_ERR("aborting sbp2 command"); | 2732 | SBP2_ERR("aborting sbp2 command"); |
| 2706 | scsi_print_command(SCpnt); | 2733 | scsi_print_command(SCpnt); |
| 2707 | 2734 | ||
| 2708 | if (scsi_id) { | 2735 | if (sbp2util_node_is_available(scsi_id)) { |
| 2709 | 2736 | ||
| 2710 | /* | 2737 | /* |
| 2711 | * Right now, just return any matching command structures | 2738 | * Right now, just return any matching command structures |
| @@ -2742,31 +2769,24 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) | |||
| 2742 | /* | 2769 | /* |
| 2743 | * Called by scsi stack when something has really gone wrong. | 2770 | * Called by scsi stack when something has really gone wrong. |
| 2744 | */ | 2771 | */ |
| 2745 | static int __sbp2scsi_reset(struct scsi_cmnd *SCpnt) | 2772 | static int sbp2scsi_reset(struct scsi_cmnd *SCpnt) |
| 2746 | { | 2773 | { |
| 2747 | struct scsi_id_instance_data *scsi_id = | 2774 | struct scsi_id_instance_data *scsi_id = |
| 2748 | (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; | 2775 | (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; |
| 2776 | unsigned long flags; | ||
| 2749 | 2777 | ||
| 2750 | SBP2_ERR("reset requested"); | 2778 | SBP2_ERR("reset requested"); |
| 2751 | 2779 | ||
| 2752 | if (scsi_id) { | 2780 | spin_lock_irqsave(SCpnt->device->host->host_lock, flags); |
| 2781 | |||
| 2782 | if (sbp2util_node_is_available(scsi_id)) { | ||
| 2753 | SBP2_ERR("Generating sbp2 fetch agent reset"); | 2783 | SBP2_ERR("Generating sbp2 fetch agent reset"); |
| 2754 | sbp2_agent_reset(scsi_id, 0); | 2784 | sbp2_agent_reset(scsi_id, 0); |
| 2755 | } | 2785 | } |
| 2756 | 2786 | ||
| 2757 | return(SUCCESS); | ||
| 2758 | } | ||
| 2759 | |||
| 2760 | static int sbp2scsi_reset(struct scsi_cmnd *SCpnt) | ||
| 2761 | { | ||
| 2762 | unsigned long flags; | ||
| 2763 | int rc; | ||
| 2764 | |||
| 2765 | spin_lock_irqsave(SCpnt->device->host->host_lock, flags); | ||
| 2766 | rc = __sbp2scsi_reset(SCpnt); | ||
| 2767 | spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags); | 2787 | spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags); |
| 2768 | 2788 | ||
| 2769 | return rc; | 2789 | return SUCCESS; |
| 2770 | } | 2790 | } |
| 2771 | 2791 | ||
| 2772 | static const char *sbp2scsi_info (struct Scsi_Host *host) | 2792 | static const char *sbp2scsi_info (struct Scsi_Host *host) |
| @@ -2817,7 +2837,9 @@ static struct scsi_host_template scsi_driver_template = { | |||
| 2817 | .eh_device_reset_handler = sbp2scsi_reset, | 2837 | .eh_device_reset_handler = sbp2scsi_reset, |
| 2818 | .eh_bus_reset_handler = sbp2scsi_reset, | 2838 | .eh_bus_reset_handler = sbp2scsi_reset, |
| 2819 | .eh_host_reset_handler = sbp2scsi_reset, | 2839 | .eh_host_reset_handler = sbp2scsi_reset, |
| 2840 | .slave_alloc = sbp2scsi_slave_alloc, | ||
| 2820 | .slave_configure = sbp2scsi_slave_configure, | 2841 | .slave_configure = sbp2scsi_slave_configure, |
| 2842 | .slave_destroy = sbp2scsi_slave_destroy, | ||
| 2821 | .this_id = -1, | 2843 | .this_id = -1, |
| 2822 | .sg_tablesize = SG_ALL, | 2844 | .sg_tablesize = SG_ALL, |
| 2823 | .use_clustering = ENABLE_CLUSTERING, | 2845 | .use_clustering = ENABLE_CLUSTERING, |
| @@ -2837,7 +2859,8 @@ static int sbp2_module_init(void) | |||
| 2837 | 2859 | ||
| 2838 | /* Module load debug option to force one command at a time (serializing I/O) */ | 2860 | /* Module load debug option to force one command at a time (serializing I/O) */ |
| 2839 | if (serialize_io) { | 2861 | if (serialize_io) { |
| 2840 | SBP2_ERR("Driver forced to serialize I/O (serialize_io = 1)"); | 2862 | SBP2_INFO("Driver forced to serialize I/O (serialize_io=1)"); |
| 2863 | SBP2_INFO("Try serialize_io=0 for better performance"); | ||
| 2841 | scsi_driver_template.can_queue = 1; | 2864 | scsi_driver_template.can_queue = 1; |
| 2842 | scsi_driver_template.cmd_per_lun = 1; | 2865 | scsi_driver_template.cmd_per_lun = 1; |
| 2843 | } | 2866 | } |
