diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/acsi.c | 1 | ||||
-rw-r--r-- | drivers/block/cciss.c | 188 | ||||
-rw-r--r-- | drivers/block/cciss.h | 11 | ||||
-rw-r--r-- | drivers/block/cciss_scsi.c | 82 |
4 files changed, 254 insertions, 28 deletions
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c index 0e1f34fef0c8..5d2d649f7e8d 100644 --- a/drivers/block/acsi.c +++ b/drivers/block/acsi.c | |||
@@ -58,7 +58,6 @@ | |||
58 | #include <linux/slab.h> | 58 | #include <linux/slab.h> |
59 | #include <linux/interrupt.h> | 59 | #include <linux/interrupt.h> |
60 | #include <scsi/scsi.h> /* for SCSI_IOCTL_GET_IDLUN */ | 60 | #include <scsi/scsi.h> /* for SCSI_IOCTL_GET_IDLUN */ |
61 | typedef void Scsi_Device; /* hack to avoid including scsi.h */ | ||
62 | #include <scsi/scsi_ioctl.h> | 61 | #include <scsi/scsi_ioctl.h> |
63 | #include <linux/hdreg.h> /* for HDIO_GETGEO */ | 62 | #include <linux/hdreg.h> /* for HDIO_GETGEO */ |
64 | #include <linux/blkpg.h> | 63 | #include <linux/blkpg.h> |
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 | } |
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index ef277baee9fd..3b0858c83897 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h | |||
@@ -44,6 +44,14 @@ typedef struct _drive_info_struct | |||
44 | */ | 44 | */ |
45 | } drive_info_struct; | 45 | } drive_info_struct; |
46 | 46 | ||
47 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
48 | |||
49 | struct sendcmd_reject_list { | ||
50 | int ncompletions; | ||
51 | unsigned long *complete; /* array of NR_CMDS tags */ | ||
52 | }; | ||
53 | |||
54 | #endif | ||
47 | struct ctlr_info | 55 | struct ctlr_info |
48 | { | 56 | { |
49 | int ctlr; | 57 | int ctlr; |
@@ -100,6 +108,9 @@ struct ctlr_info | |||
100 | struct gendisk *gendisk[NWD]; | 108 | struct gendisk *gendisk[NWD]; |
101 | #ifdef CONFIG_CISS_SCSI_TAPE | 109 | #ifdef CONFIG_CISS_SCSI_TAPE |
102 | void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ | 110 | void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ |
111 | /* list of block side commands the scsi error handling sucked up */ | ||
112 | /* and saved for later processing */ | ||
113 | struct sendcmd_reject_list scsi_rejects; | ||
103 | #endif | 114 | #endif |
104 | unsigned char alive; | 115 | unsigned char alive; |
105 | }; | 116 | }; |
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index ec27976a57da..3226aa11c6ef 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c | |||
@@ -42,6 +42,9 @@ | |||
42 | 42 | ||
43 | #include "cciss_scsi.h" | 43 | #include "cciss_scsi.h" |
44 | 44 | ||
45 | #define CCISS_ABORT_MSG 0x00 | ||
46 | #define CCISS_RESET_MSG 0x01 | ||
47 | |||
45 | /* some prototypes... */ | 48 | /* some prototypes... */ |
46 | static int sendcmd( | 49 | static int sendcmd( |
47 | __u8 cmd, | 50 | __u8 cmd, |
@@ -67,6 +70,8 @@ static int cciss_scsi_proc_info( | |||
67 | 70 | ||
68 | static int cciss_scsi_queue_command (struct scsi_cmnd *cmd, | 71 | static int cciss_scsi_queue_command (struct scsi_cmnd *cmd, |
69 | void (* done)(struct scsi_cmnd *)); | 72 | void (* done)(struct scsi_cmnd *)); |
73 | static int cciss_eh_device_reset_handler(struct scsi_cmnd *); | ||
74 | static int cciss_eh_abort_handler(struct scsi_cmnd *); | ||
70 | 75 | ||
71 | static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = { | 76 | static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = { |
72 | { .name = "cciss0", .ndevices = 0 }, | 77 | { .name = "cciss0", .ndevices = 0 }, |
@@ -90,6 +95,9 @@ static struct scsi_host_template cciss_driver_template = { | |||
90 | .sg_tablesize = MAXSGENTRIES, | 95 | .sg_tablesize = MAXSGENTRIES, |
91 | .cmd_per_lun = 1, | 96 | .cmd_per_lun = 1, |
92 | .use_clustering = DISABLE_CLUSTERING, | 97 | .use_clustering = DISABLE_CLUSTERING, |
98 | /* Can't have eh_bus_reset_handler or eh_host_reset_handler for cciss */ | ||
99 | .eh_device_reset_handler= cciss_eh_device_reset_handler, | ||
100 | .eh_abort_handler = cciss_eh_abort_handler, | ||
93 | }; | 101 | }; |
94 | 102 | ||
95 | #pragma pack(1) | 103 | #pragma pack(1) |
@@ -247,7 +255,7 @@ scsi_cmd_stack_free(int ctlr) | |||
247 | #define DEVICETYPE(n) (n<0 || n>MAX_SCSI_DEVICE_CODE) ? \ | 255 | #define DEVICETYPE(n) (n<0 || n>MAX_SCSI_DEVICE_CODE) ? \ |
248 | "Unknown" : scsi_device_types[n] | 256 | "Unknown" : scsi_device_types[n] |
249 | 257 | ||
250 | #if 0 | 258 | #if 1 |
251 | static int xmargin=8; | 259 | static int xmargin=8; |
252 | static int amargin=60; | 260 | static int amargin=60; |
253 | 261 | ||
@@ -1448,6 +1456,78 @@ cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len) | |||
1448 | *pos += size; *len += size; | 1456 | *pos += size; *len += size; |
1449 | } | 1457 | } |
1450 | 1458 | ||
1459 | /* Need at least one of these error handlers to keep ../scsi/hosts.c from | ||
1460 | * complaining. Doing a host- or bus-reset can't do anything good here. | ||
1461 | * Despite what it might say in scsi_error.c, there may well be commands | ||
1462 | * on the controller, as the cciss driver registers twice, once as a block | ||
1463 | * device for the logical drives, and once as a scsi device, for any tape | ||
1464 | * drives. So we know there are no commands out on the tape drives, but we | ||
1465 | * don't know there are no commands on the controller, and it is likely | ||
1466 | * that there probably are, as the cciss block device is most commonly used | ||
1467 | * as a boot device (embedded controller on HP/Compaq systems.) | ||
1468 | */ | ||
1469 | |||
1470 | static int cciss_eh_device_reset_handler(struct scsi_cmnd *scsicmd) | ||
1471 | { | ||
1472 | int rc; | ||
1473 | CommandList_struct *cmd_in_trouble; | ||
1474 | ctlr_info_t **c; | ||
1475 | int ctlr; | ||
1476 | |||
1477 | /* find the controller to which the command to be aborted was sent */ | ||
1478 | c = (ctlr_info_t **) &scsicmd->device->host->hostdata[0]; | ||
1479 | if (c == NULL) /* paranoia */ | ||
1480 | return FAILED; | ||
1481 | ctlr = (*c)->ctlr; | ||
1482 | printk(KERN_WARNING "cciss%d: resetting tape drive or medium changer.\n", ctlr); | ||
1483 | |||
1484 | /* find the command that's giving us trouble */ | ||
1485 | cmd_in_trouble = (CommandList_struct *) scsicmd->host_scribble; | ||
1486 | if (cmd_in_trouble == NULL) { /* paranoia */ | ||
1487 | return FAILED; | ||
1488 | } | ||
1489 | /* send a reset to the SCSI LUN which the command was sent to */ | ||
1490 | rc = sendcmd(CCISS_RESET_MSG, ctlr, NULL, 0, 2, 0, 0, | ||
1491 | (unsigned char *) &cmd_in_trouble->Header.LUN.LunAddrBytes[0], | ||
1492 | TYPE_MSG); | ||
1493 | /* sendcmd turned off interrputs on the board, turn 'em back on. */ | ||
1494 | (*c)->access.set_intr_mask(*c, CCISS_INTR_ON); | ||
1495 | if (rc == 0) | ||
1496 | return SUCCESS; | ||
1497 | printk(KERN_WARNING "cciss%d: resetting device failed.\n", ctlr); | ||
1498 | return FAILED; | ||
1499 | } | ||
1500 | |||
1501 | static int cciss_eh_abort_handler(struct scsi_cmnd *scsicmd) | ||
1502 | { | ||
1503 | int rc; | ||
1504 | CommandList_struct *cmd_to_abort; | ||
1505 | ctlr_info_t **c; | ||
1506 | int ctlr; | ||
1507 | |||
1508 | /* find the controller to which the command to be aborted was sent */ | ||
1509 | c = (ctlr_info_t **) &scsicmd->device->host->hostdata[0]; | ||
1510 | if (c == NULL) /* paranoia */ | ||
1511 | return FAILED; | ||
1512 | ctlr = (*c)->ctlr; | ||
1513 | printk(KERN_WARNING "cciss%d: aborting tardy SCSI cmd\n", ctlr); | ||
1514 | |||
1515 | /* find the command to be aborted */ | ||
1516 | cmd_to_abort = (CommandList_struct *) scsicmd->host_scribble; | ||
1517 | if (cmd_to_abort == NULL) /* paranoia */ | ||
1518 | return FAILED; | ||
1519 | rc = sendcmd(CCISS_ABORT_MSG, ctlr, &cmd_to_abort->Header.Tag, | ||
1520 | 0, 2, 0, 0, | ||
1521 | (unsigned char *) &cmd_to_abort->Header.LUN.LunAddrBytes[0], | ||
1522 | TYPE_MSG); | ||
1523 | /* sendcmd turned off interrputs on the board, turn 'em back on. */ | ||
1524 | (*c)->access.set_intr_mask(*c, CCISS_INTR_ON); | ||
1525 | if (rc == 0) | ||
1526 | return SUCCESS; | ||
1527 | return FAILED; | ||
1528 | |||
1529 | } | ||
1530 | |||
1451 | #else /* no CONFIG_CISS_SCSI_TAPE */ | 1531 | #else /* no CONFIG_CISS_SCSI_TAPE */ |
1452 | 1532 | ||
1453 | /* If no tape support, then these become defined out of existence */ | 1533 | /* If no tape support, then these become defined out of existence */ |