aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@steeleye.com>2006-06-29 13:02:11 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-06-29 13:15:15 -0400
commit0f13fc09db68de92585558984bff1c51b87db72f (patch)
tree752bb8fa84e731f7877b74a033d1b90e2c060977 /drivers
parent53cb8a1f45e06a2627a6d89b151cccb95fa45cbf (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')
-rw-r--r--drivers/scsi/53c700.c56
-rw-r--r--drivers/scsi/53c700.h34
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);
174STATIC int NCR_700_host_reset(struct scsi_cmnd * SCpnt); 174STATIC int NCR_700_host_reset(struct scsi_cmnd * SCpnt);
175STATIC void NCR_700_chip_setup(struct Scsi_Host *host); 175STATIC void NCR_700_chip_setup(struct Scsi_Host *host);
176STATIC void NCR_700_chip_reset(struct Scsi_Host *host); 176STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
177STATIC int NCR_700_slave_alloc(struct scsi_device *SDpnt);
177STATIC int NCR_700_slave_configure(struct scsi_device *SDpnt); 178STATIC int NCR_700_slave_configure(struct scsi_device *SDpnt);
178STATIC void NCR_700_slave_destroy(struct scsi_device *SDpnt); 179STATIC void NCR_700_slave_destroy(struct scsi_device *SDpnt);
179static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth); 180static 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
184STATIC struct scsi_transport_template *NCR_700_transport_template = NULL; 185STATIC struct scsi_transport_template *NCR_700_transport_template = NULL;
185 186
186struct NCR_700_sense {
187 unsigned char cmnd[MAX_COMMAND_SIZE];
188};
189
190static char *NCR_700_phase[] = { 187static 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
2038STATIC int
2039NCR_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
2041STATIC int 2050STATIC int
2042NCR_700_slave_configure(struct scsi_device *SDp) 2051NCR_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 79struct 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
106static 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
101static inline void 113static inline void
102NCR_700_set_depth(struct scsi_device *SDp, __u8 depth) 114NCR_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}
110static inline __u8 120static inline __u8
111NCR_700_get_depth(struct scsi_device *SDp) 121NCR_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}
115static inline int 127static inline int
116NCR_700_is_flag_set(struct scsi_device *SDp, __u32 flag) 128NCR_700_is_flag_set(struct scsi_device *SDp, __u32 flag)