diff options
author | Mahesh Rajashekhara <Mahesh_Rajashekhara@pmc-sierra.com> | 2012-02-09 01:51:04 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-02-19 09:09:01 -0500 |
commit | 116046127d1a3bad2853d02781ad9fee33f05e5a (patch) | |
tree | f5a0ca20662b98960ce20587f666b6267367478b /drivers | |
parent | 70fc872c738d1e0af7d0420047e4ca3acf283c9d (diff) |
[SCSI] aacraid: Added Sync.mode to support series 7/8/9 controllers
Added Sync. mode to support Series 7/8/9 controller families: This is a
compatibility mode for all these controller families. The Async. (Performance)
mode can be changed in the future. First Async. mode version added for Series
7; Controller parameter aac_sync_mode added
Signed-off-by: Mahesh Rajashekhara <aacraid@pmc-sierra.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/aacraid/aachba.c | 4 | ||||
-rw-r--r-- | drivers/scsi/aacraid/aacraid.h | 27 | ||||
-rw-r--r-- | drivers/scsi/aacraid/comminit.c | 21 | ||||
-rw-r--r-- | drivers/scsi/aacraid/commsup.c | 26 | ||||
-rw-r--r-- | drivers/scsi/aacraid/linit.c | 28 | ||||
-rw-r--r-- | drivers/scsi/aacraid/rx.c | 1 | ||||
-rw-r--r-- | drivers/scsi/aacraid/sa.c | 1 | ||||
-rw-r--r-- | drivers/scsi/aacraid/src.c | 293 |
8 files changed, 338 insertions, 63 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 409f5805bdd6..52551662d107 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
@@ -151,7 +151,11 @@ int aac_msi; | |||
151 | int aac_commit = -1; | 151 | int aac_commit = -1; |
152 | int startup_timeout = 180; | 152 | int startup_timeout = 180; |
153 | int aif_timeout = 120; | 153 | int aif_timeout = 120; |
154 | int aac_sync_mode; /* Only Sync. transfer - disabled */ | ||
154 | 155 | ||
156 | module_param(aac_sync_mode, int, S_IRUGO|S_IWUSR); | ||
157 | MODULE_PARM_DESC(aac_sync_mode, "Force sync. transfer mode" | ||
158 | " 0=off, 1=on"); | ||
155 | module_param(nondasd, int, S_IRUGO|S_IWUSR); | 159 | module_param(nondasd, int, S_IRUGO|S_IWUSR); |
156 | MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices." | 160 | MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices." |
157 | " 0=off, 1=on"); | 161 | " 0=off, 1=on"); |
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index ffb587817efc..3fcf62724fad 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h | |||
@@ -12,7 +12,7 @@ | |||
12 | *----------------------------------------------------------------------------*/ | 12 | *----------------------------------------------------------------------------*/ |
13 | 13 | ||
14 | #ifndef AAC_DRIVER_BUILD | 14 | #ifndef AAC_DRIVER_BUILD |
15 | # define AAC_DRIVER_BUILD 28000 | 15 | # define AAC_DRIVER_BUILD 28900 |
16 | # define AAC_DRIVER_BRANCH "-ms" | 16 | # define AAC_DRIVER_BRANCH "-ms" |
17 | #endif | 17 | #endif |
18 | #define MAXIMUM_NUM_CONTAINERS 32 | 18 | #define MAXIMUM_NUM_CONTAINERS 32 |
@@ -756,8 +756,16 @@ struct src_mu_registers { | |||
756 | 756 | ||
757 | struct src_registers { | 757 | struct src_registers { |
758 | struct src_mu_registers MUnit; /* 00h - c7h */ | 758 | struct src_mu_registers MUnit; /* 00h - c7h */ |
759 | __le32 reserved1[130790]; /* c8h - 7fc5fh */ | 759 | union { |
760 | struct src_inbound IndexRegs; /* 7fc60h */ | 760 | struct { |
761 | __le32 reserved1[130790]; /* c8h - 7fc5fh */ | ||
762 | struct src_inbound IndexRegs; /* 7fc60h */ | ||
763 | } tupelo; | ||
764 | struct { | ||
765 | __le32 reserved1[974]; /* c8h - fffh */ | ||
766 | struct src_inbound IndexRegs; /* 1000h */ | ||
767 | } denali; | ||
768 | } u; | ||
761 | }; | 769 | }; |
762 | 770 | ||
763 | #define src_readb(AEP, CSR) readb(&((AEP)->regs.src.bar0->CSR)) | 771 | #define src_readb(AEP, CSR) readb(&((AEP)->regs.src.bar0->CSR)) |
@@ -999,6 +1007,10 @@ struct aac_bus_info_response { | |||
999 | #define AAC_OPT_NEW_COMM cpu_to_le32(1<<17) | 1007 | #define AAC_OPT_NEW_COMM cpu_to_le32(1<<17) |
1000 | #define AAC_OPT_NEW_COMM_64 cpu_to_le32(1<<18) | 1008 | #define AAC_OPT_NEW_COMM_64 cpu_to_le32(1<<18) |
1001 | #define AAC_OPT_NEW_COMM_TYPE1 cpu_to_le32(1<<28) | 1009 | #define AAC_OPT_NEW_COMM_TYPE1 cpu_to_le32(1<<28) |
1010 | #define AAC_OPT_NEW_COMM_TYPE2 cpu_to_le32(1<<29) | ||
1011 | #define AAC_OPT_NEW_COMM_TYPE3 cpu_to_le32(1<<30) | ||
1012 | #define AAC_OPT_NEW_COMM_TYPE4 cpu_to_le32(1<<31) | ||
1013 | |||
1002 | 1014 | ||
1003 | struct aac_dev | 1015 | struct aac_dev |
1004 | { | 1016 | { |
@@ -1076,6 +1088,8 @@ struct aac_dev | |||
1076 | # define AAC_MIN_FOOTPRINT_SIZE 8192 | 1088 | # define AAC_MIN_FOOTPRINT_SIZE 8192 |
1077 | # define AAC_MIN_SRC_BAR0_SIZE 0x400000 | 1089 | # define AAC_MIN_SRC_BAR0_SIZE 0x400000 |
1078 | # define AAC_MIN_SRC_BAR1_SIZE 0x800 | 1090 | # define AAC_MIN_SRC_BAR1_SIZE 0x800 |
1091 | # define AAC_MIN_SRCV_BAR0_SIZE 0x100000 | ||
1092 | # define AAC_MIN_SRCV_BAR1_SIZE 0x400 | ||
1079 | #endif | 1093 | #endif |
1080 | union | 1094 | union |
1081 | { | 1095 | { |
@@ -1116,7 +1130,10 @@ struct aac_dev | |||
1116 | u8 msi; | 1130 | u8 msi; |
1117 | int management_fib_count; | 1131 | int management_fib_count; |
1118 | spinlock_t manage_lock; | 1132 | spinlock_t manage_lock; |
1119 | 1133 | spinlock_t sync_lock; | |
1134 | int sync_mode; | ||
1135 | struct fib *sync_fib; | ||
1136 | struct list_head sync_fib_list; | ||
1120 | }; | 1137 | }; |
1121 | 1138 | ||
1122 | #define aac_adapter_interrupt(dev) \ | 1139 | #define aac_adapter_interrupt(dev) \ |
@@ -1163,6 +1180,7 @@ struct aac_dev | |||
1163 | 1180 | ||
1164 | #define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001) | 1181 | #define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001) |
1165 | #define FIB_CONTEXT_FLAG (0x00000002) | 1182 | #define FIB_CONTEXT_FLAG (0x00000002) |
1183 | #define FIB_CONTEXT_FLAG_WAIT (0x00000004) | ||
1166 | 1184 | ||
1167 | /* | 1185 | /* |
1168 | * Define the command values | 1186 | * Define the command values |
@@ -1970,6 +1988,7 @@ int aac_rkt_init(struct aac_dev *dev); | |||
1970 | int aac_nark_init(struct aac_dev *dev); | 1988 | int aac_nark_init(struct aac_dev *dev); |
1971 | int aac_sa_init(struct aac_dev *dev); | 1989 | int aac_sa_init(struct aac_dev *dev); |
1972 | int aac_src_init(struct aac_dev *dev); | 1990 | int aac_src_init(struct aac_dev *dev); |
1991 | int aac_srcv_init(struct aac_dev *dev); | ||
1973 | int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify); | 1992 | int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify); |
1974 | unsigned int aac_response_normal(struct aac_queue * q); | 1993 | unsigned int aac_response_normal(struct aac_queue * q); |
1975 | unsigned int aac_command_normal(struct aac_queue * q); | 1994 | unsigned int aac_command_normal(struct aac_queue * q); |
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 7ac8fdb5577b..a35f54ebdce0 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c | |||
@@ -325,12 +325,14 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) | |||
325 | { | 325 | { |
326 | u32 status[5]; | 326 | u32 status[5]; |
327 | struct Scsi_Host * host = dev->scsi_host_ptr; | 327 | struct Scsi_Host * host = dev->scsi_host_ptr; |
328 | extern int aac_sync_mode; | ||
328 | 329 | ||
329 | /* | 330 | /* |
330 | * Check the preferred comm settings, defaults from template. | 331 | * Check the preferred comm settings, defaults from template. |
331 | */ | 332 | */ |
332 | dev->management_fib_count = 0; | 333 | dev->management_fib_count = 0; |
333 | spin_lock_init(&dev->manage_lock); | 334 | spin_lock_init(&dev->manage_lock); |
335 | spin_lock_init(&dev->sync_lock); | ||
334 | dev->max_fib_size = sizeof(struct hw_fib); | 336 | dev->max_fib_size = sizeof(struct hw_fib); |
335 | dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size | 337 | dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size |
336 | - sizeof(struct aac_fibhdr) | 338 | - sizeof(struct aac_fibhdr) |
@@ -344,13 +346,21 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) | |||
344 | (status[0] == 0x00000001)) { | 346 | (status[0] == 0x00000001)) { |
345 | if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64)) | 347 | if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64)) |
346 | dev->raw_io_64 = 1; | 348 | dev->raw_io_64 = 1; |
347 | if (dev->a_ops.adapter_comm) { | 349 | dev->sync_mode = aac_sync_mode; |
348 | if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE1)) { | 350 | if (dev->a_ops.adapter_comm && |
349 | dev->comm_interface = AAC_COMM_MESSAGE_TYPE1; | 351 | (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM))) { |
350 | dev->raw_io_interface = 1; | ||
351 | } else if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM)) { | ||
352 | dev->comm_interface = AAC_COMM_MESSAGE; | 352 | dev->comm_interface = AAC_COMM_MESSAGE; |
353 | dev->raw_io_interface = 1; | 353 | dev->raw_io_interface = 1; |
354 | if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE1))) { | ||
355 | /* driver supports TYPE1 (Tupelo) */ | ||
356 | dev->comm_interface = AAC_COMM_MESSAGE_TYPE1; | ||
357 | } else if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE4)) || | ||
358 | (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE3)) || | ||
359 | (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE2))) { | ||
360 | /* driver doesn't support TYPE2 (Series7), TYPE3 and TYPE4 */ | ||
361 | /* switch to sync. mode */ | ||
362 | dev->comm_interface = AAC_COMM_MESSAGE_TYPE1; | ||
363 | dev->sync_mode = 1; | ||
354 | } | 364 | } |
355 | } | 365 | } |
356 | if ((dev->comm_interface == AAC_COMM_MESSAGE) && | 366 | if ((dev->comm_interface == AAC_COMM_MESSAGE) && |
@@ -455,6 +465,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) | |||
455 | } | 465 | } |
456 | 466 | ||
457 | INIT_LIST_HEAD(&dev->fib_list); | 467 | INIT_LIST_HEAD(&dev->fib_list); |
468 | INIT_LIST_HEAD(&dev->sync_fib_list); | ||
458 | 469 | ||
459 | return dev; | 470 | return dev; |
460 | } | 471 | } |
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index e5f2d7d9002e..4b32ca442433 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c | |||
@@ -416,6 +416,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, | |||
416 | unsigned long flags = 0; | 416 | unsigned long flags = 0; |
417 | unsigned long qflags; | 417 | unsigned long qflags; |
418 | unsigned long mflags = 0; | 418 | unsigned long mflags = 0; |
419 | unsigned long sflags = 0; | ||
419 | 420 | ||
420 | 421 | ||
421 | if (!(hw_fib->header.XferState & cpu_to_le32(HostOwned))) | 422 | if (!(hw_fib->header.XferState & cpu_to_le32(HostOwned))) |
@@ -512,6 +513,31 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, | |||
512 | spin_lock_irqsave(&fibptr->event_lock, flags); | 513 | spin_lock_irqsave(&fibptr->event_lock, flags); |
513 | } | 514 | } |
514 | 515 | ||
516 | if (dev->sync_mode) { | ||
517 | if (wait) | ||
518 | spin_unlock_irqrestore(&fibptr->event_lock, flags); | ||
519 | spin_lock_irqsave(&dev->sync_lock, sflags); | ||
520 | if (dev->sync_fib) { | ||
521 | list_add_tail(&fibptr->fiblink, &dev->sync_fib_list); | ||
522 | spin_unlock_irqrestore(&dev->sync_lock, sflags); | ||
523 | } else { | ||
524 | dev->sync_fib = fibptr; | ||
525 | spin_unlock_irqrestore(&dev->sync_lock, sflags); | ||
526 | aac_adapter_sync_cmd(dev, SEND_SYNCHRONOUS_FIB, | ||
527 | (u32)fibptr->hw_fib_pa, 0, 0, 0, 0, 0, | ||
528 | NULL, NULL, NULL, NULL, NULL); | ||
529 | } | ||
530 | if (wait) { | ||
531 | fibptr->flags |= FIB_CONTEXT_FLAG_WAIT; | ||
532 | if (down_interruptible(&fibptr->event_wait)) { | ||
533 | fibptr->flags &= ~FIB_CONTEXT_FLAG_WAIT; | ||
534 | return -EFAULT; | ||
535 | } | ||
536 | return 0; | ||
537 | } | ||
538 | return -EINPROGRESS; | ||
539 | } | ||
540 | |||
515 | if (aac_adapter_deliver(fibptr) != 0) { | 541 | if (aac_adapter_deliver(fibptr) != 0) { |
516 | printk(KERN_ERR "aac_fib_send: returned -EBUSY\n"); | 542 | printk(KERN_ERR "aac_fib_send: returned -EBUSY\n"); |
517 | if (wait) { | 543 | if (wait) { |
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 705e13e470af..0d279c445a30 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c | |||
@@ -56,7 +56,7 @@ | |||
56 | 56 | ||
57 | #include "aacraid.h" | 57 | #include "aacraid.h" |
58 | 58 | ||
59 | #define AAC_DRIVER_VERSION "1.1-7" | 59 | #define AAC_DRIVER_VERSION "1.2-0" |
60 | #ifndef AAC_DRIVER_BRANCH | 60 | #ifndef AAC_DRIVER_BRANCH |
61 | #define AAC_DRIVER_BRANCH "" | 61 | #define AAC_DRIVER_BRANCH "" |
62 | #endif | 62 | #endif |
@@ -162,7 +162,10 @@ static const struct pci_device_id aac_pci_tbl[] __devinitdata = { | |||
162 | { 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */ | 162 | { 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */ |
163 | { 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */ | 163 | { 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */ |
164 | { 0x9005, 0x0288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 61 }, /* Adaptec NEMER/ARK Catch All */ | 164 | { 0x9005, 0x0288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 61 }, /* Adaptec NEMER/ARK Catch All */ |
165 | { 0x9005, 0x028b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 62 }, /* Adaptec PMC Catch All */ | 165 | { 0x9005, 0x028b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 62 }, /* Adaptec PMC Series 6 (Tupelo) */ |
166 | { 0x9005, 0x028c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 63 }, /* Adaptec PMC Series 7 (Denali) */ | ||
167 | { 0x9005, 0x028d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 64 }, /* Adaptec PMC Series 8 */ | ||
168 | { 0x9005, 0x028f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 65 }, /* Adaptec PMC Series 9 */ | ||
166 | { 0,} | 169 | { 0,} |
167 | }; | 170 | }; |
168 | MODULE_DEVICE_TABLE(pci, aac_pci_tbl); | 171 | MODULE_DEVICE_TABLE(pci, aac_pci_tbl); |
@@ -238,7 +241,10 @@ static struct aac_driver_ident aac_drivers[] = { | |||
238 | { aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Catch All */ | 241 | { aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Catch All */ |
239 | { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Rocket Catch All */ | 242 | { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Rocket Catch All */ |
240 | { aac_nark_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec NEMER/ARK Catch All */ | 243 | { aac_nark_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec NEMER/ARK Catch All */ |
241 | { aac_src_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec PMC Catch All */ | 244 | { aac_src_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec PMC Series 6 (Tupelo) */ |
245 | { aac_srcv_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec PMC Series 7 (Denali) */ | ||
246 | { aac_srcv_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec PMC Series 8 */ | ||
247 | { aac_srcv_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec PMC Series 9 */ | ||
242 | }; | 248 | }; |
243 | 249 | ||
244 | /** | 250 | /** |
@@ -1102,6 +1108,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, | |||
1102 | int error = -ENODEV; | 1108 | int error = -ENODEV; |
1103 | int unique_id = 0; | 1109 | int unique_id = 0; |
1104 | u64 dmamask; | 1110 | u64 dmamask; |
1111 | extern int aac_sync_mode; | ||
1105 | 1112 | ||
1106 | list_for_each_entry(aac, &aac_devices, entry) { | 1113 | list_for_each_entry(aac, &aac_devices, entry) { |
1107 | if (aac->id > unique_id) | 1114 | if (aac->id > unique_id) |
@@ -1162,6 +1169,21 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, | |||
1162 | if ((*aac_drivers[index].init)(aac)) | 1169 | if ((*aac_drivers[index].init)(aac)) |
1163 | goto out_unmap; | 1170 | goto out_unmap; |
1164 | 1171 | ||
1172 | if (aac->sync_mode) { | ||
1173 | if (aac_sync_mode) | ||
1174 | printk(KERN_INFO "%s%d: Sync. mode enforced " | ||
1175 | "by driver parameter. This will cause " | ||
1176 | "a significant performance decrease!\n", | ||
1177 | aac->name, | ||
1178 | aac->id); | ||
1179 | else | ||
1180 | printk(KERN_INFO "%s%d: Async. mode not supported " | ||
1181 | "by current driver, sync. mode enforced." | ||
1182 | "\nPlease update driver to get full performance.\n", | ||
1183 | aac->name, | ||
1184 | aac->id); | ||
1185 | } | ||
1186 | |||
1165 | /* | 1187 | /* |
1166 | * Start any kernel threads needed | 1188 | * Start any kernel threads needed |
1167 | */ | 1189 | */ |
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index ce530f113fdb..b029c7cc785b 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c | |||
@@ -643,6 +643,7 @@ int _aac_rx_init(struct aac_dev *dev) | |||
643 | if (aac_init_adapter(dev) == NULL) | 643 | if (aac_init_adapter(dev) == NULL) |
644 | goto error_iounmap; | 644 | goto error_iounmap; |
645 | aac_adapter_comm(dev, dev->comm_interface); | 645 | aac_adapter_comm(dev, dev->comm_interface); |
646 | dev->sync_mode = 0; /* sync. mode not supported */ | ||
646 | dev->msi = aac_msi && !pci_enable_msi(dev->pdev); | 647 | dev->msi = aac_msi && !pci_enable_msi(dev->pdev); |
647 | if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, | 648 | if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, |
648 | IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) { | 649 | IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) { |
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c index e5d4457121ea..beb533630d4b 100644 --- a/drivers/scsi/aacraid/sa.c +++ b/drivers/scsi/aacraid/sa.c | |||
@@ -385,6 +385,7 @@ int aac_sa_init(struct aac_dev *dev) | |||
385 | 385 | ||
386 | if(aac_init_adapter(dev) == NULL) | 386 | if(aac_init_adapter(dev) == NULL) |
387 | goto error_irq; | 387 | goto error_irq; |
388 | dev->sync_mode = 0; /* sync. mode not supported */ | ||
388 | if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, | 389 | if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, |
389 | IRQF_SHARED|IRQF_DISABLED, | 390 | IRQF_SHARED|IRQF_DISABLED, |
390 | "aacraid", (void *)dev ) < 0) { | 391 | "aacraid", (void *)dev ) < 0) { |
diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index 957595a7a45c..2bee51506a91 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c | |||
@@ -96,6 +96,38 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id) | |||
96 | our_interrupt = 1; | 96 | our_interrupt = 1; |
97 | /* handle AIF */ | 97 | /* handle AIF */ |
98 | aac_intr_normal(dev, 0, 2, 0, NULL); | 98 | aac_intr_normal(dev, 0, 2, 0, NULL); |
99 | } else if (bellbits_shifted & OUTBOUNDDOORBELL_0) { | ||
100 | unsigned long sflags; | ||
101 | struct list_head *entry; | ||
102 | int send_it = 0; | ||
103 | |||
104 | if (dev->sync_fib) { | ||
105 | our_interrupt = 1; | ||
106 | if (dev->sync_fib->callback) | ||
107 | dev->sync_fib->callback(dev->sync_fib->callback_data, | ||
108 | dev->sync_fib); | ||
109 | spin_lock_irqsave(&dev->sync_fib->event_lock, sflags); | ||
110 | if (dev->sync_fib->flags & FIB_CONTEXT_FLAG_WAIT) { | ||
111 | dev->management_fib_count--; | ||
112 | up(&dev->sync_fib->event_wait); | ||
113 | } | ||
114 | spin_unlock_irqrestore(&dev->sync_fib->event_lock, sflags); | ||
115 | spin_lock_irqsave(&dev->sync_lock, sflags); | ||
116 | if (!list_empty(&dev->sync_fib_list)) { | ||
117 | entry = dev->sync_fib_list.next; | ||
118 | dev->sync_fib = list_entry(entry, struct fib, fiblink); | ||
119 | list_del(entry); | ||
120 | send_it = 1; | ||
121 | } else { | ||
122 | dev->sync_fib = NULL; | ||
123 | } | ||
124 | spin_unlock_irqrestore(&dev->sync_lock, sflags); | ||
125 | if (send_it) { | ||
126 | aac_adapter_sync_cmd(dev, SEND_SYNCHRONOUS_FIB, | ||
127 | (u32)dev->sync_fib->hw_fib_pa, 0, 0, 0, 0, 0, | ||
128 | NULL, NULL, NULL, NULL, NULL); | ||
129 | } | ||
130 | } | ||
99 | } | 131 | } |
100 | } | 132 | } |
101 | 133 | ||
@@ -177,56 +209,63 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command, | |||
177 | */ | 209 | */ |
178 | src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT); | 210 | src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT); |
179 | 211 | ||
180 | ok = 0; | 212 | if (!dev->sync_mode || command != SEND_SYNCHRONOUS_FIB) { |
181 | start = jiffies; | 213 | ok = 0; |
214 | start = jiffies; | ||
182 | 215 | ||
183 | /* | 216 | /* |
184 | * Wait up to 30 seconds | 217 | * Wait up to 5 minutes |
185 | */ | ||
186 | while (time_before(jiffies, start+30*HZ)) { | ||
187 | /* Delay 5 microseconds to let Mon960 get info. */ | ||
188 | udelay(5); | ||
189 | |||
190 | /* Mon960 will set doorbell0 bit | ||
191 | * when it has completed the command | ||
192 | */ | 218 | */ |
193 | if ((src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT) & OUTBOUNDDOORBELL_0) { | 219 | while (time_before(jiffies, start+300*HZ)) { |
194 | /* Clear the doorbell */ | 220 | udelay(5); /* Delay 5 microseconds to let Mon960 get info. */ |
195 | src_writel(dev, | 221 | /* |
196 | MUnit.ODR_C, | 222 | * Mon960 will set doorbell0 bit when it has completed the command. |
197 | OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | 223 | */ |
198 | ok = 1; | 224 | if ((src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT) & OUTBOUNDDOORBELL_0) { |
199 | break; | 225 | /* |
226 | * Clear the doorbell. | ||
227 | */ | ||
228 | src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | ||
229 | ok = 1; | ||
230 | break; | ||
231 | } | ||
232 | /* | ||
233 | * Yield the processor in case we are slow | ||
234 | */ | ||
235 | msleep(1); | ||
200 | } | 236 | } |
201 | 237 | if (unlikely(ok != 1)) { | |
202 | /* Yield the processor in case we are slow */ | 238 | /* |
203 | msleep(1); | 239 | * Restore interrupt mask even though we timed out |
204 | } | 240 | */ |
205 | if (unlikely(ok != 1)) { | 241 | aac_adapter_enable_int(dev); |
206 | /* Restore interrupt mask even though we timed out */ | 242 | return -ETIMEDOUT; |
207 | aac_adapter_enable_int(dev); | 243 | } |
208 | return -ETIMEDOUT; | 244 | /* |
245 | * Pull the synch status from Mailbox 0. | ||
246 | */ | ||
247 | if (status) | ||
248 | *status = readl(&dev->IndexRegs->Mailbox[0]); | ||
249 | if (r1) | ||
250 | *r1 = readl(&dev->IndexRegs->Mailbox[1]); | ||
251 | if (r2) | ||
252 | *r2 = readl(&dev->IndexRegs->Mailbox[2]); | ||
253 | if (r3) | ||
254 | *r3 = readl(&dev->IndexRegs->Mailbox[3]); | ||
255 | if (r4) | ||
256 | *r4 = readl(&dev->IndexRegs->Mailbox[4]); | ||
257 | |||
258 | /* | ||
259 | * Clear the synch command doorbell. | ||
260 | */ | ||
261 | src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | ||
209 | } | 262 | } |
210 | 263 | ||
211 | /* Pull the synch status from Mailbox 0 */ | 264 | /* |
212 | if (status) | 265 | * Restore interrupt mask |
213 | *status = readl(&dev->IndexRegs->Mailbox[0]); | 266 | */ |
214 | if (r1) | ||
215 | *r1 = readl(&dev->IndexRegs->Mailbox[1]); | ||
216 | if (r2) | ||
217 | *r2 = readl(&dev->IndexRegs->Mailbox[2]); | ||
218 | if (r3) | ||
219 | *r3 = readl(&dev->IndexRegs->Mailbox[3]); | ||
220 | if (r4) | ||
221 | *r4 = readl(&dev->IndexRegs->Mailbox[4]); | ||
222 | |||
223 | /* Clear the synch command doorbell */ | ||
224 | src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | ||
225 | |||
226 | /* Restore interrupt mask */ | ||
227 | aac_adapter_enable_int(dev); | 267 | aac_adapter_enable_int(dev); |
228 | return 0; | 268 | return 0; |
229 | |||
230 | } | 269 | } |
231 | 270 | ||
232 | /** | 271 | /** |
@@ -386,9 +425,7 @@ static int aac_src_ioremap(struct aac_dev *dev, u32 size) | |||
386 | { | 425 | { |
387 | if (!size) { | 426 | if (!size) { |
388 | iounmap(dev->regs.src.bar0); | 427 | iounmap(dev->regs.src.bar0); |
389 | dev->regs.src.bar0 = NULL; | 428 | dev->base = dev->regs.src.bar0 = NULL; |
390 | iounmap(dev->base); | ||
391 | dev->base = NULL; | ||
392 | return 0; | 429 | return 0; |
393 | } | 430 | } |
394 | dev->regs.src.bar1 = ioremap(pci_resource_start(dev->pdev, 2), | 431 | dev->regs.src.bar1 = ioremap(pci_resource_start(dev->pdev, 2), |
@@ -404,7 +441,27 @@ static int aac_src_ioremap(struct aac_dev *dev, u32 size) | |||
404 | return -1; | 441 | return -1; |
405 | } | 442 | } |
406 | dev->IndexRegs = &((struct src_registers __iomem *) | 443 | dev->IndexRegs = &((struct src_registers __iomem *) |
407 | dev->base)->IndexRegs; | 444 | dev->base)->u.tupelo.IndexRegs; |
445 | return 0; | ||
446 | } | ||
447 | |||
448 | /** | ||
449 | * aac_srcv_ioremap | ||
450 | * @size: mapping resize request | ||
451 | * | ||
452 | */ | ||
453 | static int aac_srcv_ioremap(struct aac_dev *dev, u32 size) | ||
454 | { | ||
455 | if (!size) { | ||
456 | iounmap(dev->regs.src.bar0); | ||
457 | dev->base = dev->regs.src.bar0 = NULL; | ||
458 | return 0; | ||
459 | } | ||
460 | dev->base = dev->regs.src.bar0 = ioremap(dev->scsi_host_ptr->base, size); | ||
461 | if (dev->base == NULL) | ||
462 | return -1; | ||
463 | dev->IndexRegs = &((struct src_registers __iomem *) | ||
464 | dev->base)->u.denali.IndexRegs; | ||
408 | return 0; | 465 | return 0; |
409 | } | 466 | } |
410 | 467 | ||
@@ -419,7 +476,7 @@ static int aac_src_restart_adapter(struct aac_dev *dev, int bled) | |||
419 | bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, | 476 | bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, |
420 | 0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL); | 477 | 0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL); |
421 | if (bled || (var != 0x00000001)) | 478 | if (bled || (var != 0x00000001)) |
422 | bled = -EINVAL; | 479 | return -EINVAL; |
423 | if (dev->supplement_adapter_info.SupportedOptions2 & | 480 | if (dev->supplement_adapter_info.SupportedOptions2 & |
424 | AAC_OPTION_DOORBELL_RESET) { | 481 | AAC_OPTION_DOORBELL_RESET) { |
425 | src_writel(dev, MUnit.IDR, reset_mask); | 482 | src_writel(dev, MUnit.IDR, reset_mask); |
@@ -579,15 +636,149 @@ int aac_src_init(struct aac_dev *dev) | |||
579 | dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE; | 636 | dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE; |
580 | 637 | ||
581 | aac_adapter_enable_int(dev); | 638 | aac_adapter_enable_int(dev); |
639 | |||
640 | if (!dev->sync_mode) { | ||
641 | /* | ||
642 | * Tell the adapter that all is configured, and it can | ||
643 | * start accepting requests | ||
644 | */ | ||
645 | aac_src_start_adapter(dev); | ||
646 | } | ||
647 | return 0; | ||
648 | |||
649 | error_iounmap: | ||
650 | |||
651 | return -1; | ||
652 | } | ||
653 | |||
654 | /** | ||
655 | * aac_srcv_init - initialize an SRCv card | ||
656 | * @dev: device to configure | ||
657 | * | ||
658 | */ | ||
659 | |||
660 | int aac_srcv_init(struct aac_dev *dev) | ||
661 | { | ||
662 | unsigned long start; | ||
663 | unsigned long status; | ||
664 | int restart = 0; | ||
665 | int instance = dev->id; | ||
666 | const char *name = dev->name; | ||
667 | |||
668 | dev->a_ops.adapter_ioremap = aac_srcv_ioremap; | ||
669 | dev->a_ops.adapter_comm = aac_src_select_comm; | ||
670 | |||
671 | dev->base_size = AAC_MIN_SRCV_BAR0_SIZE; | ||
672 | if (aac_adapter_ioremap(dev, dev->base_size)) { | ||
673 | printk(KERN_WARNING "%s: unable to map adapter.\n", name); | ||
674 | goto error_iounmap; | ||
675 | } | ||
676 | |||
677 | /* Failure to reset here is an option ... */ | ||
678 | dev->a_ops.adapter_sync_cmd = src_sync_cmd; | ||
679 | dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; | ||
680 | if ((aac_reset_devices || reset_devices) && | ||
681 | !aac_src_restart_adapter(dev, 0)) | ||
682 | ++restart; | ||
582 | /* | 683 | /* |
583 | * Tell the adapter that all is configured, and it can | 684 | * Check to see if the board panic'd while booting. |
584 | * start accepting requests | ||
585 | */ | 685 | */ |
586 | aac_src_start_adapter(dev); | 686 | status = src_readl(dev, MUnit.OMR); |
687 | if (status & KERNEL_PANIC) { | ||
688 | if (aac_src_restart_adapter(dev, aac_src_check_health(dev))) | ||
689 | goto error_iounmap; | ||
690 | ++restart; | ||
691 | } | ||
692 | /* | ||
693 | * Check to see if the board failed any self tests. | ||
694 | */ | ||
695 | status = src_readl(dev, MUnit.OMR); | ||
696 | if (status & SELF_TEST_FAILED) { | ||
697 | printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance); | ||
698 | goto error_iounmap; | ||
699 | } | ||
700 | /* | ||
701 | * Check to see if the monitor panic'd while booting. | ||
702 | */ | ||
703 | if (status & MONITOR_PANIC) { | ||
704 | printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance); | ||
705 | goto error_iounmap; | ||
706 | } | ||
707 | start = jiffies; | ||
708 | /* | ||
709 | * Wait for the adapter to be up and running. Wait up to 3 minutes | ||
710 | */ | ||
711 | while (!((status = src_readl(dev, MUnit.OMR)) & KERNEL_UP_AND_RUNNING)) { | ||
712 | if ((restart && | ||
713 | (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) || | ||
714 | time_after(jiffies, start+HZ*startup_timeout)) { | ||
715 | printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", | ||
716 | dev->name, instance, status); | ||
717 | goto error_iounmap; | ||
718 | } | ||
719 | if (!restart && | ||
720 | ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) || | ||
721 | time_after(jiffies, start + HZ * | ||
722 | ((startup_timeout > 60) | ||
723 | ? (startup_timeout - 60) | ||
724 | : (startup_timeout / 2))))) { | ||
725 | if (likely(!aac_src_restart_adapter(dev, aac_src_check_health(dev)))) | ||
726 | start = jiffies; | ||
727 | ++restart; | ||
728 | } | ||
729 | msleep(1); | ||
730 | } | ||
731 | if (restart && aac_commit) | ||
732 | aac_commit = 1; | ||
733 | /* | ||
734 | * Fill in the common function dispatch table. | ||
735 | */ | ||
736 | dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter; | ||
737 | dev->a_ops.adapter_disable_int = aac_src_disable_interrupt; | ||
738 | dev->a_ops.adapter_notify = aac_src_notify_adapter; | ||
739 | dev->a_ops.adapter_sync_cmd = src_sync_cmd; | ||
740 | dev->a_ops.adapter_check_health = aac_src_check_health; | ||
741 | dev->a_ops.adapter_restart = aac_src_restart_adapter; | ||
742 | |||
743 | /* | ||
744 | * First clear out all interrupts. Then enable the one's that we | ||
745 | * can handle. | ||
746 | */ | ||
747 | aac_adapter_comm(dev, AAC_COMM_MESSAGE); | ||
748 | aac_adapter_disable_int(dev); | ||
749 | src_writel(dev, MUnit.ODR_C, 0xffffffff); | ||
750 | aac_adapter_enable_int(dev); | ||
587 | 751 | ||
752 | if (aac_init_adapter(dev) == NULL) | ||
753 | goto error_iounmap; | ||
754 | if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1) | ||
755 | goto error_iounmap; | ||
756 | dev->msi = aac_msi && !pci_enable_msi(dev->pdev); | ||
757 | if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, | ||
758 | IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) { | ||
759 | if (dev->msi) | ||
760 | pci_disable_msi(dev->pdev); | ||
761 | printk(KERN_ERR "%s%d: Interrupt unavailable.\n", | ||
762 | name, instance); | ||
763 | goto error_iounmap; | ||
764 | } | ||
765 | dev->dbg_base = dev->scsi_host_ptr->base; | ||
766 | dev->dbg_base_mapped = dev->base; | ||
767 | dev->dbg_size = dev->base_size; | ||
768 | |||
769 | aac_adapter_enable_int(dev); | ||
770 | |||
771 | if (!dev->sync_mode) { | ||
772 | /* | ||
773 | * Tell the adapter that all is configured, and it can | ||
774 | * start accepting requests | ||
775 | */ | ||
776 | aac_src_start_adapter(dev); | ||
777 | } | ||
588 | return 0; | 778 | return 0; |
589 | 779 | ||
590 | error_iounmap: | 780 | error_iounmap: |
591 | 781 | ||
592 | return -1; | 782 | return -1; |
593 | } | 783 | } |
784 | |||