diff options
| -rw-r--r-- | drivers/scsi/scsi_transport_spi.c | 49 |
1 files changed, 34 insertions, 15 deletions
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 303d7656f710..28966d05435c 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
| 23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/workqueue.h> | 24 | #include <linux/workqueue.h> |
| 25 | #include <linux/blkdev.h> | ||
| 25 | #include <asm/semaphore.h> | 26 | #include <asm/semaphore.h> |
| 26 | #include <scsi/scsi.h> | 27 | #include <scsi/scsi.h> |
| 27 | #include "scsi_priv.h" | 28 | #include "scsi_priv.h" |
| @@ -41,6 +42,11 @@ | |||
| 41 | 42 | ||
| 42 | #define SPI_MAX_ECHO_BUFFER_SIZE 4096 | 43 | #define SPI_MAX_ECHO_BUFFER_SIZE 4096 |
| 43 | 44 | ||
| 45 | #define DV_LOOPS 3 | ||
| 46 | #define DV_TIMEOUT (10*HZ) | ||
| 47 | #define DV_RETRIES 3 /* should only need at most | ||
| 48 | * two cc/ua clears */ | ||
| 49 | |||
| 44 | /* Private data accessors (keep these out of the header file) */ | 50 | /* Private data accessors (keep these out of the header file) */ |
| 45 | #define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending) | 51 | #define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending) |
| 46 | #define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_sem) | 52 | #define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_sem) |
| @@ -100,6 +106,29 @@ static int sprint_frac(char *dest, int value, int denom) | |||
| 100 | return result; | 106 | return result; |
| 101 | } | 107 | } |
| 102 | 108 | ||
| 109 | /* Modification of scsi_wait_req that will clear UNIT ATTENTION conditions | ||
| 110 | * resulting from (likely) bus and device resets */ | ||
| 111 | static void spi_wait_req(struct scsi_request *sreq, const void *cmd, | ||
| 112 | void *buffer, unsigned bufflen) | ||
| 113 | { | ||
| 114 | int i; | ||
| 115 | |||
| 116 | for(i = 0; i < DV_RETRIES; i++) { | ||
| 117 | sreq->sr_request->flags |= REQ_FAILFAST; | ||
| 118 | |||
| 119 | scsi_wait_req(sreq, cmd, buffer, bufflen, | ||
| 120 | DV_TIMEOUT, /* retries */ 1); | ||
| 121 | if (sreq->sr_result & DRIVER_SENSE) { | ||
| 122 | struct scsi_sense_hdr sshdr; | ||
| 123 | |||
| 124 | if (scsi_request_normalize_sense(sreq, &sshdr) | ||
| 125 | && sshdr.sense_key == UNIT_ATTENTION) | ||
| 126 | continue; | ||
| 127 | } | ||
| 128 | break; | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 103 | static struct { | 132 | static struct { |
| 104 | enum spi_signal_type value; | 133 | enum spi_signal_type value; |
| 105 | char *name; | 134 | char *name; |
| @@ -378,11 +407,6 @@ static CLASS_DEVICE_ATTR(signalling, S_IRUGO | S_IWUSR, | |||
| 378 | if(i->f->set_##x) \ | 407 | if(i->f->set_##x) \ |
| 379 | i->f->set_##x(sdev->sdev_target, y) | 408 | i->f->set_##x(sdev->sdev_target, y) |
| 380 | 409 | ||
| 381 | #define DV_LOOPS 3 | ||
| 382 | #define DV_TIMEOUT (10*HZ) | ||
| 383 | #define DV_RETRIES 3 /* should only need at most | ||
| 384 | * two cc/ua clears */ | ||
| 385 | |||
| 386 | enum spi_compare_returns { | 410 | enum spi_compare_returns { |
| 387 | SPI_COMPARE_SUCCESS, | 411 | SPI_COMPARE_SUCCESS, |
| 388 | SPI_COMPARE_FAILURE, | 412 | SPI_COMPARE_FAILURE, |
| @@ -446,8 +470,7 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, | |||
| 446 | for (r = 0; r < retries; r++) { | 470 | for (r = 0; r < retries; r++) { |
| 447 | sreq->sr_cmd_len = 0; /* wait_req to fill in */ | 471 | sreq->sr_cmd_len = 0; /* wait_req to fill in */ |
| 448 | sreq->sr_data_direction = DMA_TO_DEVICE; | 472 | sreq->sr_data_direction = DMA_TO_DEVICE; |
| 449 | scsi_wait_req(sreq, spi_write_buffer, buffer, len, | 473 | spi_wait_req(sreq, spi_write_buffer, buffer, len); |
| 450 | DV_TIMEOUT, DV_RETRIES); | ||
| 451 | if(sreq->sr_result || !scsi_device_online(sdev)) { | 474 | if(sreq->sr_result || !scsi_device_online(sdev)) { |
| 452 | struct scsi_sense_hdr sshdr; | 475 | struct scsi_sense_hdr sshdr; |
| 453 | 476 | ||
| @@ -471,8 +494,7 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, | |||
| 471 | memset(ptr, 0, len); | 494 | memset(ptr, 0, len); |
| 472 | sreq->sr_cmd_len = 0; /* wait_req to fill in */ | 495 | sreq->sr_cmd_len = 0; /* wait_req to fill in */ |
| 473 | sreq->sr_data_direction = DMA_FROM_DEVICE; | 496 | sreq->sr_data_direction = DMA_FROM_DEVICE; |
| 474 | scsi_wait_req(sreq, spi_read_buffer, ptr, len, | 497 | spi_wait_req(sreq, spi_read_buffer, ptr, len); |
| 475 | DV_TIMEOUT, DV_RETRIES); | ||
| 476 | scsi_device_set_state(sdev, SDEV_QUIESCE); | 498 | scsi_device_set_state(sdev, SDEV_QUIESCE); |
| 477 | 499 | ||
| 478 | if (memcmp(buffer, ptr, len) != 0) | 500 | if (memcmp(buffer, ptr, len) != 0) |
| @@ -500,8 +522,7 @@ spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer, | |||
| 500 | 522 | ||
| 501 | memset(ptr, 0, len); | 523 | memset(ptr, 0, len); |
| 502 | 524 | ||
| 503 | scsi_wait_req(sreq, spi_inquiry, ptr, len, | 525 | spi_wait_req(sreq, spi_inquiry, ptr, len); |
| 504 | DV_TIMEOUT, DV_RETRIES); | ||
| 505 | 526 | ||
| 506 | if(sreq->sr_result || !scsi_device_online(sdev)) { | 527 | if(sreq->sr_result || !scsi_device_online(sdev)) { |
| 507 | scsi_device_set_state(sdev, SDEV_QUIESCE); | 528 | scsi_device_set_state(sdev, SDEV_QUIESCE); |
| @@ -593,8 +614,7 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) | |||
| 593 | * (reservation conflict, device not ready, etc) just | 614 | * (reservation conflict, device not ready, etc) just |
| 594 | * skip the write tests */ | 615 | * skip the write tests */ |
| 595 | for (l = 0; ; l++) { | 616 | for (l = 0; ; l++) { |
| 596 | scsi_wait_req(sreq, spi_test_unit_ready, NULL, 0, | 617 | spi_wait_req(sreq, spi_test_unit_ready, NULL, 0); |
| 597 | DV_TIMEOUT, DV_RETRIES); | ||
| 598 | 618 | ||
| 599 | if(sreq->sr_result) { | 619 | if(sreq->sr_result) { |
| 600 | if(l >= 3) | 620 | if(l >= 3) |
| @@ -608,8 +628,7 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) | |||
| 608 | sreq->sr_cmd_len = 0; | 628 | sreq->sr_cmd_len = 0; |
| 609 | sreq->sr_data_direction = DMA_FROM_DEVICE; | 629 | sreq->sr_data_direction = DMA_FROM_DEVICE; |
| 610 | 630 | ||
| 611 | scsi_wait_req(sreq, spi_read_buffer_descriptor, buffer, 4, | 631 | spi_wait_req(sreq, spi_read_buffer_descriptor, buffer, 4); |
| 612 | DV_TIMEOUT, DV_RETRIES); | ||
| 613 | 632 | ||
| 614 | if (sreq->sr_result) | 633 | if (sreq->sr_result) |
| 615 | /* Device has no echo buffer */ | 634 | /* Device has no echo buffer */ |
