aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/cciss.c70
-rw-r--r--drivers/block/cciss.h1
-rw-r--r--drivers/block/cciss_cmd.h8
-rw-r--r--drivers/block/cciss_scsi.c1
4 files changed, 73 insertions, 7 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 3c6a6a21d540..a12b95eef18e 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -174,6 +174,8 @@ static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size,
174 unsigned int use_unit_num, unsigned int log_unit, __u8 page_code, 174 unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
175 int cmd_type); 175 int cmd_type);
176 176
177static void fail_all_cmds(unsigned long ctlr);
178
177#ifdef CONFIG_PROC_FS 179#ifdef CONFIG_PROC_FS
178static int cciss_proc_get_info(char *buffer, char **start, off_t offset, 180static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
179 int length, int *eof, void *data); 181 int length, int *eof, void *data);
@@ -387,6 +389,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
387 return NULL; 389 return NULL;
388 memset(c, 0, sizeof(CommandList_struct)); 390 memset(c, 0, sizeof(CommandList_struct));
389 391
392 c->cmdindex = -1;
393
390 c->err_info = (ErrorInfo_struct *)pci_alloc_consistent( 394 c->err_info = (ErrorInfo_struct *)pci_alloc_consistent(
391 h->pdev, sizeof(ErrorInfo_struct), 395 h->pdev, sizeof(ErrorInfo_struct),
392 &err_dma_handle); 396 &err_dma_handle);
@@ -417,6 +421,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
417 err_dma_handle = h->errinfo_pool_dhandle 421 err_dma_handle = h->errinfo_pool_dhandle
418 + i*sizeof(ErrorInfo_struct); 422 + i*sizeof(ErrorInfo_struct);
419 h->nr_allocs++; 423 h->nr_allocs++;
424
425 c->cmdindex = i;
420 } 426 }
421 427
422 c->busaddr = (__u32) cmd_dma_handle; 428 c->busaddr = (__u32) cmd_dma_handle;
@@ -2257,7 +2263,11 @@ queue:
2257 /* fill in the request */ 2263 /* fill in the request */
2258 drv = creq->rq_disk->private_data; 2264 drv = creq->rq_disk->private_data;
2259 c->Header.ReplyQueue = 0; // unused in simple mode 2265 c->Header.ReplyQueue = 0; // unused in simple mode
2260 c->Header.Tag.lower = c->busaddr; // use the physical address the cmd block for tag 2266 /* got command from pool, so use the command block index instead */
2267 /* for direct lookups. */
2268 /* The first 2 bits are reserved for controller error reporting. */
2269 c->Header.Tag.lower = (c->cmdindex << 3);
2270 c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */
2261 c->Header.LUN.LogDev.VolId= drv->LunID; 2271 c->Header.LUN.LogDev.VolId= drv->LunID;
2262 c->Header.LUN.LogDev.Mode = 1; 2272 c->Header.LUN.LogDev.Mode = 1;
2263 c->Request.CDBLen = 10; // 12 byte commands not in FW yet; 2273 c->Request.CDBLen = 10; // 12 byte commands not in FW yet;
@@ -2332,7 +2342,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
2332 ctlr_info_t *h = dev_id; 2342 ctlr_info_t *h = dev_id;
2333 CommandList_struct *c; 2343 CommandList_struct *c;
2334 unsigned long flags; 2344 unsigned long flags;
2335 __u32 a, a1; 2345 __u32 a, a1, a2;
2336 int j; 2346 int j;
2337 int start_queue = h->next_to_run; 2347 int start_queue = h->next_to_run;
2338 2348
@@ -2350,10 +2360,21 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
2350 while((a = h->access.command_completed(h)) != FIFO_EMPTY) 2360 while((a = h->access.command_completed(h)) != FIFO_EMPTY)
2351 { 2361 {
2352 a1 = a; 2362 a1 = a;
2363 if ((a & 0x04)) {
2364 a2 = (a >> 3);
2365 if (a2 >= NR_CMDS) {
2366 printk(KERN_WARNING "cciss: controller cciss%d failed, stopping.\n", h->ctlr);
2367 fail_all_cmds(h->ctlr);
2368 return IRQ_HANDLED;
2369 }
2370
2371 c = h->cmd_pool + a2;
2372 a = c->busaddr;
2373
2374 } else {
2353 a &= ~3; 2375 a &= ~3;
2354 if ((c = h->cmpQ) == NULL) 2376 if ((c = h->cmpQ) == NULL) {
2355 { 2377 printk(KERN_WARNING "cciss: Completion of %08x ignored\n", a1);
2356 printk(KERN_WARNING "cciss: Completion of %08lx ignored\n", (unsigned long)a1);
2357 continue; 2378 continue;
2358 } 2379 }
2359 while(c->busaddr != a) { 2380 while(c->busaddr != a) {
@@ -2361,6 +2382,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
2361 if (c == h->cmpQ) 2382 if (c == h->cmpQ)
2362 break; 2383 break;
2363 } 2384 }
2385 }
2364 /* 2386 /*
2365 * If we've found the command, take it off the 2387 * If we've found the command, take it off the
2366 * completion Q and free it 2388 * completion Q and free it
@@ -3124,5 +3146,43 @@ static void __exit cciss_cleanup(void)
3124 remove_proc_entry("cciss", proc_root_driver); 3146 remove_proc_entry("cciss", proc_root_driver);
3125} 3147}
3126 3148
3149static void fail_all_cmds(unsigned long ctlr)
3150{
3151 /* If we get here, the board is apparently dead. */
3152 ctlr_info_t *h = hba[ctlr];
3153 CommandList_struct *c;
3154 unsigned long flags;
3155
3156 printk(KERN_WARNING "cciss%d: controller not responding.\n", h->ctlr);
3157 h->alive = 0; /* the controller apparently died... */
3158
3159 spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
3160
3161 pci_disable_device(h->pdev); /* Make sure it is really dead. */
3162
3163 /* move everything off the request queue onto the completed queue */
3164 while( (c = h->reqQ) != NULL ) {
3165 removeQ(&(h->reqQ), c);
3166 h->Qdepth--;
3167 addQ (&(h->cmpQ), c);
3168 }
3169
3170 /* Now, fail everything on the completed queue with a HW error */
3171 while( (c = h->cmpQ) != NULL ) {
3172 removeQ(&h->cmpQ, c);
3173 c->err_info->CommandStatus = CMD_HARDWARE_ERR;
3174 if (c->cmd_type == CMD_RWREQ) {
3175 complete_command(h, c, 0);
3176 } else if (c->cmd_type == CMD_IOCTL_PEND)
3177 complete(c->waiting);
3178#ifdef CONFIG_CISS_SCSI_TAPE
3179 else if (c->cmd_type == CMD_SCSI)
3180 complete_scsi_command(c, 0, 0);
3181#endif
3182 }
3183 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
3184 return;
3185}
3186
3127module_init(cciss_init); 3187module_init(cciss_init);
3128module_exit(cciss_cleanup); 3188module_exit(cciss_cleanup);
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index dec27a961120..ef277baee9fd 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -101,6 +101,7 @@ struct ctlr_info
101#ifdef CONFIG_CISS_SCSI_TAPE 101#ifdef CONFIG_CISS_SCSI_TAPE
102 void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ 102 void *scsi_ctlr; /* ptr to structure containing scsi related stuff */
103#endif 103#endif
104 unsigned char alive;
104}; 105};
105 106
106/* Defining the diffent access_menthods */ 107/* Defining the diffent access_menthods */
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h
index a88a88817623..53fea549ba8b 100644
--- a/drivers/block/cciss_cmd.h
+++ b/drivers/block/cciss_cmd.h
@@ -226,6 +226,10 @@ typedef struct _ErrorInfo_struct {
226#define CMD_MSG_DONE 0x04 226#define CMD_MSG_DONE 0x04
227#define CMD_MSG_TIMEOUT 0x05 227#define CMD_MSG_TIMEOUT 0x05
228 228
229/* This structure needs to be divisible by 8 for new
230 * indexing method.
231 */
232#define PADSIZE (sizeof(long) - 4)
229typedef struct _CommandList_struct { 233typedef struct _CommandList_struct {
230 CommandListHeader_struct Header; 234 CommandListHeader_struct Header;
231 RequestBlock_struct Request; 235 RequestBlock_struct Request;
@@ -236,14 +240,14 @@ typedef struct _CommandList_struct {
236 ErrorInfo_struct * err_info; /* pointer to the allocated mem */ 240 ErrorInfo_struct * err_info; /* pointer to the allocated mem */
237 int ctlr; 241 int ctlr;
238 int cmd_type; 242 int cmd_type;
243 long cmdindex;
239 struct _CommandList_struct *prev; 244 struct _CommandList_struct *prev;
240 struct _CommandList_struct *next; 245 struct _CommandList_struct *next;
241 struct request * rq; 246 struct request * rq;
242 struct completion *waiting; 247 struct completion *waiting;
243 int retry_count; 248 int retry_count;
244#ifdef CONFIG_CISS_SCSI_TAPE
245 void * scsi_cmd; 249 void * scsi_cmd;
246#endif 250 char pad[PADSIZE];
247} CommandList_struct; 251} CommandList_struct;
248 252
249//Configuration Table Structure 253//Configuration Table Structure
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index f16e3caed58a..df4afacc75d7 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -93,6 +93,7 @@ struct cciss_scsi_cmd_stack_elem_t {
93 CommandList_struct cmd; 93 CommandList_struct cmd;
94 ErrorInfo_struct Err; 94 ErrorInfo_struct Err;
95 __u32 busaddr; 95 __u32 busaddr;
96 __u32 pad;
96}; 97};
97 98
98#pragma pack() 99#pragma pack()