diff options
-rw-r--r-- | drivers/scsi/aacraid/aacraid.h | 80 | ||||
-rw-r--r-- | drivers/scsi/aacraid/comminit.c | 95 | ||||
-rw-r--r-- | drivers/scsi/aacraid/commsup.c | 20 | ||||
-rw-r--r-- | drivers/scsi/aacraid/dpcsup.c | 9 | ||||
-rw-r--r-- | drivers/scsi/aacraid/linit.c | 20 | ||||
-rw-r--r-- | drivers/scsi/aacraid/src.c | 388 |
6 files changed, 505 insertions, 107 deletions
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 9e38b209787d..015c341f26f9 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h | |||
@@ -6,11 +6,61 @@ | |||
6 | #define nblank(x) _nblank(x)[0] | 6 | #define nblank(x) _nblank(x)[0] |
7 | 7 | ||
8 | #include <linux/interrupt.h> | 8 | #include <linux/interrupt.h> |
9 | #include <linux/pci.h> | ||
9 | 10 | ||
10 | /*------------------------------------------------------------------------------ | 11 | /*------------------------------------------------------------------------------ |
11 | * D E F I N E S | 12 | * D E F I N E S |
12 | *----------------------------------------------------------------------------*/ | 13 | *----------------------------------------------------------------------------*/ |
13 | 14 | ||
15 | #define AAC_MAX_MSIX 32 /* vectors */ | ||
16 | #define AAC_PCI_MSI_ENABLE 0x8000 | ||
17 | |||
18 | enum { | ||
19 | AAC_ENABLE_INTERRUPT = 0x0, | ||
20 | AAC_DISABLE_INTERRUPT, | ||
21 | AAC_ENABLE_MSIX, | ||
22 | AAC_DISABLE_MSIX, | ||
23 | AAC_CLEAR_AIF_BIT, | ||
24 | AAC_CLEAR_SYNC_BIT, | ||
25 | AAC_ENABLE_INTX | ||
26 | }; | ||
27 | |||
28 | #define AAC_INT_MODE_INTX (1<<0) | ||
29 | #define AAC_INT_MODE_MSI (1<<1) | ||
30 | #define AAC_INT_MODE_AIF (1<<2) | ||
31 | #define AAC_INT_MODE_SYNC (1<<3) | ||
32 | |||
33 | #define AAC_INT_ENABLE_TYPE1_INTX 0xfffffffb | ||
34 | #define AAC_INT_ENABLE_TYPE1_MSIX 0xfffffffa | ||
35 | #define AAC_INT_DISABLE_ALL 0xffffffff | ||
36 | |||
37 | /* Bit definitions in IOA->Host Interrupt Register */ | ||
38 | #define PMC_TRANSITION_TO_OPERATIONAL (1<<31) | ||
39 | #define PMC_IOARCB_TRANSFER_FAILED (1<<28) | ||
40 | #define PMC_IOA_UNIT_CHECK (1<<27) | ||
41 | #define PMC_NO_HOST_RRQ_FOR_CMD_RESPONSE (1<<26) | ||
42 | #define PMC_CRITICAL_IOA_OP_IN_PROGRESS (1<<25) | ||
43 | #define PMC_IOARRIN_LOST (1<<4) | ||
44 | #define PMC_SYSTEM_BUS_MMIO_ERROR (1<<3) | ||
45 | #define PMC_IOA_PROCESSOR_IN_ERROR_STATE (1<<2) | ||
46 | #define PMC_HOST_RRQ_VALID (1<<1) | ||
47 | #define PMC_OPERATIONAL_STATUS (1<<31) | ||
48 | #define PMC_ALLOW_MSIX_VECTOR0 (1<<0) | ||
49 | |||
50 | #define PMC_IOA_ERROR_INTERRUPTS (PMC_IOARCB_TRANSFER_FAILED | \ | ||
51 | PMC_IOA_UNIT_CHECK | \ | ||
52 | PMC_NO_HOST_RRQ_FOR_CMD_RESPONSE | \ | ||
53 | PMC_IOARRIN_LOST | \ | ||
54 | PMC_SYSTEM_BUS_MMIO_ERROR | \ | ||
55 | PMC_IOA_PROCESSOR_IN_ERROR_STATE) | ||
56 | |||
57 | #define PMC_ALL_INTERRUPT_BITS (PMC_IOA_ERROR_INTERRUPTS | \ | ||
58 | PMC_HOST_RRQ_VALID | \ | ||
59 | PMC_TRANSITION_TO_OPERATIONAL | \ | ||
60 | PMC_ALLOW_MSIX_VECTOR0) | ||
61 | #define PMC_GLOBAL_INT_BIT2 0x00000004 | ||
62 | #define PMC_GLOBAL_INT_BIT0 0x00000001 | ||
63 | |||
14 | #ifndef AAC_DRIVER_BUILD | 64 | #ifndef AAC_DRIVER_BUILD |
15 | # define AAC_DRIVER_BUILD 30300 | 65 | # define AAC_DRIVER_BUILD 30300 |
16 | # define AAC_DRIVER_BRANCH "-ms" | 66 | # define AAC_DRIVER_BRANCH "-ms" |
@@ -36,6 +86,7 @@ | |||
36 | #define CONTAINER_TO_ID(cont) (cont) | 86 | #define CONTAINER_TO_ID(cont) (cont) |
37 | #define CONTAINER_TO_LUN(cont) (0) | 87 | #define CONTAINER_TO_LUN(cont) (0) |
38 | 88 | ||
89 | #define PMC_DEVICE_S6 0x28b | ||
39 | #define PMC_DEVICE_S7 0x28c | 90 | #define PMC_DEVICE_S7 0x28c |
40 | #define PMC_DEVICE_S8 0x28d | 91 | #define PMC_DEVICE_S8 0x28d |
41 | #define PMC_DEVICE_S9 0x28f | 92 | #define PMC_DEVICE_S9 0x28f |
@@ -434,7 +485,7 @@ enum fib_xfer_state { | |||
434 | struct aac_init | 485 | struct aac_init |
435 | { | 486 | { |
436 | __le32 InitStructRevision; | 487 | __le32 InitStructRevision; |
437 | __le32 MiniPortRevision; | 488 | __le32 Sa_MSIXVectors; |
438 | __le32 fsrev; | 489 | __le32 fsrev; |
439 | __le32 CommHeaderAddress; | 490 | __le32 CommHeaderAddress; |
440 | __le32 FastIoCommAreaAddress; | 491 | __le32 FastIoCommAreaAddress; |
@@ -755,7 +806,8 @@ struct rkt_registers { | |||
755 | 806 | ||
756 | struct src_mu_registers { | 807 | struct src_mu_registers { |
757 | /* PCI*| Name */ | 808 | /* PCI*| Name */ |
758 | __le32 reserved0[8]; /* 00h | Reserved */ | 809 | __le32 reserved0[6]; /* 00h | Reserved */ |
810 | __le32 IOAR[2]; /* 18h | IOA->host interrupt register */ | ||
759 | __le32 IDR; /* 20h | Inbound Doorbell Register */ | 811 | __le32 IDR; /* 20h | Inbound Doorbell Register */ |
760 | __le32 IISR; /* 24h | Inbound Int. Status Register */ | 812 | __le32 IISR; /* 24h | Inbound Int. Status Register */ |
761 | __le32 reserved1[3]; /* 28h | Reserved */ | 813 | __le32 reserved1[3]; /* 28h | Reserved */ |
@@ -767,17 +819,18 @@ struct src_mu_registers { | |||
767 | __le32 OMR; /* bch | Outbound Message Register */ | 819 | __le32 OMR; /* bch | Outbound Message Register */ |
768 | __le32 IQ_L; /* c0h | Inbound Queue (Low address) */ | 820 | __le32 IQ_L; /* c0h | Inbound Queue (Low address) */ |
769 | __le32 IQ_H; /* c4h | Inbound Queue (High address) */ | 821 | __le32 IQ_H; /* c4h | Inbound Queue (High address) */ |
822 | __le32 ODR_MSI; /* c8h | MSI register for sync./AIF */ | ||
770 | }; | 823 | }; |
771 | 824 | ||
772 | struct src_registers { | 825 | struct src_registers { |
773 | struct src_mu_registers MUnit; /* 00h - c7h */ | 826 | struct src_mu_registers MUnit; /* 00h - cbh */ |
774 | union { | 827 | union { |
775 | struct { | 828 | struct { |
776 | __le32 reserved1[130790]; /* c8h - 7fc5fh */ | 829 | __le32 reserved1[130789]; /* cch - 7fc5fh */ |
777 | struct src_inbound IndexRegs; /* 7fc60h */ | 830 | struct src_inbound IndexRegs; /* 7fc60h */ |
778 | } tupelo; | 831 | } tupelo; |
779 | struct { | 832 | struct { |
780 | __le32 reserved1[974]; /* c8h - fffh */ | 833 | __le32 reserved1[973]; /* cch - fffh */ |
781 | struct src_inbound IndexRegs; /* 1000h */ | 834 | struct src_inbound IndexRegs; /* 1000h */ |
782 | } denali; | 835 | } denali; |
783 | } u; | 836 | } u; |
@@ -1029,6 +1082,11 @@ struct aac_bus_info_response { | |||
1029 | #define AAC_OPT_NEW_COMM_TYPE3 cpu_to_le32(1<<30) | 1082 | #define AAC_OPT_NEW_COMM_TYPE3 cpu_to_le32(1<<30) |
1030 | #define AAC_OPT_NEW_COMM_TYPE4 cpu_to_le32(1<<31) | 1083 | #define AAC_OPT_NEW_COMM_TYPE4 cpu_to_le32(1<<31) |
1031 | 1084 | ||
1085 | /* MSIX context */ | ||
1086 | struct aac_msix_ctx { | ||
1087 | int vector_no; | ||
1088 | struct aac_dev *dev; | ||
1089 | }; | ||
1032 | 1090 | ||
1033 | struct aac_dev | 1091 | struct aac_dev |
1034 | { | 1092 | { |
@@ -1084,8 +1142,10 @@ struct aac_dev | |||
1084 | * if AAC_COMM_MESSAGE_TYPE1 */ | 1142 | * if AAC_COMM_MESSAGE_TYPE1 */ |
1085 | 1143 | ||
1086 | dma_addr_t host_rrq_pa; /* phys. address */ | 1144 | dma_addr_t host_rrq_pa; /* phys. address */ |
1087 | u32 host_rrq_idx; /* index into rrq buffer */ | 1145 | /* index into rrq buffer */ |
1088 | 1146 | u32 host_rrq_idx[AAC_MAX_MSIX]; | |
1147 | atomic_t rrq_outstanding[AAC_MAX_MSIX]; | ||
1148 | u32 fibs_pushed_no; | ||
1089 | struct pci_dev *pdev; /* Our PCI interface */ | 1149 | struct pci_dev *pdev; /* Our PCI interface */ |
1090 | void * printfbuf; /* pointer to buffer used for printf's from the adapter */ | 1150 | void * printfbuf; /* pointer to buffer used for printf's from the adapter */ |
1091 | void * comm_addr; /* Base address of Comm area */ | 1151 | void * comm_addr; /* Base address of Comm area */ |
@@ -1154,6 +1214,11 @@ struct aac_dev | |||
1154 | int sync_mode; | 1214 | int sync_mode; |
1155 | struct fib *sync_fib; | 1215 | struct fib *sync_fib; |
1156 | struct list_head sync_fib_list; | 1216 | struct list_head sync_fib_list; |
1217 | u32 max_msix; /* max. MSI-X vectors */ | ||
1218 | u32 vector_cap; /* MSI-X vector capab.*/ | ||
1219 | int msi_enabled; /* MSI/MSI-X enabled */ | ||
1220 | struct msix_entry msixentry[AAC_MAX_MSIX]; | ||
1221 | struct aac_msix_ctx aac_msix[AAC_MAX_MSIX]; /* context */ | ||
1157 | }; | 1222 | }; |
1158 | 1223 | ||
1159 | #define aac_adapter_interrupt(dev) \ | 1224 | #define aac_adapter_interrupt(dev) \ |
@@ -2036,6 +2101,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum); | |||
2036 | int aac_fib_complete(struct fib * context); | 2101 | int aac_fib_complete(struct fib * context); |
2037 | #define fib_data(fibctx) ((void *)(fibctx)->hw_fib_va->data) | 2102 | #define fib_data(fibctx) ((void *)(fibctx)->hw_fib_va->data) |
2038 | struct aac_dev *aac_init_adapter(struct aac_dev *dev); | 2103 | struct aac_dev *aac_init_adapter(struct aac_dev *dev); |
2104 | void aac_src_access_devreg(struct aac_dev *dev, int mode); | ||
2039 | int aac_get_config_status(struct aac_dev *dev, int commit_flag); | 2105 | int aac_get_config_status(struct aac_dev *dev, int commit_flag); |
2040 | int aac_get_containers(struct aac_dev *dev); | 2106 | int aac_get_containers(struct aac_dev *dev); |
2041 | int aac_scsi_cmd(struct scsi_cmnd *cmd); | 2107 | int aac_scsi_cmd(struct scsi_cmnd *cmd); |
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 177b094c7792..fdd95247f034 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c | |||
@@ -43,6 +43,8 @@ | |||
43 | 43 | ||
44 | #include "aacraid.h" | 44 | #include "aacraid.h" |
45 | 45 | ||
46 | static void aac_define_int_mode(struct aac_dev *dev); | ||
47 | |||
46 | struct aac_common aac_config = { | 48 | struct aac_common aac_config = { |
47 | .irq_mod = 1 | 49 | .irq_mod = 1 |
48 | }; | 50 | }; |
@@ -91,7 +93,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co | |||
91 | init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); | 93 | init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); |
92 | if (dev->max_fib_size != sizeof(struct hw_fib)) | 94 | if (dev->max_fib_size != sizeof(struct hw_fib)) |
93 | init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4); | 95 | init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4); |
94 | init->MiniPortRevision = cpu_to_le32(Sa_MINIPORT_REVISION); | 96 | init->Sa_MSIXVectors = cpu_to_le32(Sa_MINIPORT_REVISION); |
95 | init->fsrev = cpu_to_le32(dev->fsrev); | 97 | init->fsrev = cpu_to_le32(dev->fsrev); |
96 | 98 | ||
97 | /* | 99 | /* |
@@ -140,7 +142,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co | |||
140 | INITFLAGS_NEW_COMM_TYPE2_SUPPORTED | INITFLAGS_FAST_JBOD_SUPPORTED); | 142 | INITFLAGS_NEW_COMM_TYPE2_SUPPORTED | INITFLAGS_FAST_JBOD_SUPPORTED); |
141 | init->HostRRQ_AddrHigh = cpu_to_le32((u32)((u64)dev->host_rrq_pa >> 32)); | 143 | init->HostRRQ_AddrHigh = cpu_to_le32((u32)((u64)dev->host_rrq_pa >> 32)); |
142 | init->HostRRQ_AddrLow = cpu_to_le32((u32)(dev->host_rrq_pa & 0xffffffff)); | 144 | init->HostRRQ_AddrLow = cpu_to_le32((u32)(dev->host_rrq_pa & 0xffffffff)); |
143 | init->MiniPortRevision = cpu_to_le32(0L); /* number of MSI-X */ | 145 | /* number of MSI-X */ |
146 | init->Sa_MSIXVectors = cpu_to_le32(dev->max_msix); | ||
144 | dprintk((KERN_WARNING"aacraid: New Comm Interface type2 enabled\n")); | 147 | dprintk((KERN_WARNING"aacraid: New Comm Interface type2 enabled\n")); |
145 | } | 148 | } |
146 | 149 | ||
@@ -228,6 +231,11 @@ int aac_send_shutdown(struct aac_dev * dev) | |||
228 | /* FIB should be freed only after getting the response from the F/W */ | 231 | /* FIB should be freed only after getting the response from the F/W */ |
229 | if (status != -ERESTARTSYS) | 232 | if (status != -ERESTARTSYS) |
230 | aac_fib_free(fibctx); | 233 | aac_fib_free(fibctx); |
234 | if ((dev->pdev->device == PMC_DEVICE_S7 || | ||
235 | dev->pdev->device == PMC_DEVICE_S8 || | ||
236 | dev->pdev->device == PMC_DEVICE_S9) && | ||
237 | dev->msi_enabled) | ||
238 | aac_src_access_devreg(dev, AAC_ENABLE_INTX); | ||
231 | return status; | 239 | return status; |
232 | } | 240 | } |
233 | 241 | ||
@@ -388,6 +396,8 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) | |||
388 | } | 396 | } |
389 | } | 397 | } |
390 | } | 398 | } |
399 | dev->max_msix = 0; | ||
400 | dev->msi_enabled = 0; | ||
391 | if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS, | 401 | if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS, |
392 | 0, 0, 0, 0, 0, 0, | 402 | 0, 0, 0, 0, 0, 0, |
393 | status+0, status+1, status+2, status+3, status+4)) | 403 | status+0, status+1, status+2, status+3, status+4)) |
@@ -461,6 +471,11 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) | |||
461 | if (host->can_queue > AAC_NUM_IO_FIB) | 471 | if (host->can_queue > AAC_NUM_IO_FIB) |
462 | host->can_queue = AAC_NUM_IO_FIB; | 472 | host->can_queue = AAC_NUM_IO_FIB; |
463 | 473 | ||
474 | if (dev->pdev->device == PMC_DEVICE_S6 || | ||
475 | dev->pdev->device == PMC_DEVICE_S7 || | ||
476 | dev->pdev->device == PMC_DEVICE_S8 || | ||
477 | dev->pdev->device == PMC_DEVICE_S9) | ||
478 | aac_define_int_mode(dev); | ||
464 | /* | 479 | /* |
465 | * Ok now init the communication subsystem | 480 | * Ok now init the communication subsystem |
466 | */ | 481 | */ |
@@ -489,4 +504,78 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) | |||
489 | return dev; | 504 | return dev; |
490 | } | 505 | } |
491 | 506 | ||
492 | 507 | static void aac_define_int_mode(struct aac_dev *dev) | |
508 | { | ||
509 | |||
510 | int i, msi_count; | ||
511 | |||
512 | /* max. vectors from GET_COMM_PREFERRED_SETTINGS */ | ||
513 | if (dev->max_msix == 0 || | ||
514 | dev->pdev->device == PMC_DEVICE_S6 || | ||
515 | dev->sync_mode) { | ||
516 | dev->max_msix = 1; | ||
517 | dev->vector_cap = | ||
518 | dev->scsi_host_ptr->can_queue + | ||
519 | AAC_NUM_MGT_FIB; | ||
520 | return; | ||
521 | } | ||
522 | |||
523 | msi_count = min(dev->max_msix, | ||
524 | (unsigned int)num_online_cpus()); | ||
525 | |||
526 | dev->max_msix = msi_count; | ||
527 | |||
528 | if (msi_count > AAC_MAX_MSIX) | ||
529 | msi_count = AAC_MAX_MSIX; | ||
530 | |||
531 | for (i = 0; i < msi_count; i++) | ||
532 | dev->msixentry[i].entry = i; | ||
533 | |||
534 | if (msi_count > 1 && | ||
535 | pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX)) { | ||
536 | i = pci_enable_msix(dev->pdev, | ||
537 | dev->msixentry, | ||
538 | msi_count); | ||
539 | /* Check how many MSIX vectors are allocated */ | ||
540 | if (i >= 0) { | ||
541 | dev->msi_enabled = 1; | ||
542 | if (i) { | ||
543 | msi_count = i; | ||
544 | if (pci_enable_msix(dev->pdev, | ||
545 | dev->msixentry, | ||
546 | msi_count)) { | ||
547 | dev->msi_enabled = 0; | ||
548 | printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n", | ||
549 | dev->name, dev->id, i); | ||
550 | } | ||
551 | } | ||
552 | } else { | ||
553 | dev->msi_enabled = 0; | ||
554 | printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n", | ||
555 | dev->name, dev->id, i); | ||
556 | } | ||
557 | } | ||
558 | |||
559 | if (!dev->msi_enabled) { | ||
560 | msi_count = 1; | ||
561 | i = pci_enable_msi(dev->pdev); | ||
562 | |||
563 | if (!i) { | ||
564 | dev->msi_enabled = 1; | ||
565 | dev->msi = 1; | ||
566 | } else { | ||
567 | printk(KERN_ERR "%s%d: MSI not supported!! Will try INTx 0x%x.\n", | ||
568 | dev->name, dev->id, i); | ||
569 | } | ||
570 | } | ||
571 | |||
572 | if (!dev->msi_enabled) | ||
573 | dev->max_msix = msi_count = 1; | ||
574 | else { | ||
575 | if (dev->max_msix > msi_count) | ||
576 | dev->max_msix = msi_count; | ||
577 | } | ||
578 | dev->vector_cap = | ||
579 | (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) / | ||
580 | msi_count; | ||
581 | } | ||
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 090ba681ff36..e615a0b34263 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c | |||
@@ -868,7 +868,7 @@ void aac_printf(struct aac_dev *dev, u32 val) | |||
868 | * dispatches it to the appropriate routine for handling. | 868 | * dispatches it to the appropriate routine for handling. |
869 | */ | 869 | */ |
870 | 870 | ||
871 | #define AIF_SNIFF_TIMEOUT (30*HZ) | 871 | #define AIF_SNIFF_TIMEOUT (500*HZ) |
872 | static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | 872 | static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) |
873 | { | 873 | { |
874 | struct hw_fib * hw_fib = fibptr->hw_fib_va; | 874 | struct hw_fib * hw_fib = fibptr->hw_fib_va; |
@@ -1251,7 +1251,7 @@ retry_next: | |||
1251 | static int _aac_reset_adapter(struct aac_dev *aac, int forced) | 1251 | static int _aac_reset_adapter(struct aac_dev *aac, int forced) |
1252 | { | 1252 | { |
1253 | int index, quirks; | 1253 | int index, quirks; |
1254 | int retval; | 1254 | int retval, i; |
1255 | struct Scsi_Host *host; | 1255 | struct Scsi_Host *host; |
1256 | struct scsi_device *dev; | 1256 | struct scsi_device *dev; |
1257 | struct scsi_cmnd *command; | 1257 | struct scsi_cmnd *command; |
@@ -1319,7 +1319,21 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced) | |||
1319 | aac->comm_phys = 0; | 1319 | aac->comm_phys = 0; |
1320 | kfree(aac->queues); | 1320 | kfree(aac->queues); |
1321 | aac->queues = NULL; | 1321 | aac->queues = NULL; |
1322 | free_irq(aac->pdev->irq, aac); | 1322 | if (aac->pdev->device == PMC_DEVICE_S6 || |
1323 | aac->pdev->device == PMC_DEVICE_S7 || | ||
1324 | aac->pdev->device == PMC_DEVICE_S8 || | ||
1325 | aac->pdev->device == PMC_DEVICE_S9) { | ||
1326 | if (aac->max_msix > 1) { | ||
1327 | for (i = 0; i < aac->max_msix; i++) | ||
1328 | free_irq(aac->msixentry[i].vector, | ||
1329 | &(aac->aac_msix[i])); | ||
1330 | pci_disable_msix(aac->pdev); | ||
1331 | } else { | ||
1332 | free_irq(aac->pdev->irq, &(aac->aac_msix[0])); | ||
1333 | } | ||
1334 | } else { | ||
1335 | free_irq(aac->pdev->irq, aac); | ||
1336 | } | ||
1323 | if (aac->msi) | 1337 | if (aac->msi) |
1324 | pci_disable_msi(aac->pdev); | 1338 | pci_disable_msi(aac->pdev); |
1325 | kfree(aac->fsa_dev); | 1339 | kfree(aac->fsa_dev); |
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index d81b2810f0f7..2e394662d52f 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c | |||
@@ -389,8 +389,13 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, | |||
389 | * NOTE: we cannot touch the fib after this | 389 | * NOTE: we cannot touch the fib after this |
390 | * call, because it may have been deallocated. | 390 | * call, because it may have been deallocated. |
391 | */ | 391 | */ |
392 | fib->flags &= FIB_CONTEXT_FLAG_FASTRESP; | 392 | if (likely(fib->callback && fib->callback_data)) { |
393 | fib->callback(fib->callback_data, fib); | 393 | fib->flags &= FIB_CONTEXT_FLAG_FASTRESP; |
394 | fib->callback(fib->callback_data, fib); | ||
395 | } else { | ||
396 | aac_fib_complete(fib); | ||
397 | aac_fib_free(fib); | ||
398 | } | ||
394 | } else { | 399 | } else { |
395 | unsigned long flagv; | 400 | unsigned long flagv; |
396 | dprintk((KERN_INFO "event_wait up\n")); | 401 | dprintk((KERN_INFO "event_wait up\n")); |
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index fdcdf9f781bc..75c3501e51b3 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c | |||
@@ -1082,6 +1082,8 @@ static struct scsi_host_template aac_driver_template = { | |||
1082 | 1082 | ||
1083 | static void __aac_shutdown(struct aac_dev * aac) | 1083 | static void __aac_shutdown(struct aac_dev * aac) |
1084 | { | 1084 | { |
1085 | int i; | ||
1086 | |||
1085 | if (aac->aif_thread) { | 1087 | if (aac->aif_thread) { |
1086 | int i; | 1088 | int i; |
1087 | /* Clear out events first */ | 1089 | /* Clear out events first */ |
@@ -1095,9 +1097,25 @@ static void __aac_shutdown(struct aac_dev * aac) | |||
1095 | } | 1097 | } |
1096 | aac_send_shutdown(aac); | 1098 | aac_send_shutdown(aac); |
1097 | aac_adapter_disable_int(aac); | 1099 | aac_adapter_disable_int(aac); |
1098 | free_irq(aac->pdev->irq, aac); | 1100 | if (aac->pdev->device == PMC_DEVICE_S6 || |
1101 | aac->pdev->device == PMC_DEVICE_S7 || | ||
1102 | aac->pdev->device == PMC_DEVICE_S8 || | ||
1103 | aac->pdev->device == PMC_DEVICE_S9) { | ||
1104 | if (aac->max_msix > 1) { | ||
1105 | for (i = 0; i < aac->max_msix; i++) | ||
1106 | free_irq(aac->msixentry[i].vector, | ||
1107 | &(aac->aac_msix[i])); | ||
1108 | } else { | ||
1109 | free_irq(aac->pdev->irq, | ||
1110 | &(aac->aac_msix[0])); | ||
1111 | } | ||
1112 | } else { | ||
1113 | free_irq(aac->pdev->irq, aac); | ||
1114 | } | ||
1099 | if (aac->msi) | 1115 | if (aac->msi) |
1100 | pci_disable_msi(aac->pdev); | 1116 | pci_disable_msi(aac->pdev); |
1117 | else if (aac->max_msix > 1) | ||
1118 | pci_disable_msix(aac->pdev); | ||
1101 | } | 1119 | } |
1102 | 1120 | ||
1103 | static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | 1121 | static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) |
diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index 9c65aed26212..50f181f6d1be 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c | |||
@@ -44,98 +44,128 @@ | |||
44 | 44 | ||
45 | #include "aacraid.h" | 45 | #include "aacraid.h" |
46 | 46 | ||
47 | static irqreturn_t aac_src_intr_message(int irq, void *dev_id) | 47 | static int aac_src_get_sync_status(struct aac_dev *dev); |
48 | |||
49 | irqreturn_t aac_src_intr_message(int irq, void *dev_id) | ||
48 | { | 50 | { |
49 | struct aac_dev *dev = dev_id; | 51 | struct aac_msix_ctx *ctx; |
52 | struct aac_dev *dev; | ||
50 | unsigned long bellbits, bellbits_shifted; | 53 | unsigned long bellbits, bellbits_shifted; |
51 | int our_interrupt = 0; | 54 | int vector_no; |
52 | int isFastResponse; | 55 | int isFastResponse, mode; |
53 | u32 index, handle; | 56 | u32 index, handle; |
54 | 57 | ||
55 | bellbits = src_readl(dev, MUnit.ODR_R); | 58 | ctx = (struct aac_msix_ctx *)dev_id; |
56 | if (bellbits & PmDoorBellResponseSent) { | 59 | dev = ctx->dev; |
57 | bellbits = PmDoorBellResponseSent; | 60 | vector_no = ctx->vector_no; |
58 | /* handle async. status */ | 61 | |
59 | src_writel(dev, MUnit.ODR_C, bellbits); | 62 | if (dev->msi_enabled) { |
60 | src_readl(dev, MUnit.ODR_C); | 63 | mode = AAC_INT_MODE_MSI; |
61 | our_interrupt = 1; | 64 | if (vector_no == 0) { |
62 | index = dev->host_rrq_idx; | 65 | bellbits = src_readl(dev, MUnit.ODR_MSI); |
63 | for (;;) { | 66 | if (bellbits & 0x40000) |
64 | isFastResponse = 0; | 67 | mode |= AAC_INT_MODE_AIF; |
65 | /* remove toggle bit (31) */ | 68 | if (bellbits & 0x1000) |
66 | handle = le32_to_cpu(dev->host_rrq[index]) & 0x7fffffff; | 69 | mode |= AAC_INT_MODE_SYNC; |
67 | /* check fast response bit (30) */ | ||
68 | if (handle & 0x40000000) | ||
69 | isFastResponse = 1; | ||
70 | handle &= 0x0000ffff; | ||
71 | if (handle == 0) | ||
72 | break; | ||
73 | |||
74 | aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL); | ||
75 | |||
76 | dev->host_rrq[index++] = 0; | ||
77 | if (index == dev->scsi_host_ptr->can_queue + | ||
78 | AAC_NUM_MGT_FIB) | ||
79 | index = 0; | ||
80 | dev->host_rrq_idx = index; | ||
81 | } | 70 | } |
82 | } else { | 71 | } else { |
83 | bellbits_shifted = (bellbits >> SRC_ODR_SHIFT); | 72 | mode = AAC_INT_MODE_INTX; |
84 | if (bellbits_shifted & DoorBellAifPending) { | 73 | bellbits = src_readl(dev, MUnit.ODR_R); |
74 | if (bellbits & PmDoorBellResponseSent) { | ||
75 | bellbits = PmDoorBellResponseSent; | ||
76 | src_writel(dev, MUnit.ODR_C, bellbits); | ||
77 | src_readl(dev, MUnit.ODR_C); | ||
78 | } else { | ||
79 | bellbits_shifted = (bellbits >> SRC_ODR_SHIFT); | ||
85 | src_writel(dev, MUnit.ODR_C, bellbits); | 80 | src_writel(dev, MUnit.ODR_C, bellbits); |
86 | src_readl(dev, MUnit.ODR_C); | 81 | src_readl(dev, MUnit.ODR_C); |
87 | our_interrupt = 1; | ||
88 | /* handle AIF */ | ||
89 | aac_intr_normal(dev, 0, 2, 0, NULL); | ||
90 | } else if (bellbits_shifted & OUTBOUNDDOORBELL_0) { | ||
91 | unsigned long sflags; | ||
92 | struct list_head *entry; | ||
93 | int send_it = 0; | ||
94 | extern int aac_sync_mode; | ||
95 | 82 | ||
83 | if (bellbits_shifted & DoorBellAifPending) | ||
84 | mode |= AAC_INT_MODE_AIF; | ||
85 | else if (bellbits_shifted & OUTBOUNDDOORBELL_0) | ||
86 | mode |= AAC_INT_MODE_SYNC; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | if (mode & AAC_INT_MODE_SYNC) { | ||
91 | unsigned long sflags; | ||
92 | struct list_head *entry; | ||
93 | int send_it = 0; | ||
94 | extern int aac_sync_mode; | ||
95 | |||
96 | if (!aac_sync_mode && !dev->msi_enabled) { | ||
96 | src_writel(dev, MUnit.ODR_C, bellbits); | 97 | src_writel(dev, MUnit.ODR_C, bellbits); |
97 | src_readl(dev, MUnit.ODR_C); | 98 | src_readl(dev, MUnit.ODR_C); |
99 | } | ||
98 | 100 | ||
99 | if (!aac_sync_mode) { | 101 | if (dev->sync_fib) { |
100 | src_writel(dev, MUnit.ODR_C, bellbits); | 102 | if (dev->sync_fib->callback) |
101 | src_readl(dev, MUnit.ODR_C); | 103 | dev->sync_fib->callback(dev->sync_fib->callback_data, |
102 | our_interrupt = 1; | 104 | dev->sync_fib); |
105 | spin_lock_irqsave(&dev->sync_fib->event_lock, sflags); | ||
106 | if (dev->sync_fib->flags & FIB_CONTEXT_FLAG_WAIT) { | ||
107 | dev->management_fib_count--; | ||
108 | up(&dev->sync_fib->event_wait); | ||
103 | } | 109 | } |
104 | 110 | spin_unlock_irqrestore(&dev->sync_fib->event_lock, | |
105 | if (dev->sync_fib) { | 111 | sflags); |
106 | our_interrupt = 1; | 112 | spin_lock_irqsave(&dev->sync_lock, sflags); |
107 | if (dev->sync_fib->callback) | 113 | if (!list_empty(&dev->sync_fib_list)) { |
108 | dev->sync_fib->callback(dev->sync_fib->callback_data, | 114 | entry = dev->sync_fib_list.next; |
109 | dev->sync_fib); | 115 | dev->sync_fib = list_entry(entry, |
110 | spin_lock_irqsave(&dev->sync_fib->event_lock, sflags); | 116 | struct fib, |
111 | if (dev->sync_fib->flags & FIB_CONTEXT_FLAG_WAIT) { | 117 | fiblink); |
112 | dev->management_fib_count--; | 118 | list_del(entry); |
113 | up(&dev->sync_fib->event_wait); | 119 | send_it = 1; |
114 | } | 120 | } else { |
115 | spin_unlock_irqrestore(&dev->sync_fib->event_lock, sflags); | 121 | dev->sync_fib = NULL; |
116 | spin_lock_irqsave(&dev->sync_lock, sflags); | 122 | } |
117 | if (!list_empty(&dev->sync_fib_list)) { | 123 | spin_unlock_irqrestore(&dev->sync_lock, sflags); |
118 | entry = dev->sync_fib_list.next; | 124 | if (send_it) { |
119 | dev->sync_fib = list_entry(entry, struct fib, fiblink); | 125 | aac_adapter_sync_cmd(dev, SEND_SYNCHRONOUS_FIB, |
120 | list_del(entry); | 126 | (u32)dev->sync_fib->hw_fib_pa, |
121 | send_it = 1; | 127 | 0, 0, 0, 0, 0, |
122 | } else { | 128 | NULL, NULL, NULL, NULL, NULL); |
123 | dev->sync_fib = NULL; | ||
124 | } | ||
125 | spin_unlock_irqrestore(&dev->sync_lock, sflags); | ||
126 | if (send_it) { | ||
127 | aac_adapter_sync_cmd(dev, SEND_SYNCHRONOUS_FIB, | ||
128 | (u32)dev->sync_fib->hw_fib_pa, 0, 0, 0, 0, 0, | ||
129 | NULL, NULL, NULL, NULL, NULL); | ||
130 | } | ||
131 | } | 129 | } |
132 | } | 130 | } |
131 | if (!dev->msi_enabled) | ||
132 | mode = 0; | ||
133 | |||
133 | } | 134 | } |
134 | 135 | ||
135 | if (our_interrupt) { | 136 | if (mode & AAC_INT_MODE_AIF) { |
136 | return IRQ_HANDLED; | 137 | /* handle AIF */ |
138 | aac_intr_normal(dev, 0, 2, 0, NULL); | ||
139 | if (dev->msi_enabled) | ||
140 | aac_src_access_devreg(dev, AAC_CLEAR_AIF_BIT); | ||
141 | mode = 0; | ||
137 | } | 142 | } |
138 | return IRQ_NONE; | 143 | |
144 | if (mode) { | ||
145 | index = dev->host_rrq_idx[vector_no]; | ||
146 | |||
147 | for (;;) { | ||
148 | isFastResponse = 0; | ||
149 | /* remove toggle bit (31) */ | ||
150 | handle = (dev->host_rrq[index] & 0x7fffffff); | ||
151 | /* check fast response bit (30) */ | ||
152 | if (handle & 0x40000000) | ||
153 | isFastResponse = 1; | ||
154 | handle &= 0x0000ffff; | ||
155 | if (handle == 0) | ||
156 | break; | ||
157 | if (dev->msi_enabled && dev->max_msix > 1) | ||
158 | atomic_dec(&dev->rrq_outstanding[vector_no]); | ||
159 | aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL); | ||
160 | dev->host_rrq[index++] = 0; | ||
161 | if (index == (vector_no + 1) * dev->vector_cap) | ||
162 | index = vector_no * dev->vector_cap; | ||
163 | dev->host_rrq_idx[vector_no] = index; | ||
164 | } | ||
165 | mode = 0; | ||
166 | } | ||
167 | |||
168 | return IRQ_HANDLED; | ||
139 | } | 169 | } |
140 | 170 | ||
141 | /** | 171 | /** |
@@ -155,7 +185,7 @@ static void aac_src_disable_interrupt(struct aac_dev *dev) | |||
155 | 185 | ||
156 | static void aac_src_enable_interrupt_message(struct aac_dev *dev) | 186 | static void aac_src_enable_interrupt_message(struct aac_dev *dev) |
157 | { | 187 | { |
158 | src_writel(dev, MUnit.OIMR, dev->OIMR = 0xfffffff8); | 188 | aac_src_access_devreg(dev, AAC_ENABLE_INTERRUPT); |
159 | } | 189 | } |
160 | 190 | ||
161 | /** | 191 | /** |
@@ -191,7 +221,10 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command, | |||
191 | /* | 221 | /* |
192 | * Clear the synch command doorbell to start on a clean slate. | 222 | * Clear the synch command doorbell to start on a clean slate. |
193 | */ | 223 | */ |
194 | src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | 224 | if (!dev->msi_enabled) |
225 | src_writel(dev, | ||
226 | MUnit.ODR_C, | ||
227 | OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | ||
195 | 228 | ||
196 | /* | 229 | /* |
197 | * Disable doorbell interrupts | 230 | * Disable doorbell interrupts |
@@ -221,11 +254,17 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command, | |||
221 | /* | 254 | /* |
222 | * Mon960 will set doorbell0 bit when it has completed the command. | 255 | * Mon960 will set doorbell0 bit when it has completed the command. |
223 | */ | 256 | */ |
224 | if ((src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT) & OUTBOUNDDOORBELL_0) { | 257 | if (aac_src_get_sync_status(dev) & OUTBOUNDDOORBELL_0) { |
225 | /* | 258 | /* |
226 | * Clear the doorbell. | 259 | * Clear the doorbell. |
227 | */ | 260 | */ |
228 | src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | 261 | if (dev->msi_enabled) |
262 | aac_src_access_devreg(dev, | ||
263 | AAC_CLEAR_SYNC_BIT); | ||
264 | else | ||
265 | src_writel(dev, | ||
266 | MUnit.ODR_C, | ||
267 | OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | ||
229 | ok = 1; | 268 | ok = 1; |
230 | break; | 269 | break; |
231 | } | 270 | } |
@@ -254,11 +293,16 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command, | |||
254 | *r3 = readl(&dev->IndexRegs->Mailbox[3]); | 293 | *r3 = readl(&dev->IndexRegs->Mailbox[3]); |
255 | if (r4) | 294 | if (r4) |
256 | *r4 = readl(&dev->IndexRegs->Mailbox[4]); | 295 | *r4 = readl(&dev->IndexRegs->Mailbox[4]); |
257 | 296 | if (command == GET_COMM_PREFERRED_SETTINGS) | |
297 | dev->max_msix = | ||
298 | readl(&dev->IndexRegs->Mailbox[5]) & 0xFFFF; | ||
258 | /* | 299 | /* |
259 | * Clear the synch command doorbell. | 300 | * Clear the synch command doorbell. |
260 | */ | 301 | */ |
261 | src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | 302 | if (!dev->msi_enabled) |
303 | src_writel(dev, | ||
304 | MUnit.ODR_C, | ||
305 | OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | ||
262 | } | 306 | } |
263 | 307 | ||
264 | /* | 308 | /* |
@@ -335,9 +379,14 @@ static void aac_src_notify_adapter(struct aac_dev *dev, u32 event) | |||
335 | static void aac_src_start_adapter(struct aac_dev *dev) | 379 | static void aac_src_start_adapter(struct aac_dev *dev) |
336 | { | 380 | { |
337 | struct aac_init *init; | 381 | struct aac_init *init; |
382 | int i; | ||
338 | 383 | ||
339 | /* reset host_rrq_idx first */ | 384 | /* reset host_rrq_idx first */ |
340 | dev->host_rrq_idx = 0; | 385 | for (i = 0; i < dev->max_msix; i++) { |
386 | dev->host_rrq_idx[i] = i * dev->vector_cap; | ||
387 | atomic_set(&dev->rrq_outstanding[i], 0); | ||
388 | } | ||
389 | dev->fibs_pushed_no = 0; | ||
341 | 390 | ||
342 | init = dev->init; | 391 | init = dev->init; |
343 | init->HostElapsedSeconds = cpu_to_le32(get_seconds()); | 392 | init->HostElapsedSeconds = cpu_to_le32(get_seconds()); |
@@ -400,6 +449,33 @@ static int aac_src_deliver_message(struct fib *fib) | |||
400 | q->numpending++; | 449 | q->numpending++; |
401 | spin_unlock_irqrestore(q->lock, qflags); | 450 | spin_unlock_irqrestore(q->lock, qflags); |
402 | 451 | ||
452 | if (dev->msi_enabled && fib->hw_fib_va->header.Command != AifRequest && | ||
453 | dev->max_msix > 1) { | ||
454 | u_int16_t vector_no, first_choice = 0xffff; | ||
455 | |||
456 | vector_no = dev->fibs_pushed_no % dev->max_msix; | ||
457 | do { | ||
458 | vector_no += 1; | ||
459 | if (vector_no == dev->max_msix) | ||
460 | vector_no = 1; | ||
461 | if (atomic_read(&dev->rrq_outstanding[vector_no]) < | ||
462 | dev->vector_cap) | ||
463 | break; | ||
464 | if (0xffff == first_choice) | ||
465 | first_choice = vector_no; | ||
466 | else if (vector_no == first_choice) | ||
467 | break; | ||
468 | } while (1); | ||
469 | if (vector_no == first_choice) | ||
470 | vector_no = 0; | ||
471 | atomic_inc(&dev->rrq_outstanding[vector_no]); | ||
472 | if (dev->fibs_pushed_no == 0xffffffff) | ||
473 | dev->fibs_pushed_no = 0; | ||
474 | else | ||
475 | dev->fibs_pushed_no++; | ||
476 | fib->hw_fib_va->header.Handle += (vector_no << 16); | ||
477 | } | ||
478 | |||
403 | if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) { | 479 | if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) { |
404 | /* Calculate the amount to the fibsize bits */ | 480 | /* Calculate the amount to the fibsize bits */ |
405 | fibsize = (hdr_size + 127) / 128 - 1; | 481 | fibsize = (hdr_size + 127) / 128 - 1; |
@@ -502,10 +578,19 @@ static int aac_src_restart_adapter(struct aac_dev *dev, int bled) | |||
502 | 0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL); | 578 | 0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL); |
503 | if (bled || (var != 0x00000001)) | 579 | if (bled || (var != 0x00000001)) |
504 | return -EINVAL; | 580 | return -EINVAL; |
581 | |||
582 | if ((dev->pdev->device == PMC_DEVICE_S7 || | ||
583 | dev->pdev->device == PMC_DEVICE_S8 || | ||
584 | dev->pdev->device == PMC_DEVICE_S9) && dev->msi_enabled) { | ||
585 | aac_src_access_devreg(dev, AAC_ENABLE_INTX); | ||
586 | dev->msi_enabled = 0; | ||
587 | msleep(5000); /* Delay 5 seconds */ | ||
588 | } | ||
589 | |||
505 | if (dev->supplement_adapter_info.SupportedOptions2 & | 590 | if (dev->supplement_adapter_info.SupportedOptions2 & |
506 | AAC_OPTION_DOORBELL_RESET) { | 591 | AAC_OPTION_DOORBELL_RESET) { |
507 | src_writel(dev, MUnit.IDR, reset_mask); | 592 | src_writel(dev, MUnit.IDR, reset_mask); |
508 | msleep(5000); /* Delay 5 seconds */ | 593 | ssleep(45); |
509 | } | 594 | } |
510 | } | 595 | } |
511 | 596 | ||
@@ -646,8 +731,11 @@ int aac_src_init(struct aac_dev *dev) | |||
646 | 731 | ||
647 | dev->msi = aac_msi && !pci_enable_msi(dev->pdev); | 732 | dev->msi = aac_msi && !pci_enable_msi(dev->pdev); |
648 | 733 | ||
734 | dev->aac_msix[0].vector_no = 0; | ||
735 | dev->aac_msix[0].dev = dev; | ||
736 | |||
649 | if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, | 737 | if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, |
650 | IRQF_SHARED, "aacraid", dev) < 0) { | 738 | IRQF_SHARED, "aacraid", &(dev->aac_msix[0])) < 0) { |
651 | 739 | ||
652 | if (dev->msi) | 740 | if (dev->msi) |
653 | pci_disable_msi(dev->pdev); | 741 | pci_disable_msi(dev->pdev); |
@@ -688,6 +776,7 @@ int aac_srcv_init(struct aac_dev *dev) | |||
688 | unsigned long status; | 776 | unsigned long status; |
689 | int restart = 0; | 777 | int restart = 0; |
690 | int instance = dev->id; | 778 | int instance = dev->id; |
779 | int i, j; | ||
691 | const char *name = dev->name; | 780 | const char *name = dev->name; |
692 | 781 | ||
693 | dev->a_ops.adapter_ioremap = aac_srcv_ioremap; | 782 | dev->a_ops.adapter_ioremap = aac_srcv_ioremap; |
@@ -802,14 +891,41 @@ int aac_srcv_init(struct aac_dev *dev) | |||
802 | goto error_iounmap; | 891 | goto error_iounmap; |
803 | if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE2) | 892 | if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE2) |
804 | goto error_iounmap; | 893 | goto error_iounmap; |
805 | dev->msi = aac_msi && !pci_enable_msi(dev->pdev); | 894 | if (dev->msi_enabled) |
806 | if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, | 895 | aac_src_access_devreg(dev, AAC_ENABLE_MSIX); |
807 | IRQF_SHARED, "aacraid", dev) < 0) { | 896 | if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) { |
808 | if (dev->msi) | 897 | for (i = 0; i < dev->max_msix; i++) { |
809 | pci_disable_msi(dev->pdev); | 898 | dev->aac_msix[i].vector_no = i; |
810 | printk(KERN_ERR "%s%d: Interrupt unavailable.\n", | 899 | dev->aac_msix[i].dev = dev; |
811 | name, instance); | 900 | |
812 | goto error_iounmap; | 901 | if (request_irq(dev->msixentry[i].vector, |
902 | dev->a_ops.adapter_intr, | ||
903 | 0, | ||
904 | "aacraid", | ||
905 | &(dev->aac_msix[i]))) { | ||
906 | printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n", | ||
907 | name, instance, i); | ||
908 | for (j = 0 ; j < i ; j++) | ||
909 | free_irq(dev->msixentry[j].vector, | ||
910 | &(dev->aac_msix[j])); | ||
911 | pci_disable_msix(dev->pdev); | ||
912 | goto error_iounmap; | ||
913 | } | ||
914 | } | ||
915 | } else { | ||
916 | dev->aac_msix[0].vector_no = 0; | ||
917 | dev->aac_msix[0].dev = dev; | ||
918 | |||
919 | if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, | ||
920 | IRQF_SHARED, | ||
921 | "aacraid", | ||
922 | &(dev->aac_msix[0])) < 0) { | ||
923 | if (dev->msi) | ||
924 | pci_disable_msi(dev->pdev); | ||
925 | printk(KERN_ERR "%s%d: Interrupt unavailable.\n", | ||
926 | name, instance); | ||
927 | goto error_iounmap; | ||
928 | } | ||
813 | } | 929 | } |
814 | dev->dbg_base = dev->base_start; | 930 | dev->dbg_base = dev->base_start; |
815 | dev->dbg_base_mapped = dev->base; | 931 | dev->dbg_base_mapped = dev->base; |
@@ -831,3 +947,93 @@ error_iounmap: | |||
831 | return -1; | 947 | return -1; |
832 | } | 948 | } |
833 | 949 | ||
950 | void aac_src_access_devreg(struct aac_dev *dev, int mode) | ||
951 | { | ||
952 | u_int32_t val; | ||
953 | |||
954 | switch (mode) { | ||
955 | case AAC_ENABLE_INTERRUPT: | ||
956 | src_writel(dev, | ||
957 | MUnit.OIMR, | ||
958 | dev->OIMR = (dev->msi_enabled ? | ||
959 | AAC_INT_ENABLE_TYPE1_MSIX : | ||
960 | AAC_INT_ENABLE_TYPE1_INTX)); | ||
961 | break; | ||
962 | |||
963 | case AAC_DISABLE_INTERRUPT: | ||
964 | src_writel(dev, | ||
965 | MUnit.OIMR, | ||
966 | dev->OIMR = AAC_INT_DISABLE_ALL); | ||
967 | break; | ||
968 | |||
969 | case AAC_ENABLE_MSIX: | ||
970 | /* set bit 6 */ | ||
971 | val = src_readl(dev, MUnit.IDR); | ||
972 | val |= 0x40; | ||
973 | src_writel(dev, MUnit.IDR, val); | ||
974 | src_readl(dev, MUnit.IDR); | ||
975 | /* unmask int. */ | ||
976 | val = PMC_ALL_INTERRUPT_BITS; | ||
977 | src_writel(dev, MUnit.IOAR, val); | ||
978 | val = src_readl(dev, MUnit.OIMR); | ||
979 | src_writel(dev, | ||
980 | MUnit.OIMR, | ||
981 | val & (~(PMC_GLOBAL_INT_BIT2 | PMC_GLOBAL_INT_BIT0))); | ||
982 | break; | ||
983 | |||
984 | case AAC_DISABLE_MSIX: | ||
985 | /* reset bit 6 */ | ||
986 | val = src_readl(dev, MUnit.IDR); | ||
987 | val &= ~0x40; | ||
988 | src_writel(dev, MUnit.IDR, val); | ||
989 | src_readl(dev, MUnit.IDR); | ||
990 | break; | ||
991 | |||
992 | case AAC_CLEAR_AIF_BIT: | ||
993 | /* set bit 5 */ | ||
994 | val = src_readl(dev, MUnit.IDR); | ||
995 | val |= 0x20; | ||
996 | src_writel(dev, MUnit.IDR, val); | ||
997 | src_readl(dev, MUnit.IDR); | ||
998 | break; | ||
999 | |||
1000 | case AAC_CLEAR_SYNC_BIT: | ||
1001 | /* set bit 4 */ | ||
1002 | val = src_readl(dev, MUnit.IDR); | ||
1003 | val |= 0x10; | ||
1004 | src_writel(dev, MUnit.IDR, val); | ||
1005 | src_readl(dev, MUnit.IDR); | ||
1006 | break; | ||
1007 | |||
1008 | case AAC_ENABLE_INTX: | ||
1009 | /* set bit 7 */ | ||
1010 | val = src_readl(dev, MUnit.IDR); | ||
1011 | val |= 0x80; | ||
1012 | src_writel(dev, MUnit.IDR, val); | ||
1013 | src_readl(dev, MUnit.IDR); | ||
1014 | /* unmask int. */ | ||
1015 | val = PMC_ALL_INTERRUPT_BITS; | ||
1016 | src_writel(dev, MUnit.IOAR, val); | ||
1017 | src_readl(dev, MUnit.IOAR); | ||
1018 | val = src_readl(dev, MUnit.OIMR); | ||
1019 | src_writel(dev, MUnit.OIMR, | ||
1020 | val & (~(PMC_GLOBAL_INT_BIT2))); | ||
1021 | break; | ||
1022 | |||
1023 | default: | ||
1024 | break; | ||
1025 | } | ||
1026 | } | ||
1027 | |||
1028 | static int aac_src_get_sync_status(struct aac_dev *dev) | ||
1029 | { | ||
1030 | |||
1031 | int val; | ||
1032 | |||
1033 | if (dev->msi_enabled) | ||
1034 | val = src_readl(dev, MUnit.ODR_MSI) & 0x1000 ? 1 : 0; | ||
1035 | else | ||
1036 | val = src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT; | ||
1037 | |||
1038 | return val; | ||
1039 | } | ||