diff options
author | mike.miller@hp.com <mike.miller@hp.com> | 2005-11-04 13:30:37 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-11-06 15:12:49 -0500 |
commit | 3da8b713da723e78a03f0404beedf3cc6f4f860b (patch) | |
tree | a09cc4308fcf0087aa607029bd71825b568d97e5 /drivers/block/cciss.c | |
parent | 13bf50d1f21b2f11452c4b8a82a91319791f8ba3 (diff) |
[SCSI] cciss: scsi error handling
This patch adds SCSI error handling code to the SCSI portion
of the cciss driver.
Signed-off-by: Stephen M. Cameron <steve.cameron@hp.com>
Acked-by: Mike Miller <mike.miller@hp.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r-- | drivers/block/cciss.c | 188 |
1 files changed, 162 insertions, 26 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 486b6e1c7dfb..482786068ff9 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -148,6 +148,7 @@ static struct board_type products[] = { | |||
148 | static ctlr_info_t *hba[MAX_CTLR]; | 148 | static ctlr_info_t *hba[MAX_CTLR]; |
149 | 149 | ||
150 | static void do_cciss_request(request_queue_t *q); | 150 | static void do_cciss_request(request_queue_t *q); |
151 | static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs); | ||
151 | static int cciss_open(struct inode *inode, struct file *filep); | 152 | static int cciss_open(struct inode *inode, struct file *filep); |
152 | static int cciss_release(struct inode *inode, struct file *filep); | 153 | static int cciss_release(struct inode *inode, struct file *filep); |
153 | static int cciss_ioctl(struct inode *inode, struct file *filep, | 154 | static int cciss_ioctl(struct inode *inode, struct file *filep, |
@@ -1586,6 +1587,24 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, | |||
1586 | } | 1587 | } |
1587 | } else if (cmd_type == TYPE_MSG) { | 1588 | } else if (cmd_type == TYPE_MSG) { |
1588 | switch (cmd) { | 1589 | switch (cmd) { |
1590 | case 0: /* ABORT message */ | ||
1591 | c->Request.CDBLen = 12; | ||
1592 | c->Request.Type.Attribute = ATTR_SIMPLE; | ||
1593 | c->Request.Type.Direction = XFER_WRITE; | ||
1594 | c->Request.Timeout = 0; | ||
1595 | c->Request.CDB[0] = cmd; /* abort */ | ||
1596 | c->Request.CDB[1] = 0; /* abort a command */ | ||
1597 | /* buff contains the tag of the command to abort */ | ||
1598 | memcpy(&c->Request.CDB[4], buff, 8); | ||
1599 | break; | ||
1600 | case 1: /* RESET message */ | ||
1601 | c->Request.CDBLen = 12; | ||
1602 | c->Request.Type.Attribute = ATTR_SIMPLE; | ||
1603 | c->Request.Type.Direction = XFER_WRITE; | ||
1604 | c->Request.Timeout = 0; | ||
1605 | memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); | ||
1606 | c->Request.CDB[0] = cmd; /* reset */ | ||
1607 | c->Request.CDB[1] = 0x04; /* reset a LUN */ | ||
1589 | case 3: /* No-Op message */ | 1608 | case 3: /* No-Op message */ |
1590 | c->Request.CDBLen = 1; | 1609 | c->Request.CDBLen = 1; |
1591 | c->Request.Type.Attribute = ATTR_SIMPLE; | 1610 | c->Request.Type.Attribute = ATTR_SIMPLE; |
@@ -1872,6 +1891,52 @@ static unsigned long pollcomplete(int ctlr) | |||
1872 | /* Invalid address to tell caller we ran out of time */ | 1891 | /* Invalid address to tell caller we ran out of time */ |
1873 | return 1; | 1892 | return 1; |
1874 | } | 1893 | } |
1894 | |||
1895 | static int add_sendcmd_reject(__u8 cmd, int ctlr, unsigned long complete) | ||
1896 | { | ||
1897 | /* We get in here if sendcmd() is polling for completions | ||
1898 | and gets some command back that it wasn't expecting -- | ||
1899 | something other than that which it just sent down. | ||
1900 | Ordinarily, that shouldn't happen, but it can happen when | ||
1901 | the scsi tape stuff gets into error handling mode, and | ||
1902 | starts using sendcmd() to try to abort commands and | ||
1903 | reset tape drives. In that case, sendcmd may pick up | ||
1904 | completions of commands that were sent to logical drives | ||
1905 | through the block i/o system, or cciss ioctls completing, etc. | ||
1906 | In that case, we need to save those completions for later | ||
1907 | processing by the interrupt handler. | ||
1908 | */ | ||
1909 | |||
1910 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
1911 | struct sendcmd_reject_list *srl = &hba[ctlr]->scsi_rejects; | ||
1912 | |||
1913 | /* If it's not the scsi tape stuff doing error handling, (abort */ | ||
1914 | /* or reset) then we don't expect anything weird. */ | ||
1915 | if (cmd != CCISS_RESET_MSG && cmd != CCISS_ABORT_MSG) { | ||
1916 | #endif | ||
1917 | printk( KERN_WARNING "cciss cciss%d: SendCmd " | ||
1918 | "Invalid command list address returned! (%lx)\n", | ||
1919 | ctlr, complete); | ||
1920 | /* not much we can do. */ | ||
1921 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
1922 | return 1; | ||
1923 | } | ||
1924 | |||
1925 | /* We've sent down an abort or reset, but something else | ||
1926 | has completed */ | ||
1927 | if (srl->ncompletions >= (NR_CMDS + 2)) { | ||
1928 | /* Uh oh. No room to save it for later... */ | ||
1929 | printk(KERN_WARNING "cciss%d: Sendcmd: Invalid command addr, " | ||
1930 | "reject list overflow, command lost!\n", ctlr); | ||
1931 | return 1; | ||
1932 | } | ||
1933 | /* Save it for later */ | ||
1934 | srl->complete[srl->ncompletions] = complete; | ||
1935 | srl->ncompletions++; | ||
1936 | #endif | ||
1937 | return 0; | ||
1938 | } | ||
1939 | |||
1875 | /* | 1940 | /* |
1876 | * Send a command to the controller, and wait for it to complete. | 1941 | * Send a command to the controller, and wait for it to complete. |
1877 | * Only used at init time. | 1942 | * Only used at init time. |
@@ -1894,7 +1959,7 @@ static int sendcmd( | |||
1894 | unsigned long complete; | 1959 | unsigned long complete; |
1895 | ctlr_info_t *info_p= hba[ctlr]; | 1960 | ctlr_info_t *info_p= hba[ctlr]; |
1896 | u64bit buff_dma_handle; | 1961 | u64bit buff_dma_handle; |
1897 | int status; | 1962 | int status, done = 0; |
1898 | 1963 | ||
1899 | if ((c = cmd_alloc(info_p, 1)) == NULL) { | 1964 | if ((c = cmd_alloc(info_p, 1)) == NULL) { |
1900 | printk(KERN_WARNING "cciss: unable to get memory"); | 1965 | printk(KERN_WARNING "cciss: unable to get memory"); |
@@ -1916,7 +1981,9 @@ resend_cmd1: | |||
1916 | info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF); | 1981 | info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF); |
1917 | 1982 | ||
1918 | /* Make sure there is room in the command FIFO */ | 1983 | /* Make sure there is room in the command FIFO */ |
1919 | /* Actually it should be completely empty at this time. */ | 1984 | /* Actually it should be completely empty at this time */ |
1985 | /* unless we are in here doing error handling for the scsi */ | ||
1986 | /* tape side of the driver. */ | ||
1920 | for (i = 200000; i > 0; i--) | 1987 | for (i = 200000; i > 0; i--) |
1921 | { | 1988 | { |
1922 | /* if fifo isn't full go */ | 1989 | /* if fifo isn't full go */ |
@@ -1933,13 +2000,25 @@ resend_cmd1: | |||
1933 | * Send the cmd | 2000 | * Send the cmd |
1934 | */ | 2001 | */ |
1935 | info_p->access.submit_command(info_p, c); | 2002 | info_p->access.submit_command(info_p, c); |
1936 | complete = pollcomplete(ctlr); | 2003 | done = 0; |
2004 | do { | ||
2005 | complete = pollcomplete(ctlr); | ||
1937 | 2006 | ||
1938 | #ifdef CCISS_DEBUG | 2007 | #ifdef CCISS_DEBUG |
1939 | printk(KERN_DEBUG "cciss: command completed\n"); | 2008 | printk(KERN_DEBUG "cciss: command completed\n"); |
1940 | #endif /* CCISS_DEBUG */ | 2009 | #endif /* CCISS_DEBUG */ |
1941 | 2010 | ||
1942 | if (complete != 1) { | 2011 | if (complete == 1) { |
2012 | printk( KERN_WARNING | ||
2013 | "cciss cciss%d: SendCmd Timeout out, " | ||
2014 | "No command list address returned!\n", | ||
2015 | ctlr); | ||
2016 | status = IO_ERROR; | ||
2017 | done = 1; | ||
2018 | break; | ||
2019 | } | ||
2020 | |||
2021 | /* This will need to change for direct lookup completions */ | ||
1943 | if ( (complete & CISS_ERROR_BIT) | 2022 | if ( (complete & CISS_ERROR_BIT) |
1944 | && (complete & ~CISS_ERROR_BIT) == c->busaddr) | 2023 | && (complete & ~CISS_ERROR_BIT) == c->busaddr) |
1945 | { | 2024 | { |
@@ -1979,6 +2058,10 @@ resend_cmd1: | |||
1979 | status = IO_ERROR; | 2058 | status = IO_ERROR; |
1980 | goto cleanup1; | 2059 | goto cleanup1; |
1981 | } | 2060 | } |
2061 | } else if (c->err_info->CommandStatus == CMD_UNABORTABLE) { | ||
2062 | printk(KERN_WARNING "cciss%d: command could not be aborted.\n", ctlr); | ||
2063 | status = IO_ERROR; | ||
2064 | goto cleanup1; | ||
1982 | } | 2065 | } |
1983 | printk(KERN_WARNING "ciss ciss%d: sendcmd" | 2066 | printk(KERN_WARNING "ciss ciss%d: sendcmd" |
1984 | " Error %x \n", ctlr, | 2067 | " Error %x \n", ctlr, |
@@ -1993,20 +2076,15 @@ resend_cmd1: | |||
1993 | goto cleanup1; | 2076 | goto cleanup1; |
1994 | } | 2077 | } |
1995 | } | 2078 | } |
2079 | /* This will need changing for direct lookup completions */ | ||
1996 | if (complete != c->busaddr) { | 2080 | if (complete != c->busaddr) { |
1997 | printk( KERN_WARNING "cciss cciss%d: SendCmd " | 2081 | if (add_sendcmd_reject(cmd, ctlr, complete) != 0) { |
1998 | "Invalid command list address returned! (%lx)\n", | 2082 | BUG(); /* we are pretty much hosed if we get here. */ |
1999 | ctlr, complete); | 2083 | } |
2000 | status = IO_ERROR; | 2084 | continue; |
2001 | goto cleanup1; | 2085 | } else |
2002 | } | 2086 | done = 1; |
2003 | } else { | 2087 | } while (!done); |
2004 | printk( KERN_WARNING | ||
2005 | "cciss cciss%d: SendCmd Timeout out, " | ||
2006 | "No command list address returned!\n", | ||
2007 | ctlr); | ||
2008 | status = IO_ERROR; | ||
2009 | } | ||
2010 | 2088 | ||
2011 | cleanup1: | 2089 | cleanup1: |
2012 | /* unlock the data buffer from DMA */ | 2090 | /* unlock the data buffer from DMA */ |
@@ -2014,6 +2092,11 @@ cleanup1: | |||
2014 | buff_dma_handle.val32.upper = c->SG[0].Addr.upper; | 2092 | buff_dma_handle.val32.upper = c->SG[0].Addr.upper; |
2015 | pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val, | 2093 | pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val, |
2016 | c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); | 2094 | c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); |
2095 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
2096 | /* if we saved some commands for later, process them now. */ | ||
2097 | if (info_p->scsi_rejects.ncompletions > 0) | ||
2098 | do_cciss_intr(0, info_p, NULL); | ||
2099 | #endif | ||
2017 | cmd_free(info_p, c, 1); | 2100 | cmd_free(info_p, c, 1); |
2018 | return (status); | 2101 | return (status); |
2019 | } | 2102 | } |
@@ -2338,6 +2421,48 @@ startio: | |||
2338 | start_io(h); | 2421 | start_io(h); |
2339 | } | 2422 | } |
2340 | 2423 | ||
2424 | static inline unsigned long get_next_completion(ctlr_info_t *h) | ||
2425 | { | ||
2426 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
2427 | /* Any rejects from sendcmd() lying around? Process them first */ | ||
2428 | if (h->scsi_rejects.ncompletions == 0) | ||
2429 | return h->access.command_completed(h); | ||
2430 | else { | ||
2431 | struct sendcmd_reject_list *srl; | ||
2432 | int n; | ||
2433 | srl = &h->scsi_rejects; | ||
2434 | n = --srl->ncompletions; | ||
2435 | /* printk("cciss%d: processing saved reject\n", h->ctlr); */ | ||
2436 | printk("p"); | ||
2437 | return srl->complete[n]; | ||
2438 | } | ||
2439 | #else | ||
2440 | return h->access.command_completed(h); | ||
2441 | #endif | ||
2442 | } | ||
2443 | |||
2444 | static inline int interrupt_pending(ctlr_info_t *h) | ||
2445 | { | ||
2446 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
2447 | return ( h->access.intr_pending(h) | ||
2448 | || (h->scsi_rejects.ncompletions > 0)); | ||
2449 | #else | ||
2450 | return h->access.intr_pending(h); | ||
2451 | #endif | ||
2452 | } | ||
2453 | |||
2454 | static inline long interrupt_not_for_us(ctlr_info_t *h) | ||
2455 | { | ||
2456 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
2457 | return (((h->access.intr_pending(h) == 0) || | ||
2458 | (h->interrupts_enabled == 0)) | ||
2459 | && (h->scsi_rejects.ncompletions == 0)); | ||
2460 | #else | ||
2461 | return (((h->access.intr_pending(h) == 0) || | ||
2462 | (h->interrupts_enabled == 0))); | ||
2463 | #endif | ||
2464 | } | ||
2465 | |||
2341 | static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) | 2466 | static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) |
2342 | { | 2467 | { |
2343 | ctlr_info_t *h = dev_id; | 2468 | ctlr_info_t *h = dev_id; |
@@ -2347,19 +2472,15 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
2347 | int j; | 2472 | int j; |
2348 | int start_queue = h->next_to_run; | 2473 | int start_queue = h->next_to_run; |
2349 | 2474 | ||
2350 | /* Is this interrupt for us? */ | 2475 | if (interrupt_not_for_us(h)) |
2351 | if (( h->access.intr_pending(h) == 0) || (h->interrupts_enabled == 0)) | ||
2352 | return IRQ_NONE; | 2476 | return IRQ_NONE; |
2353 | |||
2354 | /* | 2477 | /* |
2355 | * If there are completed commands in the completion queue, | 2478 | * If there are completed commands in the completion queue, |
2356 | * we had better do something about it. | 2479 | * we had better do something about it. |
2357 | */ | 2480 | */ |
2358 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | 2481 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); |
2359 | while( h->access.intr_pending(h)) | 2482 | while (interrupt_pending(h)) { |
2360 | { | 2483 | while((a = get_next_completion(h)) != FIFO_EMPTY) { |
2361 | while((a = h->access.command_completed(h)) != FIFO_EMPTY) | ||
2362 | { | ||
2363 | a1 = a; | 2484 | a1 = a; |
2364 | if ((a & 0x04)) { | 2485 | if ((a & 0x04)) { |
2365 | a2 = (a >> 3); | 2486 | a2 = (a >> 3); |
@@ -2966,7 +3087,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
2966 | printk( KERN_ERR "cciss: out of memory"); | 3087 | printk( KERN_ERR "cciss: out of memory"); |
2967 | goto clean4; | 3088 | goto clean4; |
2968 | } | 3089 | } |
2969 | 3090 | #ifdef CONFIG_CISS_SCSI_TAPE | |
3091 | hba[i]->scsi_rejects.complete = | ||
3092 | kmalloc(sizeof(hba[i]->scsi_rejects.complete[0]) * | ||
3093 | (NR_CMDS + 5), GFP_KERNEL); | ||
3094 | if (hba[i]->scsi_rejects.complete == NULL) { | ||
3095 | printk( KERN_ERR "cciss: out of memory"); | ||
3096 | goto clean4; | ||
3097 | } | ||
3098 | #endif | ||
2970 | spin_lock_init(&hba[i]->lock); | 3099 | spin_lock_init(&hba[i]->lock); |
2971 | 3100 | ||
2972 | /* Initialize the pdev driver private data. | 3101 | /* Initialize the pdev driver private data. |
@@ -3034,6 +3163,10 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3034 | return(1); | 3163 | return(1); |
3035 | 3164 | ||
3036 | clean4: | 3165 | clean4: |
3166 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
3167 | if(hba[i]->scsi_rejects.complete) | ||
3168 | kfree(hba[i]->scsi_rejects.complete); | ||
3169 | #endif | ||
3037 | if(hba[i]->cmd_pool_bits) | 3170 | if(hba[i]->cmd_pool_bits) |
3038 | kfree(hba[i]->cmd_pool_bits); | 3171 | kfree(hba[i]->cmd_pool_bits); |
3039 | if(hba[i]->cmd_pool) | 3172 | if(hba[i]->cmd_pool) |
@@ -3107,6 +3240,9 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev) | |||
3107 | pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), | 3240 | pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), |
3108 | hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); | 3241 | hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); |
3109 | kfree(hba[i]->cmd_pool_bits); | 3242 | kfree(hba[i]->cmd_pool_bits); |
3243 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
3244 | kfree(hba[i]->scsi_rejects.complete); | ||
3245 | #endif | ||
3110 | release_io_mem(hba[i]); | 3246 | release_io_mem(hba[i]); |
3111 | free_hba(i); | 3247 | free_hba(i); |
3112 | } | 3248 | } |