diff options
author | James Bottomley <James.Bottomley@steeleye.com> | 2006-06-29 13:02:11 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-06-29 13:15:15 -0400 |
commit | 0f13fc09db68de92585558984bff1c51b87db72f (patch) | |
tree | 752bb8fa84e731f7877b74a033d1b90e2c060977 /drivers/scsi | |
parent | 53cb8a1f45e06a2627a6d89b151cccb95fa45cbf (diff) |
[SCSI] 53c700: fix breakage caused by the autosense update
A bit of a brown paper bag issue. The previous patch to remove the soon
to be ripped out fields that were used in autosense actually broke the
driver. This patch fixes it and has been tested (honestly).
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/53c700.c | 56 | ||||
-rw-r--r-- | drivers/scsi/53c700.h | 34 |
2 files changed, 53 insertions, 37 deletions
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index bff04797739a..24dfd54865ee 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c | |||
@@ -174,6 +174,7 @@ STATIC int NCR_700_bus_reset(struct scsi_cmnd * SCpnt); | |||
174 | STATIC int NCR_700_host_reset(struct scsi_cmnd * SCpnt); | 174 | STATIC int NCR_700_host_reset(struct scsi_cmnd * SCpnt); |
175 | STATIC void NCR_700_chip_setup(struct Scsi_Host *host); | 175 | STATIC void NCR_700_chip_setup(struct Scsi_Host *host); |
176 | STATIC void NCR_700_chip_reset(struct Scsi_Host *host); | 176 | STATIC void NCR_700_chip_reset(struct Scsi_Host *host); |
177 | STATIC int NCR_700_slave_alloc(struct scsi_device *SDpnt); | ||
177 | STATIC int NCR_700_slave_configure(struct scsi_device *SDpnt); | 178 | STATIC int NCR_700_slave_configure(struct scsi_device *SDpnt); |
178 | STATIC void NCR_700_slave_destroy(struct scsi_device *SDpnt); | 179 | STATIC void NCR_700_slave_destroy(struct scsi_device *SDpnt); |
179 | static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth); | 180 | static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth); |
@@ -183,10 +184,6 @@ STATIC struct device_attribute *NCR_700_dev_attrs[]; | |||
183 | 184 | ||
184 | STATIC struct scsi_transport_template *NCR_700_transport_template = NULL; | 185 | STATIC struct scsi_transport_template *NCR_700_transport_template = NULL; |
185 | 186 | ||
186 | struct NCR_700_sense { | ||
187 | unsigned char cmnd[MAX_COMMAND_SIZE]; | ||
188 | }; | ||
189 | |||
190 | static char *NCR_700_phase[] = { | 187 | static char *NCR_700_phase[] = { |
191 | "", | 188 | "", |
192 | "after selection", | 189 | "after selection", |
@@ -334,6 +331,7 @@ NCR_700_detect(struct scsi_host_template *tpnt, | |||
334 | tpnt->use_clustering = ENABLE_CLUSTERING; | 331 | tpnt->use_clustering = ENABLE_CLUSTERING; |
335 | tpnt->slave_configure = NCR_700_slave_configure; | 332 | tpnt->slave_configure = NCR_700_slave_configure; |
336 | tpnt->slave_destroy = NCR_700_slave_destroy; | 333 | tpnt->slave_destroy = NCR_700_slave_destroy; |
334 | tpnt->slave_alloc = NCR_700_slave_alloc; | ||
337 | tpnt->change_queue_depth = NCR_700_change_queue_depth; | 335 | tpnt->change_queue_depth = NCR_700_change_queue_depth; |
338 | tpnt->change_queue_type = NCR_700_change_queue_type; | 336 | tpnt->change_queue_type = NCR_700_change_queue_type; |
339 | 337 | ||
@@ -612,9 +610,10 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata, | |||
612 | struct NCR_700_command_slot *slot = | 610 | struct NCR_700_command_slot *slot = |
613 | (struct NCR_700_command_slot *)SCp->host_scribble; | 611 | (struct NCR_700_command_slot *)SCp->host_scribble; |
614 | 612 | ||
615 | NCR_700_unmap(hostdata, SCp, slot); | 613 | dma_unmap_single(hostdata->dev, slot->pCmd, |
614 | sizeof(SCp->cmnd), DMA_TO_DEVICE); | ||
616 | if (slot->flags == NCR_700_FLAG_AUTOSENSE) { | 615 | if (slot->flags == NCR_700_FLAG_AUTOSENSE) { |
617 | struct NCR_700_sense *sense = SCp->device->hostdata; | 616 | char *cmnd = NCR_700_get_sense_cmnd(SCp->device); |
618 | #ifdef NCR_700_DEBUG | 617 | #ifdef NCR_700_DEBUG |
619 | printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is\n", | 618 | printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is\n", |
620 | SCp, SCp->cmnd[7], result); | 619 | SCp, SCp->cmnd[7], result); |
@@ -625,10 +624,9 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata, | |||
625 | /* restore the old result if the request sense was | 624 | /* restore the old result if the request sense was |
626 | * successful */ | 625 | * successful */ |
627 | if(result == 0) | 626 | if(result == 0) |
628 | result = sense->cmnd[7]; | 627 | result = cmnd[7]; |
629 | } else | 628 | } else |
630 | dma_unmap_single(hostdata->dev, slot->pCmd, | 629 | NCR_700_unmap(hostdata, SCp, slot); |
631 | sizeof(SCp->cmnd), DMA_TO_DEVICE); | ||
632 | 630 | ||
633 | free_slot(slot, hostdata); | 631 | free_slot(slot, hostdata); |
634 | #ifdef NCR_700_DEBUG | 632 | #ifdef NCR_700_DEBUG |
@@ -970,14 +968,15 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, | |||
970 | status_byte(hostdata->status[0]) == COMMAND_TERMINATED) { | 968 | status_byte(hostdata->status[0]) == COMMAND_TERMINATED) { |
971 | struct NCR_700_command_slot *slot = | 969 | struct NCR_700_command_slot *slot = |
972 | (struct NCR_700_command_slot *)SCp->host_scribble; | 970 | (struct NCR_700_command_slot *)SCp->host_scribble; |
973 | if(SCp->cmnd[0] == REQUEST_SENSE) { | 971 | if(slot->flags == NCR_700_FLAG_AUTOSENSE) { |
974 | /* OOPS: bad device, returning another | 972 | /* OOPS: bad device, returning another |
975 | * contingent allegiance condition */ | 973 | * contingent allegiance condition */ |
976 | scmd_printk(KERN_ERR, SCp, | 974 | scmd_printk(KERN_ERR, SCp, |
977 | "broken device is looping in contingent allegiance: ignoring\n"); | 975 | "broken device is looping in contingent allegiance: ignoring\n"); |
978 | NCR_700_scsi_done(hostdata, SCp, hostdata->status[0]); | 976 | NCR_700_scsi_done(hostdata, SCp, hostdata->status[0]); |
979 | } else { | 977 | } else { |
980 | struct NCR_700_sense *sense = SCp->device->hostdata; | 978 | char *cmnd = |
979 | NCR_700_get_sense_cmnd(SCp->device); | ||
981 | #ifdef NCR_DEBUG | 980 | #ifdef NCR_DEBUG |
982 | scsi_print_command(SCp); | 981 | scsi_print_command(SCp); |
983 | printk(" cmd %p has status %d, requesting sense\n", | 982 | printk(" cmd %p has status %d, requesting sense\n", |
@@ -995,21 +994,21 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, | |||
995 | sizeof(SCp->cmnd), | 994 | sizeof(SCp->cmnd), |
996 | DMA_TO_DEVICE); | 995 | DMA_TO_DEVICE); |
997 | 996 | ||
998 | sense->cmnd[0] = REQUEST_SENSE; | 997 | cmnd[0] = REQUEST_SENSE; |
999 | sense->cmnd[1] = (SCp->device->lun & 0x7) << 5; | 998 | cmnd[1] = (SCp->device->lun & 0x7) << 5; |
1000 | sense->cmnd[2] = 0; | 999 | cmnd[2] = 0; |
1001 | sense->cmnd[3] = 0; | 1000 | cmnd[3] = 0; |
1002 | sense->cmnd[4] = sizeof(SCp->sense_buffer); | 1001 | cmnd[4] = sizeof(SCp->sense_buffer); |
1003 | sense->cmnd[5] = 0; | 1002 | cmnd[5] = 0; |
1004 | /* Here's a quiet hack: the | 1003 | /* Here's a quiet hack: the |
1005 | * REQUEST_SENSE command is six bytes, | 1004 | * REQUEST_SENSE command is six bytes, |
1006 | * so store a flag indicating that | 1005 | * so store a flag indicating that |
1007 | * this was an internal sense request | 1006 | * this was an internal sense request |
1008 | * and the original status at the end | 1007 | * and the original status at the end |
1009 | * of the command */ | 1008 | * of the command */ |
1010 | sense->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; | 1009 | cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; |
1011 | sense->cmnd[7] = hostdata->status[0]; | 1010 | cmnd[7] = hostdata->status[0]; |
1012 | slot->pCmd = dma_map_single(hostdata->dev, sense->cmnd, sizeof(sense->cmnd), DMA_TO_DEVICE); | 1011 | slot->pCmd = dma_map_single(hostdata->dev, cmnd, MAX_COMMAND_SIZE, DMA_TO_DEVICE); |
1013 | slot->dma_handle = dma_map_single(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); | 1012 | slot->dma_handle = dma_map_single(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); |
1014 | slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer)); | 1013 | slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer)); |
1015 | slot->SG[0].pAddr = bS_to_host(slot->dma_handle); | 1014 | slot->SG[0].pAddr = bS_to_host(slot->dma_handle); |
@@ -1531,7 +1530,7 @@ NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
1531 | 1530 | ||
1532 | /* clear all the negotiated parameters */ | 1531 | /* clear all the negotiated parameters */ |
1533 | __shost_for_each_device(SDp, host) | 1532 | __shost_for_each_device(SDp, host) |
1534 | SDp->hostdata = NULL; | 1533 | NCR_700_clear_flag(SDp, ~0); |
1535 | 1534 | ||
1536 | /* clear all the slots and their pending commands */ | 1535 | /* clear all the slots and their pending commands */ |
1537 | for(i = 0; i < NCR_700_COMMAND_SLOTS_PER_HOST; i++) { | 1536 | for(i = 0; i < NCR_700_COMMAND_SLOTS_PER_HOST; i++) { |
@@ -2036,7 +2035,17 @@ NCR_700_set_offset(struct scsi_target *STp, int offset) | |||
2036 | spi_flags(STp) |= NCR_700_DEV_PRINT_SYNC_NEGOTIATION; | 2035 | spi_flags(STp) |= NCR_700_DEV_PRINT_SYNC_NEGOTIATION; |
2037 | } | 2036 | } |
2038 | 2037 | ||
2038 | STATIC int | ||
2039 | NCR_700_slave_alloc(struct scsi_device *SDp) | ||
2040 | { | ||
2041 | SDp->hostdata = kzalloc(sizeof(struct NCR_700_Device_Parameters), | ||
2042 | GFP_KERNEL); | ||
2039 | 2043 | ||
2044 | if (!SDp->hostdata) | ||
2045 | return -ENOMEM; | ||
2046 | |||
2047 | return 0; | ||
2048 | } | ||
2040 | 2049 | ||
2041 | STATIC int | 2050 | STATIC int |
2042 | NCR_700_slave_configure(struct scsi_device *SDp) | 2051 | NCR_700_slave_configure(struct scsi_device *SDp) |
@@ -2044,11 +2053,6 @@ NCR_700_slave_configure(struct scsi_device *SDp) | |||
2044 | struct NCR_700_Host_Parameters *hostdata = | 2053 | struct NCR_700_Host_Parameters *hostdata = |
2045 | (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; | 2054 | (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; |
2046 | 2055 | ||
2047 | SDp->hostdata = kmalloc(sizeof(struct NCR_700_sense), GFP_KERNEL); | ||
2048 | |||
2049 | if (!SDp->hostdata) | ||
2050 | return -ENOMEM; | ||
2051 | |||
2052 | /* to do here: allocate memory; build a queue_full list */ | 2056 | /* to do here: allocate memory; build a queue_full list */ |
2053 | if(SDp->tagged_supported) { | 2057 | if(SDp->tagged_supported) { |
2054 | scsi_set_tag_type(SDp, MSG_ORDERED_TAG); | 2058 | scsi_set_tag_type(SDp, MSG_ORDERED_TAG); |
diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h index 7f22a06fe5ec..97ebe71b701b 100644 --- a/drivers/scsi/53c700.h +++ b/drivers/scsi/53c700.h | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <asm/io.h> | 12 | #include <asm/io.h> |
13 | 13 | ||
14 | #include <scsi/scsi_device.h> | 14 | #include <scsi/scsi_device.h> |
15 | 15 | #include <scsi/scsi_cmnd.h> | |
16 | 16 | ||
17 | /* Turn on for general debugging---too verbose for normal use */ | 17 | /* Turn on for general debugging---too verbose for normal use */ |
18 | #undef NCR_700_DEBUG | 18 | #undef NCR_700_DEBUG |
@@ -76,11 +76,16 @@ struct NCR_700_SG_List { | |||
76 | #define SCRIPT_RETURN 0x90080000 | 76 | #define SCRIPT_RETURN 0x90080000 |
77 | }; | 77 | }; |
78 | 78 | ||
79 | /* We use device->hostdata to store negotiated parameters. This is | 79 | struct NCR_700_Device_Parameters { |
80 | * supposed to be a pointer to a device private area, but we cannot | 80 | /* space for creating a request sense command. Really, except |
81 | * really use it as such since it will never be freed, so just use the | 81 | * for the annoying SCSI-2 requirement for LUN information in |
82 | * 32 bits to cram the information. The SYNC negotiation sequence looks | 82 | * cmnd[1], this could be in static storage */ |
83 | * like: | 83 | unsigned char cmnd[MAX_COMMAND_SIZE]; |
84 | __u8 depth; | ||
85 | }; | ||
86 | |||
87 | |||
88 | /* The SYNC negotiation sequence looks like: | ||
84 | * | 89 | * |
85 | * If DEV_NEGOTIATED_SYNC not set, tack and SDTR message on to the | 90 | * If DEV_NEGOTIATED_SYNC not set, tack and SDTR message on to the |
86 | * initial identify for the device and set DEV_BEGIN_SYNC_NEGOTATION | 91 | * initial identify for the device and set DEV_BEGIN_SYNC_NEGOTATION |
@@ -98,19 +103,26 @@ struct NCR_700_SG_List { | |||
98 | #define NCR_700_DEV_BEGIN_SYNC_NEGOTIATION (1<<17) | 103 | #define NCR_700_DEV_BEGIN_SYNC_NEGOTIATION (1<<17) |
99 | #define NCR_700_DEV_PRINT_SYNC_NEGOTIATION (1<<19) | 104 | #define NCR_700_DEV_PRINT_SYNC_NEGOTIATION (1<<19) |
100 | 105 | ||
106 | static inline char *NCR_700_get_sense_cmnd(struct scsi_device *SDp) | ||
107 | { | ||
108 | struct NCR_700_Device_Parameters *hostdata = SDp->hostdata; | ||
109 | |||
110 | return hostdata->cmnd; | ||
111 | } | ||
112 | |||
101 | static inline void | 113 | static inline void |
102 | NCR_700_set_depth(struct scsi_device *SDp, __u8 depth) | 114 | NCR_700_set_depth(struct scsi_device *SDp, __u8 depth) |
103 | { | 115 | { |
104 | long l = (long)SDp->hostdata; | 116 | struct NCR_700_Device_Parameters *hostdata = SDp->hostdata; |
105 | 117 | ||
106 | l &= 0xffff00ff; | 118 | hostdata->depth = depth; |
107 | l |= 0xff00 & (depth << 8); | ||
108 | SDp->hostdata = (void *)l; | ||
109 | } | 119 | } |
110 | static inline __u8 | 120 | static inline __u8 |
111 | NCR_700_get_depth(struct scsi_device *SDp) | 121 | NCR_700_get_depth(struct scsi_device *SDp) |
112 | { | 122 | { |
113 | return ((((unsigned long)SDp->hostdata) & 0xff00)>>8); | 123 | struct NCR_700_Device_Parameters *hostdata = SDp->hostdata; |
124 | |||
125 | return hostdata->depth; | ||
114 | } | 126 | } |
115 | static inline int | 127 | static inline int |
116 | NCR_700_is_flag_set(struct scsi_device *SDp, __u32 flag) | 128 | NCR_700_is_flag_set(struct scsi_device *SDp, __u32 flag) |