diff options
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 a97c80b57737..e239a6c29230 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, |
@@ -1583,6 +1584,24 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, | |||
1583 | } | 1584 | } |
1584 | } else if (cmd_type == TYPE_MSG) { | 1585 | } else if (cmd_type == TYPE_MSG) { |
1585 | switch (cmd) { | 1586 | switch (cmd) { |
1587 | case 0: /* ABORT message */ | ||
1588 | c->Request.CDBLen = 12; | ||
1589 | c->Request.Type.Attribute = ATTR_SIMPLE; | ||
1590 | c->Request.Type.Direction = XFER_WRITE; | ||
1591 | c->Request.Timeout = 0; | ||
1592 | c->Request.CDB[0] = cmd; /* abort */ | ||
1593 | c->Request.CDB[1] = 0; /* abort a command */ | ||
1594 | /* buff contains the tag of the command to abort */ | ||
1595 | memcpy(&c->Request.CDB[4], buff, 8); | ||
1596 | break; | ||
1597 | case 1: /* RESET message */ | ||
1598 | c->Request.CDBLen = 12; | ||
1599 | c->Request.Type.Attribute = ATTR_SIMPLE; | ||
1600 | c->Request.Type.Direction = XFER_WRITE; | ||
1601 | c->Request.Timeout = 0; | ||
1602 | memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); | ||
1603 | c->Request.CDB[0] = cmd; /* reset */ | ||
1604 | c->Request.CDB[1] = 0x04; /* reset a LUN */ | ||
1586 | case 3: /* No-Op message */ | 1605 | case 3: /* No-Op message */ |
1587 | c->Request.CDBLen = 1; | 1606 | c->Request.CDBLen = 1; |
1588 | c->Request.Type.Attribute = ATTR_SIMPLE; | 1607 | c->Request.Type.Attribute = ATTR_SIMPLE; |
@@ -1869,6 +1888,52 @@ static unsigned long pollcomplete(int ctlr) | |||
1869 | /* Invalid address to tell caller we ran out of time */ | 1888 | /* Invalid address to tell caller we ran out of time */ |
1870 | return 1; | 1889 | return 1; |
1871 | } | 1890 | } |
1891 | |||
1892 | static int add_sendcmd_reject(__u8 cmd, int ctlr, unsigned long complete) | ||
1893 | { | ||
1894 | /* We get in here if sendcmd() is polling for completions | ||
1895 | and gets some command back that it wasn't expecting -- | ||
1896 | something other than that which it just sent down. | ||
1897 | Ordinarily, that shouldn't happen, but it can happen when | ||
1898 | the scsi tape stuff gets into error handling mode, and | ||
1899 | starts using sendcmd() to try to abort commands and | ||
1900 | reset tape drives. In that case, sendcmd may pick up | ||
1901 | completions of commands that were sent to logical drives | ||
1902 | through the block i/o system, or cciss ioctls completing, etc. | ||
1903 | In that case, we need to save those completions for later | ||
1904 | processing by the interrupt handler. | ||
1905 | */ | ||
1906 | |||
1907 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
1908 | struct sendcmd_reject_list *srl = &hba[ctlr]->scsi_rejects; | ||
1909 | |||
1910 | /* If it's not the scsi tape stuff doing error handling, (abort */ | ||
1911 | /* or reset) then we don't expect anything weird. */ | ||
1912 | if (cmd != CCISS_RESET_MSG && cmd != CCISS_ABORT_MSG) { | ||
1913 | #endif | ||
1914 | printk( KERN_WARNING "cciss cciss%d: SendCmd " | ||
1915 | "Invalid command list address returned! (%lx)\n", | ||
1916 | ctlr, complete); | ||
1917 | /* not much we can do. */ | ||
1918 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
1919 | return 1; | ||
1920 | } | ||
1921 | |||
1922 | /* We've sent down an abort or reset, but something else | ||
1923 | has completed */ | ||
1924 | if (srl->ncompletions >= (NR_CMDS + 2)) { | ||
1925 | /* Uh oh. No room to save it for later... */ | ||
1926 | printk(KERN_WARNING "cciss%d: Sendcmd: Invalid command addr, " | ||
1927 | "reject list overflow, command lost!\n", ctlr); | ||
1928 | return 1; | ||
1929 | } | ||
1930 | /* Save it for later */ | ||
1931 | srl->complete[srl->ncompletions] = complete; | ||
1932 | srl->ncompletions++; | ||
1933 | #endif | ||
1934 | return 0; | ||
1935 | } | ||
1936 | |||
1872 | /* | 1937 | /* |
1873 | * Send a command to the controller, and wait for it to complete. | 1938 | * Send a command to the controller, and wait for it to complete. |
1874 | * Only used at init time. | 1939 | * Only used at init time. |
@@ -1891,7 +1956,7 @@ static int sendcmd( | |||
1891 | unsigned long complete; | 1956 | unsigned long complete; |
1892 | ctlr_info_t *info_p= hba[ctlr]; | 1957 | ctlr_info_t *info_p= hba[ctlr]; |
1893 | u64bit buff_dma_handle; | 1958 | u64bit buff_dma_handle; |
1894 | int status; | 1959 | int status, done = 0; |
1895 | 1960 | ||
1896 | if ((c = cmd_alloc(info_p, 1)) == NULL) { | 1961 | if ((c = cmd_alloc(info_p, 1)) == NULL) { |
1897 | printk(KERN_WARNING "cciss: unable to get memory"); | 1962 | printk(KERN_WARNING "cciss: unable to get memory"); |
@@ -1913,7 +1978,9 @@ resend_cmd1: | |||
1913 | info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF); | 1978 | info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF); |
1914 | 1979 | ||
1915 | /* Make sure there is room in the command FIFO */ | 1980 | /* Make sure there is room in the command FIFO */ |
1916 | /* Actually it should be completely empty at this time. */ | 1981 | /* Actually it should be completely empty at this time */ |
1982 | /* unless we are in here doing error handling for the scsi */ | ||
1983 | /* tape side of the driver. */ | ||
1917 | for (i = 200000; i > 0; i--) | 1984 | for (i = 200000; i > 0; i--) |
1918 | { | 1985 | { |
1919 | /* if fifo isn't full go */ | 1986 | /* if fifo isn't full go */ |
@@ -1930,13 +1997,25 @@ resend_cmd1: | |||
1930 | * Send the cmd | 1997 | * Send the cmd |
1931 | */ | 1998 | */ |
1932 | info_p->access.submit_command(info_p, c); | 1999 | info_p->access.submit_command(info_p, c); |
1933 | complete = pollcomplete(ctlr); | 2000 | done = 0; |
2001 | do { | ||
2002 | complete = pollcomplete(ctlr); | ||
1934 | 2003 | ||
1935 | #ifdef CCISS_DEBUG | 2004 | #ifdef CCISS_DEBUG |
1936 | printk(KERN_DEBUG "cciss: command completed\n"); | 2005 | printk(KERN_DEBUG "cciss: command completed\n"); |
1937 | #endif /* CCISS_DEBUG */ | 2006 | #endif /* CCISS_DEBUG */ |
1938 | 2007 | ||
1939 | if (complete != 1) { | 2008 | if (complete == 1) { |
2009 | printk( KERN_WARNING | ||
2010 | "cciss cciss%d: SendCmd Timeout out, " | ||
2011 | "No command list address returned!\n", | ||
2012 | ctlr); | ||
2013 | status = IO_ERROR; | ||
2014 | done = 1; | ||
2015 | break; | ||
2016 | } | ||
2017 | |||
2018 | /* This will need to change for direct lookup completions */ | ||
1940 | if ( (complete & CISS_ERROR_BIT) | 2019 | if ( (complete & CISS_ERROR_BIT) |
1941 | && (complete & ~CISS_ERROR_BIT) == c->busaddr) | 2020 | && (complete & ~CISS_ERROR_BIT) == c->busaddr) |
1942 | { | 2021 | { |
@@ -1976,6 +2055,10 @@ resend_cmd1: | |||
1976 | status = IO_ERROR; | 2055 | status = IO_ERROR; |
1977 | goto cleanup1; | 2056 | goto cleanup1; |
1978 | } | 2057 | } |
2058 | } else if (c->err_info->CommandStatus == CMD_UNABORTABLE) { | ||
2059 | printk(KERN_WARNING "cciss%d: command could not be aborted.\n", ctlr); | ||
2060 | status = IO_ERROR; | ||
2061 | goto cleanup1; | ||
1979 | } | 2062 | } |
1980 | printk(KERN_WARNING "ciss ciss%d: sendcmd" | 2063 | printk(KERN_WARNING "ciss ciss%d: sendcmd" |
1981 | " Error %x \n", ctlr, | 2064 | " Error %x \n", ctlr, |
@@ -1990,20 +2073,15 @@ resend_cmd1: | |||
1990 | goto cleanup1; | 2073 | goto cleanup1; |
1991 | } | 2074 | } |
1992 | } | 2075 | } |
2076 | /* This will need changing for direct lookup completions */ | ||
1993 | if (complete != c->busaddr) { | 2077 | if (complete != c->busaddr) { |
1994 | printk( KERN_WARNING "cciss cciss%d: SendCmd " | 2078 | if (add_sendcmd_reject(cmd, ctlr, complete) != 0) { |
1995 | "Invalid command list address returned! (%lx)\n", | 2079 | BUG(); /* we are pretty much hosed if we get here. */ |
1996 | ctlr, complete); | 2080 | } |
1997 | status = IO_ERROR; | 2081 | continue; |
1998 | goto cleanup1; | 2082 | } else |
1999 | } | 2083 | done = 1; |
2000 | } else { | 2084 | } while (!done); |
2001 | printk( KERN_WARNING | ||
2002 | "cciss cciss%d: SendCmd Timeout out, " | ||
2003 | "No command list address returned!\n", | ||
2004 | ctlr); | ||
2005 | status = IO_ERROR; | ||
2006 | } | ||
2007 | 2085 | ||
2008 | cleanup1: | 2086 | cleanup1: |
2009 | /* unlock the data buffer from DMA */ | 2087 | /* unlock the data buffer from DMA */ |
@@ -2011,6 +2089,11 @@ cleanup1: | |||
2011 | buff_dma_handle.val32.upper = c->SG[0].Addr.upper; | 2089 | buff_dma_handle.val32.upper = c->SG[0].Addr.upper; |
2012 | pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val, | 2090 | pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val, |
2013 | c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); | 2091 | c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); |
2092 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
2093 | /* if we saved some commands for later, process them now. */ | ||
2094 | if (info_p->scsi_rejects.ncompletions > 0) | ||
2095 | do_cciss_intr(0, info_p, NULL); | ||
2096 | #endif | ||
2014 | cmd_free(info_p, c, 1); | 2097 | cmd_free(info_p, c, 1); |
2015 | return (status); | 2098 | return (status); |
2016 | } | 2099 | } |
@@ -2335,6 +2418,48 @@ startio: | |||
2335 | start_io(h); | 2418 | start_io(h); |
2336 | } | 2419 | } |
2337 | 2420 | ||
2421 | static inline unsigned long get_next_completion(ctlr_info_t *h) | ||
2422 | { | ||
2423 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
2424 | /* Any rejects from sendcmd() lying around? Process them first */ | ||
2425 | if (h->scsi_rejects.ncompletions == 0) | ||
2426 | return h->access.command_completed(h); | ||
2427 | else { | ||
2428 | struct sendcmd_reject_list *srl; | ||
2429 | int n; | ||
2430 | srl = &h->scsi_rejects; | ||
2431 | n = --srl->ncompletions; | ||
2432 | /* printk("cciss%d: processing saved reject\n", h->ctlr); */ | ||
2433 | printk("p"); | ||
2434 | return srl->complete[n]; | ||
2435 | } | ||
2436 | #else | ||
2437 | return h->access.command_completed(h); | ||
2438 | #endif | ||
2439 | } | ||
2440 | |||
2441 | static inline int interrupt_pending(ctlr_info_t *h) | ||
2442 | { | ||
2443 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
2444 | return ( h->access.intr_pending(h) | ||
2445 | || (h->scsi_rejects.ncompletions > 0)); | ||
2446 | #else | ||
2447 | return h->access.intr_pending(h); | ||
2448 | #endif | ||
2449 | } | ||
2450 | |||
2451 | static inline long interrupt_not_for_us(ctlr_info_t *h) | ||
2452 | { | ||
2453 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
2454 | return (((h->access.intr_pending(h) == 0) || | ||
2455 | (h->interrupts_enabled == 0)) | ||
2456 | && (h->scsi_rejects.ncompletions == 0)); | ||
2457 | #else | ||
2458 | return (((h->access.intr_pending(h) == 0) || | ||
2459 | (h->interrupts_enabled == 0))); | ||
2460 | #endif | ||
2461 | } | ||
2462 | |||
2338 | static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) | 2463 | static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) |
2339 | { | 2464 | { |
2340 | ctlr_info_t *h = dev_id; | 2465 | ctlr_info_t *h = dev_id; |
@@ -2344,19 +2469,15 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
2344 | int j; | 2469 | int j; |
2345 | int start_queue = h->next_to_run; | 2470 | int start_queue = h->next_to_run; |
2346 | 2471 | ||
2347 | /* Is this interrupt for us? */ | 2472 | if (interrupt_not_for_us(h)) |
2348 | if (( h->access.intr_pending(h) == 0) || (h->interrupts_enabled == 0)) | ||
2349 | return IRQ_NONE; | 2473 | return IRQ_NONE; |
2350 | |||
2351 | /* | 2474 | /* |
2352 | * If there are completed commands in the completion queue, | 2475 | * If there are completed commands in the completion queue, |
2353 | * we had better do something about it. | 2476 | * we had better do something about it. |
2354 | */ | 2477 | */ |
2355 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | 2478 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); |
2356 | while( h->access.intr_pending(h)) | 2479 | while (interrupt_pending(h)) { |
2357 | { | 2480 | while((a = get_next_completion(h)) != FIFO_EMPTY) { |
2358 | while((a = h->access.command_completed(h)) != FIFO_EMPTY) | ||
2359 | { | ||
2360 | a1 = a; | 2481 | a1 = a; |
2361 | if ((a & 0x04)) { | 2482 | if ((a & 0x04)) { |
2362 | a2 = (a >> 3); | 2483 | a2 = (a >> 3); |
@@ -2963,7 +3084,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
2963 | printk( KERN_ERR "cciss: out of memory"); | 3084 | printk( KERN_ERR "cciss: out of memory"); |
2964 | goto clean4; | 3085 | goto clean4; |
2965 | } | 3086 | } |
2966 | 3087 | #ifdef CONFIG_CISS_SCSI_TAPE | |
3088 | hba[i]->scsi_rejects.complete = | ||
3089 | kmalloc(sizeof(hba[i]->scsi_rejects.complete[0]) * | ||
3090 | (NR_CMDS + 5), GFP_KERNEL); | ||
3091 | if (hba[i]->scsi_rejects.complete == NULL) { | ||
3092 | printk( KERN_ERR "cciss: out of memory"); | ||
3093 | goto clean4; | ||
3094 | } | ||
3095 | #endif | ||
2967 | spin_lock_init(&hba[i]->lock); | 3096 | spin_lock_init(&hba[i]->lock); |
2968 | 3097 | ||
2969 | /* Initialize the pdev driver private data. | 3098 | /* Initialize the pdev driver private data. |
@@ -3031,6 +3160,10 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3031 | return(1); | 3160 | return(1); |
3032 | 3161 | ||
3033 | clean4: | 3162 | clean4: |
3163 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
3164 | if(hba[i]->scsi_rejects.complete) | ||
3165 | kfree(hba[i]->scsi_rejects.complete); | ||
3166 | #endif | ||
3034 | kfree(hba[i]->cmd_pool_bits); | 3167 | kfree(hba[i]->cmd_pool_bits); |
3035 | if(hba[i]->cmd_pool) | 3168 | if(hba[i]->cmd_pool) |
3036 | pci_free_consistent(hba[i]->pdev, | 3169 | pci_free_consistent(hba[i]->pdev, |
@@ -3103,6 +3236,9 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev) | |||
3103 | pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), | 3236 | pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), |
3104 | hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); | 3237 | hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); |
3105 | kfree(hba[i]->cmd_pool_bits); | 3238 | kfree(hba[i]->cmd_pool_bits); |
3239 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
3240 | kfree(hba[i]->scsi_rejects.complete); | ||
3241 | #endif | ||
3106 | release_io_mem(hba[i]); | 3242 | release_io_mem(hba[i]); |
3107 | free_hba(i); | 3243 | free_hba(i); |
3108 | } | 3244 | } |