diff options
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r-- | drivers/block/cciss.c | 227 |
1 files changed, 189 insertions, 38 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index a97c80b57737..c3441b3f086e 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, |
@@ -1016,10 +1017,11 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, | |||
1016 | status = -ENOMEM; | 1017 | status = -ENOMEM; |
1017 | goto cleanup1; | 1018 | goto cleanup1; |
1018 | } | 1019 | } |
1019 | if (ioc->Request.Type.Direction == XFER_WRITE && | 1020 | if (ioc->Request.Type.Direction == XFER_WRITE) { |
1020 | copy_from_user(buff[sg_used], data_ptr, sz)) { | 1021 | if (copy_from_user(buff[sg_used], data_ptr, sz)) { |
1021 | status = -ENOMEM; | 1022 | status = -ENOMEM; |
1022 | goto cleanup1; | 1023 | goto cleanup1; |
1024 | } | ||
1023 | } else { | 1025 | } else { |
1024 | memset(buff[sg_used], 0, sz); | 1026 | memset(buff[sg_used], 0, sz); |
1025 | } | 1027 | } |
@@ -1137,8 +1139,14 @@ static int revalidate_allvol(ctlr_info_t *host) | |||
1137 | 1139 | ||
1138 | for(i=0; i< NWD; i++) { | 1140 | for(i=0; i< NWD; i++) { |
1139 | struct gendisk *disk = host->gendisk[i]; | 1141 | struct gendisk *disk = host->gendisk[i]; |
1140 | if (disk->flags & GENHD_FL_UP) | 1142 | if (disk) { |
1141 | del_gendisk(disk); | 1143 | request_queue_t *q = disk->queue; |
1144 | |||
1145 | if (disk->flags & GENHD_FL_UP) | ||
1146 | del_gendisk(disk); | ||
1147 | if (q) | ||
1148 | blk_cleanup_queue(q); | ||
1149 | } | ||
1142 | } | 1150 | } |
1143 | 1151 | ||
1144 | /* | 1152 | /* |
@@ -1452,10 +1460,14 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, | |||
1452 | * allows us to delete disk zero but keep the controller registered. | 1460 | * allows us to delete disk zero but keep the controller registered. |
1453 | */ | 1461 | */ |
1454 | if (h->gendisk[0] != disk){ | 1462 | if (h->gendisk[0] != disk){ |
1455 | if (disk->flags & GENHD_FL_UP){ | 1463 | if (disk) { |
1456 | blk_cleanup_queue(disk->queue); | 1464 | request_queue_t *q = disk->queue; |
1457 | del_gendisk(disk); | 1465 | if (disk->flags & GENHD_FL_UP) |
1458 | drv->queue = NULL; | 1466 | del_gendisk(disk); |
1467 | if (q) { | ||
1468 | blk_cleanup_queue(q); | ||
1469 | drv->queue = NULL; | ||
1470 | } | ||
1459 | } | 1471 | } |
1460 | } | 1472 | } |
1461 | 1473 | ||
@@ -1583,6 +1595,24 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, | |||
1583 | } | 1595 | } |
1584 | } else if (cmd_type == TYPE_MSG) { | 1596 | } else if (cmd_type == TYPE_MSG) { |
1585 | switch (cmd) { | 1597 | switch (cmd) { |
1598 | case 0: /* ABORT message */ | ||
1599 | c->Request.CDBLen = 12; | ||
1600 | c->Request.Type.Attribute = ATTR_SIMPLE; | ||
1601 | c->Request.Type.Direction = XFER_WRITE; | ||
1602 | c->Request.Timeout = 0; | ||
1603 | c->Request.CDB[0] = cmd; /* abort */ | ||
1604 | c->Request.CDB[1] = 0; /* abort a command */ | ||
1605 | /* buff contains the tag of the command to abort */ | ||
1606 | memcpy(&c->Request.CDB[4], buff, 8); | ||
1607 | break; | ||
1608 | case 1: /* RESET message */ | ||
1609 | c->Request.CDBLen = 12; | ||
1610 | c->Request.Type.Attribute = ATTR_SIMPLE; | ||
1611 | c->Request.Type.Direction = XFER_WRITE; | ||
1612 | c->Request.Timeout = 0; | ||
1613 | memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); | ||
1614 | c->Request.CDB[0] = cmd; /* reset */ | ||
1615 | c->Request.CDB[1] = 0x04; /* reset a LUN */ | ||
1586 | case 3: /* No-Op message */ | 1616 | case 3: /* No-Op message */ |
1587 | c->Request.CDBLen = 1; | 1617 | c->Request.CDBLen = 1; |
1588 | c->Request.Type.Attribute = ATTR_SIMPLE; | 1618 | c->Request.Type.Attribute = ATTR_SIMPLE; |
@@ -1869,6 +1899,52 @@ static unsigned long pollcomplete(int ctlr) | |||
1869 | /* Invalid address to tell caller we ran out of time */ | 1899 | /* Invalid address to tell caller we ran out of time */ |
1870 | return 1; | 1900 | return 1; |
1871 | } | 1901 | } |
1902 | |||
1903 | static int add_sendcmd_reject(__u8 cmd, int ctlr, unsigned long complete) | ||
1904 | { | ||
1905 | /* We get in here if sendcmd() is polling for completions | ||
1906 | and gets some command back that it wasn't expecting -- | ||
1907 | something other than that which it just sent down. | ||
1908 | Ordinarily, that shouldn't happen, but it can happen when | ||
1909 | the scsi tape stuff gets into error handling mode, and | ||
1910 | starts using sendcmd() to try to abort commands and | ||
1911 | reset tape drives. In that case, sendcmd may pick up | ||
1912 | completions of commands that were sent to logical drives | ||
1913 | through the block i/o system, or cciss ioctls completing, etc. | ||
1914 | In that case, we need to save those completions for later | ||
1915 | processing by the interrupt handler. | ||
1916 | */ | ||
1917 | |||
1918 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
1919 | struct sendcmd_reject_list *srl = &hba[ctlr]->scsi_rejects; | ||
1920 | |||
1921 | /* If it's not the scsi tape stuff doing error handling, (abort */ | ||
1922 | /* or reset) then we don't expect anything weird. */ | ||
1923 | if (cmd != CCISS_RESET_MSG && cmd != CCISS_ABORT_MSG) { | ||
1924 | #endif | ||
1925 | printk( KERN_WARNING "cciss cciss%d: SendCmd " | ||
1926 | "Invalid command list address returned! (%lx)\n", | ||
1927 | ctlr, complete); | ||
1928 | /* not much we can do. */ | ||
1929 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
1930 | return 1; | ||
1931 | } | ||
1932 | |||
1933 | /* We've sent down an abort or reset, but something else | ||
1934 | has completed */ | ||
1935 | if (srl->ncompletions >= (NR_CMDS + 2)) { | ||
1936 | /* Uh oh. No room to save it for later... */ | ||
1937 | printk(KERN_WARNING "cciss%d: Sendcmd: Invalid command addr, " | ||
1938 | "reject list overflow, command lost!\n", ctlr); | ||
1939 | return 1; | ||
1940 | } | ||
1941 | /* Save it for later */ | ||
1942 | srl->complete[srl->ncompletions] = complete; | ||
1943 | srl->ncompletions++; | ||
1944 | #endif | ||
1945 | return 0; | ||
1946 | } | ||
1947 | |||
1872 | /* | 1948 | /* |
1873 | * Send a command to the controller, and wait for it to complete. | 1949 | * Send a command to the controller, and wait for it to complete. |
1874 | * Only used at init time. | 1950 | * Only used at init time. |
@@ -1891,7 +1967,7 @@ static int sendcmd( | |||
1891 | unsigned long complete; | 1967 | unsigned long complete; |
1892 | ctlr_info_t *info_p= hba[ctlr]; | 1968 | ctlr_info_t *info_p= hba[ctlr]; |
1893 | u64bit buff_dma_handle; | 1969 | u64bit buff_dma_handle; |
1894 | int status; | 1970 | int status, done = 0; |
1895 | 1971 | ||
1896 | if ((c = cmd_alloc(info_p, 1)) == NULL) { | 1972 | if ((c = cmd_alloc(info_p, 1)) == NULL) { |
1897 | printk(KERN_WARNING "cciss: unable to get memory"); | 1973 | printk(KERN_WARNING "cciss: unable to get memory"); |
@@ -1913,7 +1989,9 @@ resend_cmd1: | |||
1913 | info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF); | 1989 | info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF); |
1914 | 1990 | ||
1915 | /* Make sure there is room in the command FIFO */ | 1991 | /* Make sure there is room in the command FIFO */ |
1916 | /* Actually it should be completely empty at this time. */ | 1992 | /* Actually it should be completely empty at this time */ |
1993 | /* unless we are in here doing error handling for the scsi */ | ||
1994 | /* tape side of the driver. */ | ||
1917 | for (i = 200000; i > 0; i--) | 1995 | for (i = 200000; i > 0; i--) |
1918 | { | 1996 | { |
1919 | /* if fifo isn't full go */ | 1997 | /* if fifo isn't full go */ |
@@ -1930,13 +2008,25 @@ resend_cmd1: | |||
1930 | * Send the cmd | 2008 | * Send the cmd |
1931 | */ | 2009 | */ |
1932 | info_p->access.submit_command(info_p, c); | 2010 | info_p->access.submit_command(info_p, c); |
1933 | complete = pollcomplete(ctlr); | 2011 | done = 0; |
2012 | do { | ||
2013 | complete = pollcomplete(ctlr); | ||
1934 | 2014 | ||
1935 | #ifdef CCISS_DEBUG | 2015 | #ifdef CCISS_DEBUG |
1936 | printk(KERN_DEBUG "cciss: command completed\n"); | 2016 | printk(KERN_DEBUG "cciss: command completed\n"); |
1937 | #endif /* CCISS_DEBUG */ | 2017 | #endif /* CCISS_DEBUG */ |
1938 | 2018 | ||
1939 | if (complete != 1) { | 2019 | if (complete == 1) { |
2020 | printk( KERN_WARNING | ||
2021 | "cciss cciss%d: SendCmd Timeout out, " | ||
2022 | "No command list address returned!\n", | ||
2023 | ctlr); | ||
2024 | status = IO_ERROR; | ||
2025 | done = 1; | ||
2026 | break; | ||
2027 | } | ||
2028 | |||
2029 | /* This will need to change for direct lookup completions */ | ||
1940 | if ( (complete & CISS_ERROR_BIT) | 2030 | if ( (complete & CISS_ERROR_BIT) |
1941 | && (complete & ~CISS_ERROR_BIT) == c->busaddr) | 2031 | && (complete & ~CISS_ERROR_BIT) == c->busaddr) |
1942 | { | 2032 | { |
@@ -1976,6 +2066,10 @@ resend_cmd1: | |||
1976 | status = IO_ERROR; | 2066 | status = IO_ERROR; |
1977 | goto cleanup1; | 2067 | goto cleanup1; |
1978 | } | 2068 | } |
2069 | } else if (c->err_info->CommandStatus == CMD_UNABORTABLE) { | ||
2070 | printk(KERN_WARNING "cciss%d: command could not be aborted.\n", ctlr); | ||
2071 | status = IO_ERROR; | ||
2072 | goto cleanup1; | ||
1979 | } | 2073 | } |
1980 | printk(KERN_WARNING "ciss ciss%d: sendcmd" | 2074 | printk(KERN_WARNING "ciss ciss%d: sendcmd" |
1981 | " Error %x \n", ctlr, | 2075 | " Error %x \n", ctlr, |
@@ -1990,20 +2084,15 @@ resend_cmd1: | |||
1990 | goto cleanup1; | 2084 | goto cleanup1; |
1991 | } | 2085 | } |
1992 | } | 2086 | } |
2087 | /* This will need changing for direct lookup completions */ | ||
1993 | if (complete != c->busaddr) { | 2088 | if (complete != c->busaddr) { |
1994 | printk( KERN_WARNING "cciss cciss%d: SendCmd " | 2089 | if (add_sendcmd_reject(cmd, ctlr, complete) != 0) { |
1995 | "Invalid command list address returned! (%lx)\n", | 2090 | BUG(); /* we are pretty much hosed if we get here. */ |
1996 | ctlr, complete); | 2091 | } |
1997 | status = IO_ERROR; | 2092 | continue; |
1998 | goto cleanup1; | 2093 | } else |
1999 | } | 2094 | done = 1; |
2000 | } else { | 2095 | } 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 | 2096 | ||
2008 | cleanup1: | 2097 | cleanup1: |
2009 | /* unlock the data buffer from DMA */ | 2098 | /* unlock the data buffer from DMA */ |
@@ -2011,6 +2100,11 @@ cleanup1: | |||
2011 | buff_dma_handle.val32.upper = c->SG[0].Addr.upper; | 2100 | buff_dma_handle.val32.upper = c->SG[0].Addr.upper; |
2012 | pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val, | 2101 | pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val, |
2013 | c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); | 2102 | c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); |
2103 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
2104 | /* if we saved some commands for later, process them now. */ | ||
2105 | if (info_p->scsi_rejects.ncompletions > 0) | ||
2106 | do_cciss_intr(0, info_p, NULL); | ||
2107 | #endif | ||
2014 | cmd_free(info_p, c, 1); | 2108 | cmd_free(info_p, c, 1); |
2015 | return (status); | 2109 | return (status); |
2016 | } | 2110 | } |
@@ -2335,6 +2429,48 @@ startio: | |||
2335 | start_io(h); | 2429 | start_io(h); |
2336 | } | 2430 | } |
2337 | 2431 | ||
2432 | static inline unsigned long get_next_completion(ctlr_info_t *h) | ||
2433 | { | ||
2434 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
2435 | /* Any rejects from sendcmd() lying around? Process them first */ | ||
2436 | if (h->scsi_rejects.ncompletions == 0) | ||
2437 | return h->access.command_completed(h); | ||
2438 | else { | ||
2439 | struct sendcmd_reject_list *srl; | ||
2440 | int n; | ||
2441 | srl = &h->scsi_rejects; | ||
2442 | n = --srl->ncompletions; | ||
2443 | /* printk("cciss%d: processing saved reject\n", h->ctlr); */ | ||
2444 | printk("p"); | ||
2445 | return srl->complete[n]; | ||
2446 | } | ||
2447 | #else | ||
2448 | return h->access.command_completed(h); | ||
2449 | #endif | ||
2450 | } | ||
2451 | |||
2452 | static inline int interrupt_pending(ctlr_info_t *h) | ||
2453 | { | ||
2454 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
2455 | return ( h->access.intr_pending(h) | ||
2456 | || (h->scsi_rejects.ncompletions > 0)); | ||
2457 | #else | ||
2458 | return h->access.intr_pending(h); | ||
2459 | #endif | ||
2460 | } | ||
2461 | |||
2462 | static inline long interrupt_not_for_us(ctlr_info_t *h) | ||
2463 | { | ||
2464 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
2465 | return (((h->access.intr_pending(h) == 0) || | ||
2466 | (h->interrupts_enabled == 0)) | ||
2467 | && (h->scsi_rejects.ncompletions == 0)); | ||
2468 | #else | ||
2469 | return (((h->access.intr_pending(h) == 0) || | ||
2470 | (h->interrupts_enabled == 0))); | ||
2471 | #endif | ||
2472 | } | ||
2473 | |||
2338 | static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) | 2474 | static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) |
2339 | { | 2475 | { |
2340 | ctlr_info_t *h = dev_id; | 2476 | ctlr_info_t *h = dev_id; |
@@ -2344,19 +2480,15 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
2344 | int j; | 2480 | int j; |
2345 | int start_queue = h->next_to_run; | 2481 | int start_queue = h->next_to_run; |
2346 | 2482 | ||
2347 | /* Is this interrupt for us? */ | 2483 | if (interrupt_not_for_us(h)) |
2348 | if (( h->access.intr_pending(h) == 0) || (h->interrupts_enabled == 0)) | ||
2349 | return IRQ_NONE; | 2484 | return IRQ_NONE; |
2350 | |||
2351 | /* | 2485 | /* |
2352 | * If there are completed commands in the completion queue, | 2486 | * If there are completed commands in the completion queue, |
2353 | * we had better do something about it. | 2487 | * we had better do something about it. |
2354 | */ | 2488 | */ |
2355 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | 2489 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); |
2356 | while( h->access.intr_pending(h)) | 2490 | while (interrupt_pending(h)) { |
2357 | { | 2491 | while((a = get_next_completion(h)) != FIFO_EMPTY) { |
2358 | while((a = h->access.command_completed(h)) != FIFO_EMPTY) | ||
2359 | { | ||
2360 | a1 = a; | 2492 | a1 = a; |
2361 | if ((a & 0x04)) { | 2493 | if ((a & 0x04)) { |
2362 | a2 = (a >> 3); | 2494 | a2 = (a >> 3); |
@@ -2963,7 +3095,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
2963 | printk( KERN_ERR "cciss: out of memory"); | 3095 | printk( KERN_ERR "cciss: out of memory"); |
2964 | goto clean4; | 3096 | goto clean4; |
2965 | } | 3097 | } |
2966 | 3098 | #ifdef CONFIG_CISS_SCSI_TAPE | |
3099 | hba[i]->scsi_rejects.complete = | ||
3100 | kmalloc(sizeof(hba[i]->scsi_rejects.complete[0]) * | ||
3101 | (NR_CMDS + 5), GFP_KERNEL); | ||
3102 | if (hba[i]->scsi_rejects.complete == NULL) { | ||
3103 | printk( KERN_ERR "cciss: out of memory"); | ||
3104 | goto clean4; | ||
3105 | } | ||
3106 | #endif | ||
2967 | spin_lock_init(&hba[i]->lock); | 3107 | spin_lock_init(&hba[i]->lock); |
2968 | 3108 | ||
2969 | /* Initialize the pdev driver private data. | 3109 | /* Initialize the pdev driver private data. |
@@ -3031,6 +3171,10 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3031 | return(1); | 3171 | return(1); |
3032 | 3172 | ||
3033 | clean4: | 3173 | clean4: |
3174 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
3175 | if(hba[i]->scsi_rejects.complete) | ||
3176 | kfree(hba[i]->scsi_rejects.complete); | ||
3177 | #endif | ||
3034 | kfree(hba[i]->cmd_pool_bits); | 3178 | kfree(hba[i]->cmd_pool_bits); |
3035 | if(hba[i]->cmd_pool) | 3179 | if(hba[i]->cmd_pool) |
3036 | pci_free_consistent(hba[i]->pdev, | 3180 | pci_free_consistent(hba[i]->pdev, |
@@ -3092,9 +3236,13 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev) | |||
3092 | /* remove it from the disk list */ | 3236 | /* remove it from the disk list */ |
3093 | for (j = 0; j < NWD; j++) { | 3237 | for (j = 0; j < NWD; j++) { |
3094 | struct gendisk *disk = hba[i]->gendisk[j]; | 3238 | struct gendisk *disk = hba[i]->gendisk[j]; |
3095 | if (disk->flags & GENHD_FL_UP) { | 3239 | if (disk) { |
3096 | del_gendisk(disk); | 3240 | request_queue_t *q = disk->queue; |
3097 | blk_cleanup_queue(disk->queue); | 3241 | |
3242 | if (disk->flags & GENHD_FL_UP) | ||
3243 | del_gendisk(disk); | ||
3244 | if (q) | ||
3245 | blk_cleanup_queue(q); | ||
3098 | } | 3246 | } |
3099 | } | 3247 | } |
3100 | 3248 | ||
@@ -3103,6 +3251,9 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev) | |||
3103 | pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), | 3251 | pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), |
3104 | hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); | 3252 | hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); |
3105 | kfree(hba[i]->cmd_pool_bits); | 3253 | kfree(hba[i]->cmd_pool_bits); |
3254 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
3255 | kfree(hba[i]->scsi_rejects.complete); | ||
3256 | #endif | ||
3106 | release_io_mem(hba[i]); | 3257 | release_io_mem(hba[i]); |
3107 | free_hba(i); | 3258 | free_hba(i); |
3108 | } | 3259 | } |