diff options
Diffstat (limited to 'drivers/scsi/aacraid/commsup.c')
-rw-r--r-- | drivers/scsi/aacraid/commsup.c | 112 |
1 files changed, 47 insertions, 65 deletions
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 1b97f60652ba..5824a757a753 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * based on the old aacraid driver that is.. | 5 | * based on the old aacraid driver that is.. |
6 | * Adaptec aacraid device driver for Linux. | 6 | * Adaptec aacraid device driver for Linux. |
7 | * | 7 | * |
8 | * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) | 8 | * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
@@ -94,7 +94,7 @@ void aac_fib_map_free(struct aac_dev *dev) | |||
94 | int aac_fib_setup(struct aac_dev * dev) | 94 | int aac_fib_setup(struct aac_dev * dev) |
95 | { | 95 | { |
96 | struct fib *fibptr; | 96 | struct fib *fibptr; |
97 | struct hw_fib *hw_fib_va; | 97 | struct hw_fib *hw_fib; |
98 | dma_addr_t hw_fib_pa; | 98 | dma_addr_t hw_fib_pa; |
99 | int i; | 99 | int i; |
100 | 100 | ||
@@ -106,24 +106,24 @@ int aac_fib_setup(struct aac_dev * dev) | |||
106 | if (i<0) | 106 | if (i<0) |
107 | return -ENOMEM; | 107 | return -ENOMEM; |
108 | 108 | ||
109 | hw_fib_va = dev->hw_fib_va; | 109 | hw_fib = dev->hw_fib_va; |
110 | hw_fib_pa = dev->hw_fib_pa; | 110 | hw_fib_pa = dev->hw_fib_pa; |
111 | memset(hw_fib_va, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)); | 111 | memset(hw_fib, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)); |
112 | /* | 112 | /* |
113 | * Initialise the fibs | 113 | * Initialise the fibs |
114 | */ | 114 | */ |
115 | for (i = 0, fibptr = &dev->fibs[i]; i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); i++, fibptr++) | 115 | for (i = 0, fibptr = &dev->fibs[i]; i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); i++, fibptr++) |
116 | { | 116 | { |
117 | fibptr->dev = dev; | 117 | fibptr->dev = dev; |
118 | fibptr->hw_fib = hw_fib_va; | 118 | fibptr->hw_fib_va = hw_fib; |
119 | fibptr->data = (void *) fibptr->hw_fib->data; | 119 | fibptr->data = (void *) fibptr->hw_fib_va->data; |
120 | fibptr->next = fibptr+1; /* Forward chain the fibs */ | 120 | fibptr->next = fibptr+1; /* Forward chain the fibs */ |
121 | init_MUTEX_LOCKED(&fibptr->event_wait); | 121 | init_MUTEX_LOCKED(&fibptr->event_wait); |
122 | spin_lock_init(&fibptr->event_lock); | 122 | spin_lock_init(&fibptr->event_lock); |
123 | hw_fib_va->header.XferState = cpu_to_le32(0xffffffff); | 123 | hw_fib->header.XferState = cpu_to_le32(0xffffffff); |
124 | hw_fib_va->header.SenderSize = cpu_to_le16(dev->max_fib_size); | 124 | hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size); |
125 | fibptr->hw_fib_pa = hw_fib_pa; | 125 | fibptr->hw_fib_pa = hw_fib_pa; |
126 | hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + dev->max_fib_size); | 126 | hw_fib = (struct hw_fib *)((unsigned char *)hw_fib + dev->max_fib_size); |
127 | hw_fib_pa = hw_fib_pa + dev->max_fib_size; | 127 | hw_fib_pa = hw_fib_pa + dev->max_fib_size; |
128 | } | 128 | } |
129 | /* | 129 | /* |
@@ -166,7 +166,7 @@ struct fib *aac_fib_alloc(struct aac_dev *dev) | |||
166 | * Null out fields that depend on being zero at the start of | 166 | * Null out fields that depend on being zero at the start of |
167 | * each I/O | 167 | * each I/O |
168 | */ | 168 | */ |
169 | fibptr->hw_fib->header.XferState = 0; | 169 | fibptr->hw_fib_va->header.XferState = 0; |
170 | fibptr->callback = NULL; | 170 | fibptr->callback = NULL; |
171 | fibptr->callback_data = NULL; | 171 | fibptr->callback_data = NULL; |
172 | 172 | ||
@@ -178,7 +178,6 @@ struct fib *aac_fib_alloc(struct aac_dev *dev) | |||
178 | * @fibptr: fib to free up | 178 | * @fibptr: fib to free up |
179 | * | 179 | * |
180 | * Frees up a fib and places it on the appropriate queue | 180 | * Frees up a fib and places it on the appropriate queue |
181 | * (either free or timed out) | ||
182 | */ | 181 | */ |
183 | 182 | ||
184 | void aac_fib_free(struct fib *fibptr) | 183 | void aac_fib_free(struct fib *fibptr) |
@@ -186,19 +185,15 @@ void aac_fib_free(struct fib *fibptr) | |||
186 | unsigned long flags; | 185 | unsigned long flags; |
187 | 186 | ||
188 | spin_lock_irqsave(&fibptr->dev->fib_lock, flags); | 187 | spin_lock_irqsave(&fibptr->dev->fib_lock, flags); |
189 | if (fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT) { | 188 | if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) |
190 | aac_config.fib_timeouts++; | 189 | aac_config.fib_timeouts++; |
191 | fibptr->next = fibptr->dev->timeout_fib; | 190 | if (fibptr->hw_fib_va->header.XferState != 0) { |
192 | fibptr->dev->timeout_fib = fibptr; | 191 | printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", |
193 | } else { | 192 | (void*)fibptr, |
194 | if (fibptr->hw_fib->header.XferState != 0) { | 193 | le32_to_cpu(fibptr->hw_fib_va->header.XferState)); |
195 | printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", | 194 | } |
196 | (void*)fibptr, | 195 | fibptr->next = fibptr->dev->free_fib; |
197 | le32_to_cpu(fibptr->hw_fib->header.XferState)); | 196 | fibptr->dev->free_fib = fibptr; |
198 | } | ||
199 | fibptr->next = fibptr->dev->free_fib; | ||
200 | fibptr->dev->free_fib = fibptr; | ||
201 | } | ||
202 | spin_unlock_irqrestore(&fibptr->dev->fib_lock, flags); | 197 | spin_unlock_irqrestore(&fibptr->dev->fib_lock, flags); |
203 | } | 198 | } |
204 | 199 | ||
@@ -211,7 +206,7 @@ void aac_fib_free(struct fib *fibptr) | |||
211 | 206 | ||
212 | void aac_fib_init(struct fib *fibptr) | 207 | void aac_fib_init(struct fib *fibptr) |
213 | { | 208 | { |
214 | struct hw_fib *hw_fib = fibptr->hw_fib; | 209 | struct hw_fib *hw_fib = fibptr->hw_fib_va; |
215 | 210 | ||
216 | hw_fib->header.StructType = FIB_MAGIC; | 211 | hw_fib->header.StructType = FIB_MAGIC; |
217 | hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size); | 212 | hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size); |
@@ -231,7 +226,7 @@ void aac_fib_init(struct fib *fibptr) | |||
231 | 226 | ||
232 | static void fib_dealloc(struct fib * fibptr) | 227 | static void fib_dealloc(struct fib * fibptr) |
233 | { | 228 | { |
234 | struct hw_fib *hw_fib = fibptr->hw_fib; | 229 | struct hw_fib *hw_fib = fibptr->hw_fib_va; |
235 | BUG_ON(hw_fib->header.StructType != FIB_MAGIC); | 230 | BUG_ON(hw_fib->header.StructType != FIB_MAGIC); |
236 | hw_fib->header.XferState = 0; | 231 | hw_fib->header.XferState = 0; |
237 | } | 232 | } |
@@ -386,7 +381,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, | |||
386 | void *callback_data) | 381 | void *callback_data) |
387 | { | 382 | { |
388 | struct aac_dev * dev = fibptr->dev; | 383 | struct aac_dev * dev = fibptr->dev; |
389 | struct hw_fib * hw_fib = fibptr->hw_fib; | 384 | struct hw_fib * hw_fib = fibptr->hw_fib_va; |
390 | unsigned long flags = 0; | 385 | unsigned long flags = 0; |
391 | unsigned long qflags; | 386 | unsigned long qflags; |
392 | 387 | ||
@@ -430,7 +425,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, | |||
430 | */ | 425 | */ |
431 | hw_fib->header.Command = cpu_to_le16(command); | 426 | hw_fib->header.Command = cpu_to_le16(command); |
432 | hw_fib->header.XferState |= cpu_to_le32(SentFromHost); | 427 | hw_fib->header.XferState |= cpu_to_le32(SentFromHost); |
433 | fibptr->hw_fib->header.Flags = 0; /* 0 the flags field - internal only*/ | 428 | fibptr->hw_fib_va->header.Flags = 0; /* 0 the flags field - internal only*/ |
434 | /* | 429 | /* |
435 | * Set the size of the Fib we want to send to the adapter | 430 | * Set the size of the Fib we want to send to the adapter |
436 | */ | 431 | */ |
@@ -462,7 +457,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, | |||
462 | dprintk((KERN_DEBUG " Command = %d.\n", le32_to_cpu(hw_fib->header.Command))); | 457 | dprintk((KERN_DEBUG " Command = %d.\n", le32_to_cpu(hw_fib->header.Command))); |
463 | dprintk((KERN_DEBUG " SubCommand = %d.\n", le32_to_cpu(((struct aac_query_mount *)fib_data(fibptr))->command))); | 458 | dprintk((KERN_DEBUG " SubCommand = %d.\n", le32_to_cpu(((struct aac_query_mount *)fib_data(fibptr))->command))); |
464 | dprintk((KERN_DEBUG " XferState = %x.\n", le32_to_cpu(hw_fib->header.XferState))); | 459 | dprintk((KERN_DEBUG " XferState = %x.\n", le32_to_cpu(hw_fib->header.XferState))); |
465 | dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib)); | 460 | dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib_va)); |
466 | dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); | 461 | dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); |
467 | dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); | 462 | dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); |
468 | 463 | ||
@@ -513,22 +508,20 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, | |||
513 | } | 508 | } |
514 | udelay(5); | 509 | udelay(5); |
515 | } | 510 | } |
516 | } else if (down_interruptible(&fibptr->event_wait)) { | 511 | } else |
517 | spin_lock_irqsave(&fibptr->event_lock, flags); | 512 | (void)down_interruptible(&fibptr->event_wait); |
518 | if (fibptr->done == 0) { | 513 | spin_lock_irqsave(&fibptr->event_lock, flags); |
519 | fibptr->done = 2; /* Tell interrupt we aborted */ | 514 | if (fibptr->done == 0) { |
520 | spin_unlock_irqrestore(&fibptr->event_lock, flags); | 515 | fibptr->done = 2; /* Tell interrupt we aborted */ |
521 | return -EINTR; | ||
522 | } | ||
523 | spin_unlock_irqrestore(&fibptr->event_lock, flags); | 516 | spin_unlock_irqrestore(&fibptr->event_lock, flags); |
517 | return -EINTR; | ||
524 | } | 518 | } |
519 | spin_unlock_irqrestore(&fibptr->event_lock, flags); | ||
525 | BUG_ON(fibptr->done == 0); | 520 | BUG_ON(fibptr->done == 0); |
526 | 521 | ||
527 | if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){ | 522 | if(unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) |
528 | return -ETIMEDOUT; | 523 | return -ETIMEDOUT; |
529 | } else { | 524 | return 0; |
530 | return 0; | ||
531 | } | ||
532 | } | 525 | } |
533 | /* | 526 | /* |
534 | * If the user does not want a response than return success otherwise | 527 | * If the user does not want a response than return success otherwise |
@@ -624,7 +617,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid) | |||
624 | 617 | ||
625 | int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) | 618 | int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) |
626 | { | 619 | { |
627 | struct hw_fib * hw_fib = fibptr->hw_fib; | 620 | struct hw_fib * hw_fib = fibptr->hw_fib_va; |
628 | struct aac_dev * dev = fibptr->dev; | 621 | struct aac_dev * dev = fibptr->dev; |
629 | struct aac_queue * q; | 622 | struct aac_queue * q; |
630 | unsigned long nointr = 0; | 623 | unsigned long nointr = 0; |
@@ -688,7 +681,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) | |||
688 | 681 | ||
689 | int aac_fib_complete(struct fib *fibptr) | 682 | int aac_fib_complete(struct fib *fibptr) |
690 | { | 683 | { |
691 | struct hw_fib * hw_fib = fibptr->hw_fib; | 684 | struct hw_fib * hw_fib = fibptr->hw_fib_va; |
692 | 685 | ||
693 | /* | 686 | /* |
694 | * Check for a fib which has already been completed | 687 | * Check for a fib which has already been completed |
@@ -774,9 +767,8 @@ void aac_printf(struct aac_dev *dev, u32 val) | |||
774 | #define AIF_SNIFF_TIMEOUT (30*HZ) | 767 | #define AIF_SNIFF_TIMEOUT (30*HZ) |
775 | static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | 768 | static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) |
776 | { | 769 | { |
777 | struct hw_fib * hw_fib = fibptr->hw_fib; | 770 | struct hw_fib * hw_fib = fibptr->hw_fib_va; |
778 | struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data; | 771 | struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data; |
779 | int busy; | ||
780 | u32 container; | 772 | u32 container; |
781 | struct scsi_device *device; | 773 | struct scsi_device *device; |
782 | enum { | 774 | enum { |
@@ -988,9 +980,6 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | |||
988 | * behind you. | 980 | * behind you. |
989 | */ | 981 | */ |
990 | 982 | ||
991 | busy = 0; | ||
992 | |||
993 | |||
994 | /* | 983 | /* |
995 | * Find the scsi_device associated with the SCSI address, | 984 | * Find the scsi_device associated with the SCSI address, |
996 | * and mark it as changed, invalidating the cache. This deals | 985 | * and mark it as changed, invalidating the cache. This deals |
@@ -1035,7 +1024,6 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | |||
1035 | static int _aac_reset_adapter(struct aac_dev *aac) | 1024 | static int _aac_reset_adapter(struct aac_dev *aac) |
1036 | { | 1025 | { |
1037 | int index, quirks; | 1026 | int index, quirks; |
1038 | u32 ret; | ||
1039 | int retval; | 1027 | int retval; |
1040 | struct Scsi_Host *host; | 1028 | struct Scsi_Host *host; |
1041 | struct scsi_device *dev; | 1029 | struct scsi_device *dev; |
@@ -1059,35 +1047,29 @@ static int _aac_reset_adapter(struct aac_dev *aac) | |||
1059 | * If a positive health, means in a known DEAD PANIC | 1047 | * If a positive health, means in a known DEAD PANIC |
1060 | * state and the adapter could be reset to `try again'. | 1048 | * state and the adapter could be reset to `try again'. |
1061 | */ | 1049 | */ |
1062 | retval = aac_adapter_check_health(aac); | 1050 | retval = aac_adapter_restart(aac, aac_adapter_check_health(aac)); |
1063 | if (retval == 0) | ||
1064 | retval = aac_adapter_sync_cmd(aac, IOP_RESET_ALWAYS, | ||
1065 | 0, 0, 0, 0, 0, 0, &ret, NULL, NULL, NULL, NULL); | ||
1066 | if (retval) | ||
1067 | retval = aac_adapter_sync_cmd(aac, IOP_RESET, | ||
1068 | 0, 0, 0, 0, 0, 0, &ret, NULL, NULL, NULL, NULL); | ||
1069 | 1051 | ||
1070 | if (retval) | 1052 | if (retval) |
1071 | goto out; | 1053 | goto out; |
1072 | if (ret != 0x00000001) { | ||
1073 | retval = -ENODEV; | ||
1074 | goto out; | ||
1075 | } | ||
1076 | 1054 | ||
1077 | /* | 1055 | /* |
1078 | * Loop through the fibs, close the synchronous FIBS | 1056 | * Loop through the fibs, close the synchronous FIBS |
1079 | */ | 1057 | */ |
1080 | for (index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) { | 1058 | for (retval = 1, index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) { |
1081 | struct fib *fib = &aac->fibs[index]; | 1059 | struct fib *fib = &aac->fibs[index]; |
1082 | if (!(fib->hw_fib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) && | 1060 | if (!(fib->hw_fib_va->header.XferState & cpu_to_le32(NoResponseExpected | Async)) && |
1083 | (fib->hw_fib->header.XferState & cpu_to_le32(ResponseExpected))) { | 1061 | (fib->hw_fib_va->header.XferState & cpu_to_le32(ResponseExpected))) { |
1084 | unsigned long flagv; | 1062 | unsigned long flagv; |
1085 | spin_lock_irqsave(&fib->event_lock, flagv); | 1063 | spin_lock_irqsave(&fib->event_lock, flagv); |
1086 | up(&fib->event_wait); | 1064 | up(&fib->event_wait); |
1087 | spin_unlock_irqrestore(&fib->event_lock, flagv); | 1065 | spin_unlock_irqrestore(&fib->event_lock, flagv); |
1088 | schedule(); | 1066 | schedule(); |
1067 | retval = 0; | ||
1089 | } | 1068 | } |
1090 | } | 1069 | } |
1070 | /* Give some extra time for ioctls to complete. */ | ||
1071 | if (retval == 0) | ||
1072 | ssleep(2); | ||
1091 | index = aac->cardtype; | 1073 | index = aac->cardtype; |
1092 | 1074 | ||
1093 | /* | 1075 | /* |
@@ -1248,7 +1230,7 @@ int aac_check_health(struct aac_dev * aac) | |||
1248 | 1230 | ||
1249 | memset(hw_fib, 0, sizeof(struct hw_fib)); | 1231 | memset(hw_fib, 0, sizeof(struct hw_fib)); |
1250 | memset(fib, 0, sizeof(struct fib)); | 1232 | memset(fib, 0, sizeof(struct fib)); |
1251 | fib->hw_fib = hw_fib; | 1233 | fib->hw_fib_va = hw_fib; |
1252 | fib->dev = aac; | 1234 | fib->dev = aac; |
1253 | aac_fib_init(fib); | 1235 | aac_fib_init(fib); |
1254 | fib->type = FSAFS_NTC_FIB_CONTEXT; | 1236 | fib->type = FSAFS_NTC_FIB_CONTEXT; |
@@ -1354,11 +1336,11 @@ int aac_command_thread(void *data) | |||
1354 | * do anything at this point since we don't have | 1336 | * do anything at this point since we don't have |
1355 | * anything defined for this thread to do. | 1337 | * anything defined for this thread to do. |
1356 | */ | 1338 | */ |
1357 | hw_fib = fib->hw_fib; | 1339 | hw_fib = fib->hw_fib_va; |
1358 | memset(fib, 0, sizeof(struct fib)); | 1340 | memset(fib, 0, sizeof(struct fib)); |
1359 | fib->type = FSAFS_NTC_FIB_CONTEXT; | 1341 | fib->type = FSAFS_NTC_FIB_CONTEXT; |
1360 | fib->size = sizeof( struct fib ); | 1342 | fib->size = sizeof( struct fib ); |
1361 | fib->hw_fib = hw_fib; | 1343 | fib->hw_fib_va = hw_fib; |
1362 | fib->data = hw_fib->data; | 1344 | fib->data = hw_fib->data; |
1363 | fib->dev = dev; | 1345 | fib->dev = dev; |
1364 | /* | 1346 | /* |
@@ -1485,7 +1467,7 @@ int aac_command_thread(void *data) | |||
1485 | */ | 1467 | */ |
1486 | memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib)); | 1468 | memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib)); |
1487 | memcpy(newfib, fib, sizeof(struct fib)); | 1469 | memcpy(newfib, fib, sizeof(struct fib)); |
1488 | newfib->hw_fib = hw_newfib; | 1470 | newfib->hw_fib_va = hw_newfib; |
1489 | /* | 1471 | /* |
1490 | * Put the FIB onto the | 1472 | * Put the FIB onto the |
1491 | * fibctx's fibs | 1473 | * fibctx's fibs |