aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_spi.c
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@steeleye.com>2005-05-01 19:58:15 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-05-05 17:08:59 -0400
commit949bf797595fc99d4cadf9a294fe6fd32a4474e6 (patch)
tree0c91a5d3822785a5608db8a4970f40ea857a9e7b /drivers/scsi/scsi_transport_spi.c
parent69b528936b702d4c13ffa0d14215a029dc754e50 (diff)
[SCSI] fix command retries in spi_transport class
The premise is that domain validation is likely to trigger errors which it wants to know about, so the only time it should be retrying them is when it gets a unit attention (likely as the result of a previous bus or device reset). Ironically, the previous coding retried three times in all cases except those of unit attention. The attached fixes this to do the right thing. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/scsi_transport_spi.c')
-rw-r--r--drivers/scsi/scsi_transport_spi.c49
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 */
111static 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
103static struct { 132static 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
386enum spi_compare_returns { 410enum 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 */