diff options
author | Mahesh Rajashekhara <Mahesh_Rajashekhara@pmc-sierra.com> | 2011-03-17 05:10:32 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2011-03-23 12:36:58 -0400 |
commit | e8b12f0fb8352237525961f14ec933e915848840 (patch) | |
tree | cdbf1209bdb6dc300434a6608e5ac73d536e47c0 /drivers/scsi | |
parent | 0a2385cea9a715e11df10fce1f1442d933008a40 (diff) |
[SCSI] aacraid: Add new code for PMC-Sierra's SRC based controller family
Added new hardware device 0x28b interface for PMC-Sierra's SRC based
controller family.
- new src.c file for 0x28b specific functions
- new XPORT header required
- sync. command interface: doorbell bits shifted (SRC_ODR_SHIFT, SRC_IDR_SHIFT)
- async. Interface: different inbound queue handling, no outbound I2O
queue available, using doorbell ("PmDoorBellResponseSent") and
response buffer on the host ("host_rrq") for status
- changed AIF (adapter initiated FIBs) interface: "DoorBellAifPending"
bit to inform about pending AIF, "AifRequest" command to read AIF,
"NoMoreAifDataAvailable" to mark the end of the AIFs
Signed-off-by: Mahesh Rajashekhara <aacraid@pmc-sierra.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/aacraid/Makefile | 2 | ||||
-rw-r--r-- | drivers/scsi/aacraid/aachba.c | 7 | ||||
-rw-r--r-- | drivers/scsi/aacraid/aacraid.h | 106 | ||||
-rw-r--r-- | drivers/scsi/aacraid/commctrl.c | 3 | ||||
-rw-r--r-- | drivers/scsi/aacraid/comminit.c | 58 | ||||
-rw-r--r-- | drivers/scsi/aacraid/commsup.c | 41 | ||||
-rw-r--r-- | drivers/scsi/aacraid/dpcsup.c | 85 | ||||
-rw-r--r-- | drivers/scsi/aacraid/linit.c | 15 | ||||
-rw-r--r-- | drivers/scsi/aacraid/nark.c | 3 | ||||
-rw-r--r-- | drivers/scsi/aacraid/rkt.c | 3 | ||||
-rw-r--r-- | drivers/scsi/aacraid/rx.c | 33 | ||||
-rw-r--r-- | drivers/scsi/aacraid/sa.c | 7 | ||||
-rw-r--r-- | drivers/scsi/aacraid/src.c | 594 |
13 files changed, 898 insertions, 59 deletions
diff --git a/drivers/scsi/aacraid/Makefile b/drivers/scsi/aacraid/Makefile index 92df4d6b6147..1bd9fd18f7f3 100644 --- a/drivers/scsi/aacraid/Makefile +++ b/drivers/scsi/aacraid/Makefile | |||
@@ -3,6 +3,6 @@ | |||
3 | obj-$(CONFIG_SCSI_AACRAID) := aacraid.o | 3 | obj-$(CONFIG_SCSI_AACRAID) := aacraid.o |
4 | 4 | ||
5 | aacraid-objs := linit.o aachba.o commctrl.o comminit.o commsup.o \ | 5 | aacraid-objs := linit.o aachba.o commctrl.o comminit.o commsup.o \ |
6 | dpcsup.o rx.o sa.o rkt.o nark.o | 6 | dpcsup.o rx.o sa.o rkt.o nark.o src.o |
7 | 7 | ||
8 | ccflags-y := -Idrivers/scsi | 8 | ccflags-y := -Idrivers/scsi |
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 7df2dd1d2c6f..118ce83a737c 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
@@ -5,7 +5,8 @@ | |||
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-2007 Adaptec, Inc. (aacraid@adaptec.com) | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
9 | * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | ||
9 | * | 10 | * |
10 | * This program is free software; you can redistribute it and/or modify | 11 | * 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 | 12 | * it under the terms of the GNU General Public License as published by |
@@ -1486,7 +1487,9 @@ int aac_get_adapter_info(struct aac_dev* dev) | |||
1486 | dev->a_ops.adapter_write = aac_write_block; | 1487 | dev->a_ops.adapter_write = aac_write_block; |
1487 | } | 1488 | } |
1488 | dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT; | 1489 | dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT; |
1489 | if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) { | 1490 | if (dev->adapter_info.options & AAC_OPT_NEW_COMM_TYPE1) |
1491 | dev->adapter_info.options |= AAC_OPT_NEW_COMM; | ||
1492 | if (!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) { | ||
1490 | /* | 1493 | /* |
1491 | * Worst case size that could cause sg overflow when | 1494 | * Worst case size that could cause sg overflow when |
1492 | * we break up SG elements that are larger than 64KB. | 1495 | * we break up SG elements that are larger than 64KB. |
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 4dbcc055ac78..29ab00016b78 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 26400 | 15 | # define AAC_DRIVER_BUILD 28000 |
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 |
@@ -277,6 +277,16 @@ enum aac_queue_types { | |||
277 | 277 | ||
278 | #define FsaNormal 1 | 278 | #define FsaNormal 1 |
279 | 279 | ||
280 | /* transport FIB header (PMC) */ | ||
281 | struct aac_fib_xporthdr { | ||
282 | u64 HostAddress; /* FIB host address w/o xport header */ | ||
283 | u32 Size; /* FIB size excluding xport header */ | ||
284 | u32 Handle; /* driver handle to reference the FIB */ | ||
285 | u64 Reserved[2]; | ||
286 | }; | ||
287 | |||
288 | #define ALIGN32 32 | ||
289 | |||
280 | /* | 290 | /* |
281 | * Define the FIB. The FIB is the where all the requested data and | 291 | * Define the FIB. The FIB is the where all the requested data and |
282 | * command information are put to the application on the FSA adapter. | 292 | * command information are put to the application on the FSA adapter. |
@@ -394,7 +404,9 @@ enum fib_xfer_state { | |||
394 | AdapterMicroFib = (1<<17), | 404 | AdapterMicroFib = (1<<17), |
395 | BIOSFibPath = (1<<18), | 405 | BIOSFibPath = (1<<18), |
396 | FastResponseCapable = (1<<19), | 406 | FastResponseCapable = (1<<19), |
397 | ApiFib = (1<<20) // Its an API Fib. | 407 | ApiFib = (1<<20), /* Its an API Fib */ |
408 | /* PMC NEW COMM: There is no more AIF data pending */ | ||
409 | NoMoreAifDataAvailable = (1<<21) | ||
398 | }; | 410 | }; |
399 | 411 | ||
400 | /* | 412 | /* |
@@ -404,6 +416,7 @@ enum fib_xfer_state { | |||
404 | 416 | ||
405 | #define ADAPTER_INIT_STRUCT_REVISION 3 | 417 | #define ADAPTER_INIT_STRUCT_REVISION 3 |
406 | #define ADAPTER_INIT_STRUCT_REVISION_4 4 // rocket science | 418 | #define ADAPTER_INIT_STRUCT_REVISION_4 4 // rocket science |
419 | #define ADAPTER_INIT_STRUCT_REVISION_6 6 /* PMC src */ | ||
407 | 420 | ||
408 | struct aac_init | 421 | struct aac_init |
409 | { | 422 | { |
@@ -428,9 +441,15 @@ struct aac_init | |||
428 | #define INITFLAGS_NEW_COMM_SUPPORTED 0x00000001 | 441 | #define INITFLAGS_NEW_COMM_SUPPORTED 0x00000001 |
429 | #define INITFLAGS_DRIVER_USES_UTC_TIME 0x00000010 | 442 | #define INITFLAGS_DRIVER_USES_UTC_TIME 0x00000010 |
430 | #define INITFLAGS_DRIVER_SUPPORTS_PM 0x00000020 | 443 | #define INITFLAGS_DRIVER_SUPPORTS_PM 0x00000020 |
444 | #define INITFLAGS_NEW_COMM_TYPE1_SUPPORTED 0x00000041 | ||
431 | __le32 MaxIoCommands; /* max outstanding commands */ | 445 | __le32 MaxIoCommands; /* max outstanding commands */ |
432 | __le32 MaxIoSize; /* largest I/O command */ | 446 | __le32 MaxIoSize; /* largest I/O command */ |
433 | __le32 MaxFibSize; /* largest FIB to adapter */ | 447 | __le32 MaxFibSize; /* largest FIB to adapter */ |
448 | /* ADAPTER_INIT_STRUCT_REVISION_5 begins here */ | ||
449 | __le32 MaxNumAif; /* max number of aif */ | ||
450 | /* ADAPTER_INIT_STRUCT_REVISION_6 begins here */ | ||
451 | __le32 HostRRQ_AddrLow; | ||
452 | __le32 HostRRQ_AddrHigh; /* Host RRQ (response queue) for SRC */ | ||
434 | }; | 453 | }; |
435 | 454 | ||
436 | enum aac_log_level { | 455 | enum aac_log_level { |
@@ -685,7 +704,7 @@ struct rx_inbound { | |||
685 | #define OutboundDoorbellReg MUnit.ODR | 704 | #define OutboundDoorbellReg MUnit.ODR |
686 | 705 | ||
687 | struct rx_registers { | 706 | struct rx_registers { |
688 | struct rx_mu_registers MUnit; /* 1300h - 1344h */ | 707 | struct rx_mu_registers MUnit; /* 1300h - 1347h */ |
689 | __le32 reserved1[2]; /* 1348h - 134ch */ | 708 | __le32 reserved1[2]; /* 1348h - 134ch */ |
690 | struct rx_inbound IndexRegs; | 709 | struct rx_inbound IndexRegs; |
691 | }; | 710 | }; |
@@ -703,7 +722,7 @@ struct rx_registers { | |||
703 | #define rkt_inbound rx_inbound | 722 | #define rkt_inbound rx_inbound |
704 | 723 | ||
705 | struct rkt_registers { | 724 | struct rkt_registers { |
706 | struct rkt_mu_registers MUnit; /* 1300h - 1344h */ | 725 | struct rkt_mu_registers MUnit; /* 1300h - 1347h */ |
707 | __le32 reserved1[1006]; /* 1348h - 22fch */ | 726 | __le32 reserved1[1006]; /* 1348h - 22fch */ |
708 | struct rkt_inbound IndexRegs; /* 2300h - */ | 727 | struct rkt_inbound IndexRegs; /* 2300h - */ |
709 | }; | 728 | }; |
@@ -713,6 +732,44 @@ struct rkt_registers { | |||
713 | #define rkt_writeb(AEP, CSR, value) writeb(value, &((AEP)->regs.rkt->CSR)) | 732 | #define rkt_writeb(AEP, CSR, value) writeb(value, &((AEP)->regs.rkt->CSR)) |
714 | #define rkt_writel(AEP, CSR, value) writel(value, &((AEP)->regs.rkt->CSR)) | 733 | #define rkt_writel(AEP, CSR, value) writel(value, &((AEP)->regs.rkt->CSR)) |
715 | 734 | ||
735 | /* | ||
736 | * PMC SRC message unit registers | ||
737 | */ | ||
738 | |||
739 | #define src_inbound rx_inbound | ||
740 | |||
741 | struct src_mu_registers { | ||
742 | /* PCI*| Name */ | ||
743 | __le32 reserved0[8]; /* 00h | Reserved */ | ||
744 | __le32 IDR; /* 20h | Inbound Doorbell Register */ | ||
745 | __le32 IISR; /* 24h | Inbound Int. Status Register */ | ||
746 | __le32 reserved1[3]; /* 28h | Reserved */ | ||
747 | __le32 OIMR; /* 34h | Outbound Int. Mask Register */ | ||
748 | __le32 reserved2[25]; /* 38h | Reserved */ | ||
749 | __le32 ODR_R; /* 9ch | Outbound Doorbell Read */ | ||
750 | __le32 ODR_C; /* a0h | Outbound Doorbell Clear */ | ||
751 | __le32 reserved3[6]; /* a4h | Reserved */ | ||
752 | __le32 OMR; /* bch | Outbound Message Register */ | ||
753 | __le32 IQ_L; /* c0h | Inbound Queue (Low address) */ | ||
754 | __le32 IQ_H; /* c4h | Inbound Queue (High address) */ | ||
755 | }; | ||
756 | |||
757 | struct src_registers { | ||
758 | struct src_mu_registers MUnit; /* 00h - c7h */ | ||
759 | __le32 reserved1[130790]; /* c8h - 7fc5fh */ | ||
760 | struct src_inbound IndexRegs; /* 7fc60h */ | ||
761 | }; | ||
762 | |||
763 | #define src_readb(AEP, CSR) readb(&((AEP)->regs.src.bar0->CSR)) | ||
764 | #define src_readl(AEP, CSR) readl(&((AEP)->regs.src.bar0->CSR)) | ||
765 | #define src_writeb(AEP, CSR, value) writeb(value, \ | ||
766 | &((AEP)->regs.src.bar0->CSR)) | ||
767 | #define src_writel(AEP, CSR, value) writel(value, \ | ||
768 | &((AEP)->regs.src.bar0->CSR)) | ||
769 | |||
770 | #define SRC_ODR_SHIFT 12 | ||
771 | #define SRC_IDR_SHIFT 9 | ||
772 | |||
716 | typedef void (*fib_callback)(void *ctxt, struct fib *fibctx); | 773 | typedef void (*fib_callback)(void *ctxt, struct fib *fibctx); |
717 | 774 | ||
718 | struct aac_fib_context { | 775 | struct aac_fib_context { |
@@ -879,6 +936,7 @@ struct aac_supplement_adapter_info | |||
879 | #define AAC_OPTION_MU_RESET cpu_to_le32(0x00000001) | 936 | #define AAC_OPTION_MU_RESET cpu_to_le32(0x00000001) |
880 | #define AAC_OPTION_IGNORE_RESET cpu_to_le32(0x00000002) | 937 | #define AAC_OPTION_IGNORE_RESET cpu_to_le32(0x00000002) |
881 | #define AAC_OPTION_POWER_MANAGEMENT cpu_to_le32(0x00000004) | 938 | #define AAC_OPTION_POWER_MANAGEMENT cpu_to_le32(0x00000004) |
939 | #define AAC_OPTION_DOORBELL_RESET cpu_to_le32(0x00004000) | ||
882 | #define AAC_SIS_VERSION_V3 3 | 940 | #define AAC_SIS_VERSION_V3 3 |
883 | #define AAC_SIS_SLOT_UNKNOWN 0xFF | 941 | #define AAC_SIS_SLOT_UNKNOWN 0xFF |
884 | 942 | ||
@@ -940,6 +998,7 @@ struct aac_bus_info_response { | |||
940 | #define AAC_OPT_SUPPLEMENT_ADAPTER_INFO cpu_to_le32(1<<16) | 998 | #define AAC_OPT_SUPPLEMENT_ADAPTER_INFO cpu_to_le32(1<<16) |
941 | #define AAC_OPT_NEW_COMM cpu_to_le32(1<<17) | 999 | #define AAC_OPT_NEW_COMM cpu_to_le32(1<<17) |
942 | #define AAC_OPT_NEW_COMM_64 cpu_to_le32(1<<18) | 1000 | #define AAC_OPT_NEW_COMM_64 cpu_to_le32(1<<18) |
1001 | #define AAC_OPT_NEW_COMM_TYPE1 cpu_to_le32(1<<28) | ||
943 | 1002 | ||
944 | struct aac_dev | 1003 | struct aac_dev |
945 | { | 1004 | { |
@@ -952,6 +1011,7 @@ struct aac_dev | |||
952 | */ | 1011 | */ |
953 | unsigned max_fib_size; | 1012 | unsigned max_fib_size; |
954 | unsigned sg_tablesize; | 1013 | unsigned sg_tablesize; |
1014 | unsigned max_num_aif; | ||
955 | 1015 | ||
956 | /* | 1016 | /* |
957 | * Map for 128 fib objects (64k) | 1017 | * Map for 128 fib objects (64k) |
@@ -980,10 +1040,21 @@ struct aac_dev | |||
980 | struct adapter_ops a_ops; | 1040 | struct adapter_ops a_ops; |
981 | unsigned long fsrev; /* Main driver's revision number */ | 1041 | unsigned long fsrev; /* Main driver's revision number */ |
982 | 1042 | ||
983 | unsigned base_size; /* Size of mapped in region */ | 1043 | unsigned long dbg_base; /* address of UART |
1044 | * debug buffer */ | ||
1045 | |||
1046 | unsigned base_size, dbg_size; /* Size of | ||
1047 | * mapped in region */ | ||
1048 | |||
984 | struct aac_init *init; /* Holds initialization info to communicate with adapter */ | 1049 | struct aac_init *init; /* Holds initialization info to communicate with adapter */ |
985 | dma_addr_t init_pa; /* Holds physical address of the init struct */ | 1050 | dma_addr_t init_pa; /* Holds physical address of the init struct */ |
986 | 1051 | ||
1052 | u32 *host_rrq; /* response queue | ||
1053 | * if AAC_COMM_MESSAGE_TYPE1 */ | ||
1054 | |||
1055 | dma_addr_t host_rrq_pa; /* phys. address */ | ||
1056 | u32 host_rrq_idx; /* index into rrq buffer */ | ||
1057 | |||
987 | struct pci_dev *pdev; /* Our PCI interface */ | 1058 | struct pci_dev *pdev; /* Our PCI interface */ |
988 | void * printfbuf; /* pointer to buffer used for printf's from the adapter */ | 1059 | void * printfbuf; /* pointer to buffer used for printf's from the adapter */ |
989 | void * comm_addr; /* Base address of Comm area */ | 1060 | void * comm_addr; /* Base address of Comm area */ |
@@ -1003,14 +1074,20 @@ struct aac_dev | |||
1003 | */ | 1074 | */ |
1004 | #ifndef AAC_MIN_FOOTPRINT_SIZE | 1075 | #ifndef AAC_MIN_FOOTPRINT_SIZE |
1005 | # define AAC_MIN_FOOTPRINT_SIZE 8192 | 1076 | # define AAC_MIN_FOOTPRINT_SIZE 8192 |
1077 | # define AAC_MIN_SRC_BAR0_SIZE 0x400000 | ||
1078 | # define AAC_MIN_SRC_BAR1_SIZE 0x800 | ||
1006 | #endif | 1079 | #endif |
1007 | union | 1080 | union |
1008 | { | 1081 | { |
1009 | struct sa_registers __iomem *sa; | 1082 | struct sa_registers __iomem *sa; |
1010 | struct rx_registers __iomem *rx; | 1083 | struct rx_registers __iomem *rx; |
1011 | struct rkt_registers __iomem *rkt; | 1084 | struct rkt_registers __iomem *rkt; |
1085 | struct { | ||
1086 | struct src_registers __iomem *bar0; | ||
1087 | char __iomem *bar1; | ||
1088 | } src; | ||
1012 | } regs; | 1089 | } regs; |
1013 | volatile void __iomem *base; | 1090 | volatile void __iomem *base, *dbg_base_mapped; |
1014 | volatile struct rx_inbound __iomem *IndexRegs; | 1091 | volatile struct rx_inbound __iomem *IndexRegs; |
1015 | u32 OIMR; /* Mask Register Cache */ | 1092 | u32 OIMR; /* Mask Register Cache */ |
1016 | /* | 1093 | /* |
@@ -1031,9 +1108,8 @@ struct aac_dev | |||
1031 | u8 comm_interface; | 1108 | u8 comm_interface; |
1032 | # define AAC_COMM_PRODUCER 0 | 1109 | # define AAC_COMM_PRODUCER 0 |
1033 | # define AAC_COMM_MESSAGE 1 | 1110 | # define AAC_COMM_MESSAGE 1 |
1034 | /* macro side-effects BEWARE */ | 1111 | # define AAC_COMM_MESSAGE_TYPE1 3 |
1035 | # define raw_io_interface \ | 1112 | u8 raw_io_interface; |
1036 | init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4) | ||
1037 | u8 raw_io_64; | 1113 | u8 raw_io_64; |
1038 | u8 printf_enabled; | 1114 | u8 printf_enabled; |
1039 | u8 in_reset; | 1115 | u8 in_reset; |
@@ -1789,6 +1865,10 @@ extern struct aac_common aac_config; | |||
1789 | #define DoorBellAdapterNormCmdNotFull (1<<3) /* Adapter -> Host */ | 1865 | #define DoorBellAdapterNormCmdNotFull (1<<3) /* Adapter -> Host */ |
1790 | #define DoorBellAdapterNormRespNotFull (1<<4) /* Adapter -> Host */ | 1866 | #define DoorBellAdapterNormRespNotFull (1<<4) /* Adapter -> Host */ |
1791 | #define DoorBellPrintfReady (1<<5) /* Adapter -> Host */ | 1867 | #define DoorBellPrintfReady (1<<5) /* Adapter -> Host */ |
1868 | #define DoorBellAifPending (1<<6) /* Adapter -> Host */ | ||
1869 | |||
1870 | /* PMC specific outbound doorbell bits */ | ||
1871 | #define PmDoorBellResponseSent (1<<1) /* Adapter -> Host */ | ||
1792 | 1872 | ||
1793 | /* | 1873 | /* |
1794 | * For FIB communication, we need all of the following things | 1874 | * For FIB communication, we need all of the following things |
@@ -1831,6 +1911,9 @@ extern struct aac_common aac_config; | |||
1831 | #define AifReqAPIJobUpdate 109 /* Update a job report from the API */ | 1911 | #define AifReqAPIJobUpdate 109 /* Update a job report from the API */ |
1832 | #define AifReqAPIJobFinish 110 /* Finish a job from the API */ | 1912 | #define AifReqAPIJobFinish 110 /* Finish a job from the API */ |
1833 | 1913 | ||
1914 | /* PMC NEW COMM: Request the event data */ | ||
1915 | #define AifReqEvent 200 | ||
1916 | |||
1834 | /* | 1917 | /* |
1835 | * Adapter Initiated FIB command structures. Start with the adapter | 1918 | * Adapter Initiated FIB command structures. Start with the adapter |
1836 | * initiated FIBs that really come from the adapter, and get responded | 1919 | * initiated FIBs that really come from the adapter, and get responded |
@@ -1886,10 +1969,13 @@ int aac_rx_init(struct aac_dev *dev); | |||
1886 | int aac_rkt_init(struct aac_dev *dev); | 1969 | int aac_rkt_init(struct aac_dev *dev); |
1887 | int aac_nark_init(struct aac_dev *dev); | 1970 | int aac_nark_init(struct aac_dev *dev); |
1888 | int aac_sa_init(struct aac_dev *dev); | 1971 | int aac_sa_init(struct aac_dev *dev); |
1972 | int aac_src_init(struct aac_dev *dev); | ||
1889 | 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); | 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); |
1890 | unsigned int aac_response_normal(struct aac_queue * q); | 1974 | unsigned int aac_response_normal(struct aac_queue * q); |
1891 | unsigned int aac_command_normal(struct aac_queue * q); | 1975 | unsigned int aac_command_normal(struct aac_queue * q); |
1892 | unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index); | 1976 | unsigned int aac_intr_normal(struct aac_dev *dev, u32 Index, |
1977 | int isAif, int isFastResponse, | ||
1978 | struct hw_fib *aif_fib); | ||
1893 | int aac_reset_adapter(struct aac_dev * dev, int forced); | 1979 | int aac_reset_adapter(struct aac_dev * dev, int forced); |
1894 | int aac_check_health(struct aac_dev * dev); | 1980 | int aac_check_health(struct aac_dev * dev); |
1895 | int aac_command_thread(void *data); | 1981 | int aac_command_thread(void *data); |
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 645ddd9d9b9e..8a0b33033177 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c | |||
@@ -5,7 +5,8 @@ | |||
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-2007 Adaptec, Inc. (aacraid@adaptec.com) | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
9 | * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | ||
9 | * | 10 | * |
10 | * This program is free software; you can redistribute it and/or modify | 11 | * 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 | 12 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index a7261486ccd4..7ac8fdb5577b 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c | |||
@@ -5,7 +5,8 @@ | |||
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-2007 Adaptec, Inc. (aacraid@adaptec.com) | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
9 | * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | ||
9 | * | 10 | * |
10 | * This program is free software; you can redistribute it and/or modify | 11 | * 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 | 12 | * it under the terms of the GNU General Public License as published by |
@@ -52,12 +53,16 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co | |||
52 | unsigned long size, align; | 53 | unsigned long size, align; |
53 | const unsigned long fibsize = 4096; | 54 | const unsigned long fibsize = 4096; |
54 | const unsigned long printfbufsiz = 256; | 55 | const unsigned long printfbufsiz = 256; |
56 | unsigned long host_rrq_size = 0; | ||
55 | struct aac_init *init; | 57 | struct aac_init *init; |
56 | dma_addr_t phys; | 58 | dma_addr_t phys; |
57 | unsigned long aac_max_hostphysmempages; | 59 | unsigned long aac_max_hostphysmempages; |
58 | 60 | ||
59 | size = fibsize + sizeof(struct aac_init) + commsize + commalign + printfbufsiz; | 61 | if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) |
60 | 62 | host_rrq_size = (dev->scsi_host_ptr->can_queue | |
63 | + AAC_NUM_MGT_FIB) * sizeof(u32); | ||
64 | size = fibsize + sizeof(struct aac_init) + commsize + | ||
65 | commalign + printfbufsiz + host_rrq_size; | ||
61 | 66 | ||
62 | base = pci_alloc_consistent(dev->pdev, size, &phys); | 67 | base = pci_alloc_consistent(dev->pdev, size, &phys); |
63 | 68 | ||
@@ -70,8 +75,14 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co | |||
70 | dev->comm_phys = phys; | 75 | dev->comm_phys = phys; |
71 | dev->comm_size = size; | 76 | dev->comm_size = size; |
72 | 77 | ||
73 | dev->init = (struct aac_init *)(base + fibsize); | 78 | if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) { |
74 | dev->init_pa = phys + fibsize; | 79 | dev->host_rrq = (u32 *)(base + fibsize); |
80 | dev->host_rrq_pa = phys + fibsize; | ||
81 | memset(dev->host_rrq, 0, host_rrq_size); | ||
82 | } | ||
83 | |||
84 | dev->init = (struct aac_init *)(base + fibsize + host_rrq_size); | ||
85 | dev->init_pa = phys + fibsize + host_rrq_size; | ||
75 | 86 | ||
76 | init = dev->init; | 87 | init = dev->init; |
77 | 88 | ||
@@ -106,8 +117,13 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co | |||
106 | 117 | ||
107 | init->InitFlags = 0; | 118 | init->InitFlags = 0; |
108 | if (dev->comm_interface == AAC_COMM_MESSAGE) { | 119 | if (dev->comm_interface == AAC_COMM_MESSAGE) { |
109 | init->InitFlags = cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED); | 120 | init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED); |
110 | dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n")); | 121 | dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n")); |
122 | } else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) { | ||
123 | init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_6); | ||
124 | init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_TYPE1_SUPPORTED); | ||
125 | dprintk((KERN_WARNING | ||
126 | "aacraid: New Comm Interface type1 enabled\n")); | ||
111 | } | 127 | } |
112 | init->InitFlags |= cpu_to_le32(INITFLAGS_DRIVER_USES_UTC_TIME | | 128 | init->InitFlags |= cpu_to_le32(INITFLAGS_DRIVER_USES_UTC_TIME | |
113 | INITFLAGS_DRIVER_SUPPORTS_PM); | 129 | INITFLAGS_DRIVER_SUPPORTS_PM); |
@@ -115,11 +131,18 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co | |||
115 | init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9); | 131 | init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9); |
116 | init->MaxFibSize = cpu_to_le32(dev->max_fib_size); | 132 | init->MaxFibSize = cpu_to_le32(dev->max_fib_size); |
117 | 133 | ||
134 | init->MaxNumAif = cpu_to_le32(dev->max_num_aif); | ||
135 | init->HostRRQ_AddrHigh = (u32)((u64)dev->host_rrq_pa >> 32); | ||
136 | init->HostRRQ_AddrLow = (u32)(dev->host_rrq_pa & 0xffffffff); | ||
137 | |||
138 | |||
118 | /* | 139 | /* |
119 | * Increment the base address by the amount already used | 140 | * Increment the base address by the amount already used |
120 | */ | 141 | */ |
121 | base = base + fibsize + sizeof(struct aac_init); | 142 | base = base + fibsize + host_rrq_size + sizeof(struct aac_init); |
122 | phys = (dma_addr_t)((ulong)phys + fibsize + sizeof(struct aac_init)); | 143 | phys = (dma_addr_t)((ulong)phys + fibsize + host_rrq_size + |
144 | sizeof(struct aac_init)); | ||
145 | |||
123 | /* | 146 | /* |
124 | * Align the beginning of Headers to commalign | 147 | * Align the beginning of Headers to commalign |
125 | */ | 148 | */ |
@@ -314,15 +337,22 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) | |||
314 | - sizeof(struct aac_write) + sizeof(struct sgentry)) | 337 | - sizeof(struct aac_write) + sizeof(struct sgentry)) |
315 | / sizeof(struct sgentry); | 338 | / sizeof(struct sgentry); |
316 | dev->comm_interface = AAC_COMM_PRODUCER; | 339 | dev->comm_interface = AAC_COMM_PRODUCER; |
317 | dev->raw_io_64 = 0; | 340 | dev->raw_io_interface = dev->raw_io_64 = 0; |
341 | |||
318 | if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, | 342 | if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, |
319 | 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) && | 343 | 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) && |
320 | (status[0] == 0x00000001)) { | 344 | (status[0] == 0x00000001)) { |
321 | if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64)) | 345 | if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64)) |
322 | dev->raw_io_64 = 1; | 346 | dev->raw_io_64 = 1; |
323 | if (dev->a_ops.adapter_comm && | 347 | if (dev->a_ops.adapter_comm) { |
324 | (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM))) | 348 | if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE1)) { |
325 | dev->comm_interface = AAC_COMM_MESSAGE; | 349 | dev->comm_interface = AAC_COMM_MESSAGE_TYPE1; |
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; | ||
353 | dev->raw_io_interface = 1; | ||
354 | } | ||
355 | } | ||
326 | if ((dev->comm_interface == AAC_COMM_MESSAGE) && | 356 | if ((dev->comm_interface == AAC_COMM_MESSAGE) && |
327 | (status[2] > dev->base_size)) { | 357 | (status[2] > dev->base_size)) { |
328 | aac_adapter_ioremap(dev, 0); | 358 | aac_adapter_ioremap(dev, 0); |
@@ -350,10 +380,12 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) | |||
350 | * status[3] & 0xFFFF maximum number FIBs outstanding | 380 | * status[3] & 0xFFFF maximum number FIBs outstanding |
351 | */ | 381 | */ |
352 | host->max_sectors = (status[1] >> 16) << 1; | 382 | host->max_sectors = (status[1] >> 16) << 1; |
353 | dev->max_fib_size = status[1] & 0xFFFF; | 383 | /* Multiple of 32 for PMC */ |
384 | dev->max_fib_size = status[1] & 0xFFE0; | ||
354 | host->sg_tablesize = status[2] >> 16; | 385 | host->sg_tablesize = status[2] >> 16; |
355 | dev->sg_tablesize = status[2] & 0xFFFF; | 386 | dev->sg_tablesize = status[2] & 0xFFFF; |
356 | host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB; | 387 | host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB; |
388 | dev->max_num_aif = status[4] & 0xFFFF; | ||
357 | /* | 389 | /* |
358 | * NOTE: | 390 | * NOTE: |
359 | * All these overrides are based on a fixed internal | 391 | * All these overrides are based on a fixed internal |
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 060ac4bd5a14..dd7ad3ba2dad 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c | |||
@@ -5,7 +5,8 @@ | |||
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-2007 Adaptec, Inc. (aacraid@adaptec.com) | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
9 | * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | ||
9 | * | 10 | * |
10 | * This program is free software; you can redistribute it and/or modify | 11 | * 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 | 12 | * it under the terms of the GNU General Public License as published by |
@@ -63,9 +64,11 @@ static int fib_map_alloc(struct aac_dev *dev) | |||
63 | "allocate hardware fibs pci_alloc_consistent(%p, %d * (%d + %d), %p)\n", | 64 | "allocate hardware fibs pci_alloc_consistent(%p, %d * (%d + %d), %p)\n", |
64 | dev->pdev, dev->max_fib_size, dev->scsi_host_ptr->can_queue, | 65 | dev->pdev, dev->max_fib_size, dev->scsi_host_ptr->can_queue, |
65 | AAC_NUM_MGT_FIB, &dev->hw_fib_pa)); | 66 | AAC_NUM_MGT_FIB, &dev->hw_fib_pa)); |
66 | if((dev->hw_fib_va = pci_alloc_consistent(dev->pdev, dev->max_fib_size | 67 | dev->hw_fib_va = pci_alloc_consistent(dev->pdev, |
67 | * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), | 68 | (dev->max_fib_size + sizeof(struct aac_fib_xporthdr)) |
68 | &dev->hw_fib_pa))==NULL) | 69 | * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) + (ALIGN32 - 1), |
70 | &dev->hw_fib_pa); | ||
71 | if (dev->hw_fib_va == NULL) | ||
69 | return -ENOMEM; | 72 | return -ENOMEM; |
70 | return 0; | 73 | return 0; |
71 | } | 74 | } |
@@ -110,9 +113,22 @@ int aac_fib_setup(struct aac_dev * dev) | |||
110 | if (i<0) | 113 | if (i<0) |
111 | return -ENOMEM; | 114 | return -ENOMEM; |
112 | 115 | ||
116 | /* 32 byte alignment for PMC */ | ||
117 | hw_fib_pa = (dev->hw_fib_pa + (ALIGN32 - 1)) & ~(ALIGN32 - 1); | ||
118 | dev->hw_fib_va = (struct hw_fib *)((unsigned char *)dev->hw_fib_va + | ||
119 | (hw_fib_pa - dev->hw_fib_pa)); | ||
120 | dev->hw_fib_pa = hw_fib_pa; | ||
121 | memset(dev->hw_fib_va, 0, | ||
122 | (dev->max_fib_size + sizeof(struct aac_fib_xporthdr)) * | ||
123 | (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)); | ||
124 | |||
125 | /* add Xport header */ | ||
126 | dev->hw_fib_va = (struct hw_fib *)((unsigned char *)dev->hw_fib_va + | ||
127 | sizeof(struct aac_fib_xporthdr)); | ||
128 | dev->hw_fib_pa += sizeof(struct aac_fib_xporthdr); | ||
129 | |||
113 | hw_fib = dev->hw_fib_va; | 130 | hw_fib = dev->hw_fib_va; |
114 | hw_fib_pa = dev->hw_fib_pa; | 131 | hw_fib_pa = dev->hw_fib_pa; |
115 | memset(hw_fib, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)); | ||
116 | /* | 132 | /* |
117 | * Initialise the fibs | 133 | * Initialise the fibs |
118 | */ | 134 | */ |
@@ -129,8 +145,10 @@ int aac_fib_setup(struct aac_dev * dev) | |||
129 | hw_fib->header.XferState = cpu_to_le32(0xffffffff); | 145 | hw_fib->header.XferState = cpu_to_le32(0xffffffff); |
130 | hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size); | 146 | hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size); |
131 | fibptr->hw_fib_pa = hw_fib_pa; | 147 | fibptr->hw_fib_pa = hw_fib_pa; |
132 | hw_fib = (struct hw_fib *)((unsigned char *)hw_fib + dev->max_fib_size); | 148 | hw_fib = (struct hw_fib *)((unsigned char *)hw_fib + |
133 | hw_fib_pa = hw_fib_pa + dev->max_fib_size; | 149 | dev->max_fib_size + sizeof(struct aac_fib_xporthdr)); |
150 | hw_fib_pa = hw_fib_pa + | ||
151 | dev->max_fib_size + sizeof(struct aac_fib_xporthdr); | ||
134 | } | 152 | } |
135 | /* | 153 | /* |
136 | * Add the fib chain to the free list | 154 | * Add the fib chain to the free list |
@@ -664,9 +682,14 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) | |||
664 | unsigned long nointr = 0; | 682 | unsigned long nointr = 0; |
665 | unsigned long qflags; | 683 | unsigned long qflags; |
666 | 684 | ||
685 | if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) { | ||
686 | kfree(hw_fib); | ||
687 | return 0; | ||
688 | } | ||
689 | |||
667 | if (hw_fib->header.XferState == 0) { | 690 | if (hw_fib->header.XferState == 0) { |
668 | if (dev->comm_interface == AAC_COMM_MESSAGE) | 691 | if (dev->comm_interface == AAC_COMM_MESSAGE) |
669 | kfree (hw_fib); | 692 | kfree(hw_fib); |
670 | return 0; | 693 | return 0; |
671 | } | 694 | } |
672 | /* | 695 | /* |
@@ -674,7 +697,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) | |||
674 | */ | 697 | */ |
675 | if (hw_fib->header.StructType != FIB_MAGIC) { | 698 | if (hw_fib->header.StructType != FIB_MAGIC) { |
676 | if (dev->comm_interface == AAC_COMM_MESSAGE) | 699 | if (dev->comm_interface == AAC_COMM_MESSAGE) |
677 | kfree (hw_fib); | 700 | kfree(hw_fib); |
678 | return -EINVAL; | 701 | return -EINVAL; |
679 | } | 702 | } |
680 | /* | 703 | /* |
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index 9c7408fe8c7d..f0c66a80ad13 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c | |||
@@ -5,7 +5,8 @@ | |||
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-2007 Adaptec, Inc. (aacraid@adaptec.com) | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
9 | * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | ||
9 | * | 10 | * |
10 | * This program is free software; you can redistribute it and/or modify | 11 | * 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 | 12 | * it under the terms of the GNU General Public License as published by |
@@ -228,6 +229,48 @@ unsigned int aac_command_normal(struct aac_queue *q) | |||
228 | return 0; | 229 | return 0; |
229 | } | 230 | } |
230 | 231 | ||
232 | /* | ||
233 | * | ||
234 | * aac_aif_callback | ||
235 | * @context: the context set in the fib - here it is scsi cmd | ||
236 | * @fibptr: pointer to the fib | ||
237 | * | ||
238 | * Handles the AIFs - new method (SRC) | ||
239 | * | ||
240 | */ | ||
241 | |||
242 | static void aac_aif_callback(void *context, struct fib * fibptr) | ||
243 | { | ||
244 | struct fib *fibctx; | ||
245 | struct aac_dev *dev; | ||
246 | struct aac_aifcmd *cmd; | ||
247 | int status; | ||
248 | |||
249 | fibctx = (struct fib *)context; | ||
250 | BUG_ON(fibptr == NULL); | ||
251 | dev = fibptr->dev; | ||
252 | |||
253 | if (fibptr->hw_fib_va->header.XferState & | ||
254 | cpu_to_le32(NoMoreAifDataAvailable)) { | ||
255 | aac_fib_complete(fibptr); | ||
256 | aac_fib_free(fibptr); | ||
257 | return; | ||
258 | } | ||
259 | |||
260 | aac_intr_normal(dev, 0, 1, 0, fibptr->hw_fib_va); | ||
261 | |||
262 | aac_fib_init(fibctx); | ||
263 | cmd = (struct aac_aifcmd *) fib_data(fibctx); | ||
264 | cmd->command = cpu_to_le32(AifReqEvent); | ||
265 | |||
266 | status = aac_fib_send(AifRequest, | ||
267 | fibctx, | ||
268 | sizeof(struct hw_fib)-sizeof(struct aac_fibhdr), | ||
269 | FsaNormal, | ||
270 | 0, 1, | ||
271 | (fib_callback)aac_aif_callback, fibctx); | ||
272 | } | ||
273 | |||
231 | 274 | ||
232 | /** | 275 | /** |
233 | * aac_intr_normal - Handle command replies | 276 | * aac_intr_normal - Handle command replies |
@@ -238,19 +281,17 @@ unsigned int aac_command_normal(struct aac_queue *q) | |||
238 | * know there is a response on our normal priority queue. We will pull off | 281 | * know there is a response on our normal priority queue. We will pull off |
239 | * all QE there are and wake up all the waiters before exiting. | 282 | * all QE there are and wake up all the waiters before exiting. |
240 | */ | 283 | */ |
241 | 284 | unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, | |
242 | unsigned int aac_intr_normal(struct aac_dev * dev, u32 index) | 285 | int isAif, int isFastResponse, struct hw_fib *aif_fib) |
243 | { | 286 | { |
244 | unsigned long mflags; | 287 | unsigned long mflags; |
245 | dprintk((KERN_INFO "aac_intr_normal(%p,%x)\n", dev, index)); | 288 | dprintk((KERN_INFO "aac_intr_normal(%p,%x)\n", dev, index)); |
246 | if ((index & 0x00000002L)) { | 289 | if (isAif == 1) { /* AIF - common */ |
247 | struct hw_fib * hw_fib; | 290 | struct hw_fib * hw_fib; |
248 | struct fib * fib; | 291 | struct fib * fib; |
249 | struct aac_queue *q = &dev->queues->queue[HostNormCmdQueue]; | 292 | struct aac_queue *q = &dev->queues->queue[HostNormCmdQueue]; |
250 | unsigned long flags; | 293 | unsigned long flags; |
251 | 294 | ||
252 | if (index == 0xFFFFFFFEL) /* Special Case */ | ||
253 | return 0; /* Do nothing */ | ||
254 | /* | 295 | /* |
255 | * Allocate a FIB. For non queued stuff we can just use | 296 | * Allocate a FIB. For non queued stuff we can just use |
256 | * the stack so we are happy. We need a fib object in order to | 297 | * the stack so we are happy. We need a fib object in order to |
@@ -263,8 +304,13 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 index) | |||
263 | kfree (fib); | 304 | kfree (fib); |
264 | return 1; | 305 | return 1; |
265 | } | 306 | } |
266 | memcpy(hw_fib, (struct hw_fib *)(((uintptr_t)(dev->regs.sa)) + | 307 | if (aif_fib != NULL) { |
267 | (index & ~0x00000002L)), sizeof(struct hw_fib)); | 308 | memcpy(hw_fib, aif_fib, sizeof(struct hw_fib)); |
309 | } else { | ||
310 | memcpy(hw_fib, | ||
311 | (struct hw_fib *)(((uintptr_t)(dev->regs.sa)) + | ||
312 | index), sizeof(struct hw_fib)); | ||
313 | } | ||
268 | INIT_LIST_HEAD(&fib->fiblink); | 314 | INIT_LIST_HEAD(&fib->fiblink); |
269 | fib->type = FSAFS_NTC_FIB_CONTEXT; | 315 | fib->type = FSAFS_NTC_FIB_CONTEXT; |
270 | fib->size = sizeof(struct fib); | 316 | fib->size = sizeof(struct fib); |
@@ -277,9 +323,26 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 index) | |||
277 | wake_up_interruptible(&q->cmdready); | 323 | wake_up_interruptible(&q->cmdready); |
278 | spin_unlock_irqrestore(q->lock, flags); | 324 | spin_unlock_irqrestore(q->lock, flags); |
279 | return 1; | 325 | return 1; |
326 | } else if (isAif == 2) { /* AIF - new (SRC) */ | ||
327 | struct fib *fibctx; | ||
328 | struct aac_aifcmd *cmd; | ||
329 | |||
330 | fibctx = aac_fib_alloc(dev); | ||
331 | if (!fibctx) | ||
332 | return 1; | ||
333 | aac_fib_init(fibctx); | ||
334 | |||
335 | cmd = (struct aac_aifcmd *) fib_data(fibctx); | ||
336 | cmd->command = cpu_to_le32(AifReqEvent); | ||
337 | |||
338 | return aac_fib_send(AifRequest, | ||
339 | fibctx, | ||
340 | sizeof(struct hw_fib)-sizeof(struct aac_fibhdr), | ||
341 | FsaNormal, | ||
342 | 0, 1, | ||
343 | (fib_callback)aac_aif_callback, fibctx); | ||
280 | } else { | 344 | } else { |
281 | int fast = index & 0x01; | 345 | struct fib *fib = &dev->fibs[index]; |
282 | struct fib * fib = &dev->fibs[index >> 2]; | ||
283 | struct hw_fib * hwfib = fib->hw_fib_va; | 346 | struct hw_fib * hwfib = fib->hw_fib_va; |
284 | 347 | ||
285 | /* | 348 | /* |
@@ -298,7 +361,7 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 index) | |||
298 | return 0; | 361 | return 0; |
299 | } | 362 | } |
300 | 363 | ||
301 | if (fast) { | 364 | if (isFastResponse) { |
302 | /* | 365 | /* |
303 | * Doctor the fib | 366 | * Doctor the fib |
304 | */ | 367 | */ |
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 2c93d9496d62..4ff26521d75f 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c | |||
@@ -5,7 +5,8 @@ | |||
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-2007 Adaptec, Inc. (aacraid@adaptec.com) | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
9 | * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | ||
9 | * | 10 | * |
10 | * This program is free software; you can redistribute it and/or modify | 11 | * 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 | 12 | * it under the terms of the GNU General Public License as published by |
@@ -54,7 +55,7 @@ | |||
54 | 55 | ||
55 | #include "aacraid.h" | 56 | #include "aacraid.h" |
56 | 57 | ||
57 | #define AAC_DRIVER_VERSION "1.1-5" | 58 | #define AAC_DRIVER_VERSION "1.1-7" |
58 | #ifndef AAC_DRIVER_BRANCH | 59 | #ifndef AAC_DRIVER_BRANCH |
59 | #define AAC_DRIVER_BRANCH "" | 60 | #define AAC_DRIVER_BRANCH "" |
60 | #endif | 61 | #endif |
@@ -161,6 +162,7 @@ static const struct pci_device_id aac_pci_tbl[] __devinitdata = { | |||
161 | { 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 */ |
162 | { 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 */ |
163 | { 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 */ | ||
164 | { 0,} | 166 | { 0,} |
165 | }; | 167 | }; |
166 | MODULE_DEVICE_TABLE(pci, aac_pci_tbl); | 168 | MODULE_DEVICE_TABLE(pci, aac_pci_tbl); |
@@ -235,7 +237,8 @@ static struct aac_driver_ident aac_drivers[] = { | |||
235 | { aac_rx_init, "aacraid", "Legend ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Legend Catchall */ | 237 | { aac_rx_init, "aacraid", "Legend ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Legend Catchall */ |
236 | { aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Catch All */ | 238 | { aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Catch All */ |
237 | { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Rocket Catch All */ | 239 | { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Rocket Catch All */ |
238 | { aac_nark_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec NEMER/ARK Catch All */ | 240 | { aac_nark_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec NEMER/ARK Catch All */ |
241 | { aac_src_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec PMC Catch All */ | ||
239 | }; | 242 | }; |
240 | 243 | ||
241 | /** | 244 | /** |
@@ -653,8 +656,10 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) | |||
653 | * This adapter needs a blind reset, only do so for Adapters that | 656 | * This adapter needs a blind reset, only do so for Adapters that |
654 | * support a register, instead of a commanded, reset. | 657 | * support a register, instead of a commanded, reset. |
655 | */ | 658 | */ |
656 | if ((aac->supplement_adapter_info.SupportedOptions2 & | 659 | if (((aac->supplement_adapter_info.SupportedOptions2 & |
657 | AAC_OPTION_MU_RESET) && | 660 | AAC_OPTION_MU_RESET) || |
661 | (aac->supplement_adapter_info.SupportedOptions2 & | ||
662 | AAC_OPTION_DOORBELL_RESET)) && | ||
658 | aac_check_reset && | 663 | aac_check_reset && |
659 | ((aac_check_reset != 1) || | 664 | ((aac_check_reset != 1) || |
660 | !(aac->supplement_adapter_info.SupportedOptions2 & | 665 | !(aac->supplement_adapter_info.SupportedOptions2 & |
diff --git a/drivers/scsi/aacraid/nark.c b/drivers/scsi/aacraid/nark.c index c55f7c862f0e..f397d21a0c06 100644 --- a/drivers/scsi/aacraid/nark.c +++ b/drivers/scsi/aacraid/nark.c | |||
@@ -4,7 +4,8 @@ | |||
4 | * based on the old aacraid driver that is.. | 4 | * based on the old aacraid driver that is.. |
5 | * Adaptec aacraid device driver for Linux. | 5 | * Adaptec aacraid device driver for Linux. |
6 | * | 6 | * |
7 | * Copyright (c) 2006-2007 Adaptec, Inc. (aacraid@adaptec.com) | 7 | * Copyright (c) 2000-2010 Adaptec, Inc. |
8 | * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | ||
8 | * | 9 | * |
9 | * 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 |
10 | * 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 |
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c index 16d8db550027..be44de92429a 100644 --- a/drivers/scsi/aacraid/rkt.c +++ b/drivers/scsi/aacraid/rkt.c | |||
@@ -5,7 +5,8 @@ | |||
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-2007 Adaptec, Inc. (aacraid@adaptec.com) | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
9 | * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | ||
9 | * | 10 | * |
10 | * This program is free software; you can redistribute it and/or modify | 11 | * 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 | 12 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 84d77fd86e5b..ce530f113fdb 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c | |||
@@ -5,7 +5,8 @@ | |||
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-2007 Adaptec, Inc. (aacraid@adaptec.com) | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
9 | * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | ||
9 | * | 10 | * |
10 | * This program is free software; you can redistribute it and/or modify | 11 | * 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 | 12 | * it under the terms of the GNU General Public License as published by |
@@ -84,15 +85,35 @@ static irqreturn_t aac_rx_intr_producer(int irq, void *dev_id) | |||
84 | 85 | ||
85 | static irqreturn_t aac_rx_intr_message(int irq, void *dev_id) | 86 | static irqreturn_t aac_rx_intr_message(int irq, void *dev_id) |
86 | { | 87 | { |
88 | int isAif, isFastResponse, isSpecial; | ||
87 | struct aac_dev *dev = dev_id; | 89 | struct aac_dev *dev = dev_id; |
88 | u32 Index = rx_readl(dev, MUnit.OutboundQueue); | 90 | u32 Index = rx_readl(dev, MUnit.OutboundQueue); |
89 | if (unlikely(Index == 0xFFFFFFFFL)) | 91 | if (unlikely(Index == 0xFFFFFFFFL)) |
90 | Index = rx_readl(dev, MUnit.OutboundQueue); | 92 | Index = rx_readl(dev, MUnit.OutboundQueue); |
91 | if (likely(Index != 0xFFFFFFFFL)) { | 93 | if (likely(Index != 0xFFFFFFFFL)) { |
92 | do { | 94 | do { |
93 | if (unlikely(aac_intr_normal(dev, Index))) { | 95 | isAif = isFastResponse = isSpecial = 0; |
94 | rx_writel(dev, MUnit.OutboundQueue, Index); | 96 | if (Index & 0x00000002L) { |
95 | rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady); | 97 | isAif = 1; |
98 | if (Index == 0xFFFFFFFEL) | ||
99 | isSpecial = 1; | ||
100 | Index &= ~0x00000002L; | ||
101 | } else { | ||
102 | if (Index & 0x00000001L) | ||
103 | isFastResponse = 1; | ||
104 | Index >>= 2; | ||
105 | } | ||
106 | if (!isSpecial) { | ||
107 | if (unlikely(aac_intr_normal(dev, | ||
108 | Index, isAif, | ||
109 | isFastResponse, NULL))) { | ||
110 | rx_writel(dev, | ||
111 | MUnit.OutboundQueue, | ||
112 | Index); | ||
113 | rx_writel(dev, | ||
114 | MUnit.ODR, | ||
115 | DoorBellAdapterNormRespReady); | ||
116 | } | ||
96 | } | 117 | } |
97 | Index = rx_readl(dev, MUnit.OutboundQueue); | 118 | Index = rx_readl(dev, MUnit.OutboundQueue); |
98 | } while (Index != 0xFFFFFFFFL); | 119 | } while (Index != 0xFFFFFFFFL); |
@@ -631,6 +652,10 @@ int _aac_rx_init(struct aac_dev *dev) | |||
631 | name, instance); | 652 | name, instance); |
632 | goto error_iounmap; | 653 | goto error_iounmap; |
633 | } | 654 | } |
655 | dev->dbg_base = dev->scsi_host_ptr->base; | ||
656 | dev->dbg_base_mapped = dev->base; | ||
657 | dev->dbg_size = dev->base_size; | ||
658 | |||
634 | aac_adapter_enable_int(dev); | 659 | aac_adapter_enable_int(dev); |
635 | /* | 660 | /* |
636 | * Tell the adapter that all is configured, and it can | 661 | * Tell the adapter that all is configured, and it can |
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c index 622c21c68e65..e5d4457121ea 100644 --- a/drivers/scsi/aacraid/sa.c +++ b/drivers/scsi/aacraid/sa.c | |||
@@ -5,7 +5,8 @@ | |||
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-2007 Adaptec, Inc. (aacraid@adaptec.com) | 8 | * Copyright (c) 2000-2010 Adaptec, Inc. |
9 | * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | ||
9 | * | 10 | * |
10 | * This program is free software; you can redistribute it and/or modify | 11 | * 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 | 12 | * it under the terms of the GNU General Public License as published by |
@@ -391,6 +392,10 @@ int aac_sa_init(struct aac_dev *dev) | |||
391 | name, instance); | 392 | name, instance); |
392 | goto error_iounmap; | 393 | goto error_iounmap; |
393 | } | 394 | } |
395 | dev->dbg_base = dev->scsi_host_ptr->base; | ||
396 | dev->dbg_base_mapped = dev->base; | ||
397 | dev->dbg_size = dev->base_size; | ||
398 | |||
394 | aac_adapter_enable_int(dev); | 399 | aac_adapter_enable_int(dev); |
395 | 400 | ||
396 | /* | 401 | /* |
diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c new file mode 100644 index 000000000000..c20494660603 --- /dev/null +++ b/drivers/scsi/aacraid/src.c | |||
@@ -0,0 +1,594 @@ | |||
1 | /* | ||
2 | * Adaptec AAC series RAID controller driver | ||
3 | * (c) Copyright 2001 Red Hat Inc. | ||
4 | * | ||
5 | * based on the old aacraid driver that is.. | ||
6 | * Adaptec aacraid device driver for Linux. | ||
7 | * | ||
8 | * Copyright (c) 2000-2010 Adaptec, Inc. | ||
9 | * 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2, or (at your option) | ||
14 | * any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; see the file COPYING. If not, write to | ||
23 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | * Module Name: | ||
26 | * src.c | ||
27 | * | ||
28 | * Abstract: Hardware Device Interface for PMC SRC based controllers | ||
29 | * | ||
30 | */ | ||
31 | |||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <linux/types.h> | ||
35 | #include <linux/pci.h> | ||
36 | #include <linux/spinlock.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/blkdev.h> | ||
39 | #include <linux/delay.h> | ||
40 | #include <linux/version.h> | ||
41 | #include <linux/completion.h> | ||
42 | #include <linux/time.h> | ||
43 | #include <linux/interrupt.h> | ||
44 | #include <scsi/scsi_host.h> | ||
45 | |||
46 | #include "aacraid.h" | ||
47 | |||
48 | static irqreturn_t aac_src_intr_message(int irq, void *dev_id) | ||
49 | { | ||
50 | struct aac_dev *dev = dev_id; | ||
51 | unsigned long bellbits, bellbits_shifted; | ||
52 | int our_interrupt = 0; | ||
53 | int isFastResponse; | ||
54 | u32 index, handle; | ||
55 | |||
56 | bellbits = src_readl(dev, MUnit.ODR_R); | ||
57 | if (bellbits & PmDoorBellResponseSent) { | ||
58 | bellbits = PmDoorBellResponseSent; | ||
59 | /* handle async. status */ | ||
60 | our_interrupt = 1; | ||
61 | index = dev->host_rrq_idx; | ||
62 | if (dev->host_rrq[index] == 0) { | ||
63 | u32 old_index = index; | ||
64 | /* adjust index */ | ||
65 | do { | ||
66 | index++; | ||
67 | if (index == dev->scsi_host_ptr->can_queue + | ||
68 | AAC_NUM_MGT_FIB) | ||
69 | index = 0; | ||
70 | if (dev->host_rrq[index] != 0) | ||
71 | break; | ||
72 | } while (index != old_index); | ||
73 | dev->host_rrq_idx = index; | ||
74 | } | ||
75 | for (;;) { | ||
76 | isFastResponse = 0; | ||
77 | /* remove toggle bit (31) */ | ||
78 | handle = (dev->host_rrq[index] & 0x7fffffff); | ||
79 | /* check fast response bit (30) */ | ||
80 | if (handle & 0x40000000) | ||
81 | isFastResponse = 1; | ||
82 | handle &= 0x0000ffff; | ||
83 | if (handle == 0) | ||
84 | break; | ||
85 | |||
86 | aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL); | ||
87 | |||
88 | dev->host_rrq[index++] = 0; | ||
89 | if (index == dev->scsi_host_ptr->can_queue + | ||
90 | AAC_NUM_MGT_FIB) | ||
91 | index = 0; | ||
92 | dev->host_rrq_idx = index; | ||
93 | } | ||
94 | } else { | ||
95 | bellbits_shifted = (bellbits >> SRC_ODR_SHIFT); | ||
96 | if (bellbits_shifted & DoorBellAifPending) { | ||
97 | our_interrupt = 1; | ||
98 | /* handle AIF */ | ||
99 | aac_intr_normal(dev, 0, 2, 0, NULL); | ||
100 | } | ||
101 | } | ||
102 | |||
103 | if (our_interrupt) { | ||
104 | src_writel(dev, MUnit.ODR_C, bellbits); | ||
105 | return IRQ_HANDLED; | ||
106 | } | ||
107 | return IRQ_NONE; | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * aac_src_disable_interrupt - Disable interrupts | ||
112 | * @dev: Adapter | ||
113 | */ | ||
114 | |||
115 | static void aac_src_disable_interrupt(struct aac_dev *dev) | ||
116 | { | ||
117 | src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff); | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * aac_src_enable_interrupt_message - Enable interrupts | ||
122 | * @dev: Adapter | ||
123 | */ | ||
124 | |||
125 | static void aac_src_enable_interrupt_message(struct aac_dev *dev) | ||
126 | { | ||
127 | src_writel(dev, MUnit.OIMR, dev->OIMR = 0xfffffff8); | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * src_sync_cmd - send a command and wait | ||
132 | * @dev: Adapter | ||
133 | * @command: Command to execute | ||
134 | * @p1: first parameter | ||
135 | * @ret: adapter status | ||
136 | * | ||
137 | * This routine will send a synchronous command to the adapter and wait | ||
138 | * for its completion. | ||
139 | */ | ||
140 | |||
141 | static int src_sync_cmd(struct aac_dev *dev, u32 command, | ||
142 | u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, | ||
143 | u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4) | ||
144 | { | ||
145 | unsigned long start; | ||
146 | int ok; | ||
147 | |||
148 | /* | ||
149 | * Write the command into Mailbox 0 | ||
150 | */ | ||
151 | writel(command, &dev->IndexRegs->Mailbox[0]); | ||
152 | /* | ||
153 | * Write the parameters into Mailboxes 1 - 6 | ||
154 | */ | ||
155 | writel(p1, &dev->IndexRegs->Mailbox[1]); | ||
156 | writel(p2, &dev->IndexRegs->Mailbox[2]); | ||
157 | writel(p3, &dev->IndexRegs->Mailbox[3]); | ||
158 | writel(p4, &dev->IndexRegs->Mailbox[4]); | ||
159 | |||
160 | /* | ||
161 | * Clear the synch command doorbell to start on a clean slate. | ||
162 | */ | ||
163 | src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | ||
164 | |||
165 | /* | ||
166 | * Disable doorbell interrupts | ||
167 | */ | ||
168 | src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff); | ||
169 | |||
170 | /* | ||
171 | * Force the completion of the mask register write before issuing | ||
172 | * the interrupt. | ||
173 | */ | ||
174 | src_readl(dev, MUnit.OIMR); | ||
175 | |||
176 | /* | ||
177 | * Signal that there is a new synch command | ||
178 | */ | ||
179 | src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT); | ||
180 | |||
181 | ok = 0; | ||
182 | start = jiffies; | ||
183 | |||
184 | /* | ||
185 | * Wait up to 30 seconds | ||
186 | */ | ||
187 | while (time_before(jiffies, start+30*HZ)) { | ||
188 | /* Delay 5 microseconds to let Mon960 get info. */ | ||
189 | udelay(5); | ||
190 | |||
191 | /* Mon960 will set doorbell0 bit | ||
192 | * when it has completed the command | ||
193 | */ | ||
194 | if ((src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT) & OUTBOUNDDOORBELL_0) { | ||
195 | /* Clear the doorbell */ | ||
196 | src_writel(dev, | ||
197 | MUnit.ODR_C, | ||
198 | OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | ||
199 | ok = 1; | ||
200 | break; | ||
201 | } | ||
202 | |||
203 | /* Yield the processor in case we are slow */ | ||
204 | msleep(1); | ||
205 | } | ||
206 | if (unlikely(ok != 1)) { | ||
207 | /* Restore interrupt mask even though we timed out */ | ||
208 | aac_adapter_enable_int(dev); | ||
209 | return -ETIMEDOUT; | ||
210 | } | ||
211 | |||
212 | /* Pull the synch status from Mailbox 0 */ | ||
213 | if (status) | ||
214 | *status = readl(&dev->IndexRegs->Mailbox[0]); | ||
215 | if (r1) | ||
216 | *r1 = readl(&dev->IndexRegs->Mailbox[1]); | ||
217 | if (r2) | ||
218 | *r2 = readl(&dev->IndexRegs->Mailbox[2]); | ||
219 | if (r3) | ||
220 | *r3 = readl(&dev->IndexRegs->Mailbox[3]); | ||
221 | if (r4) | ||
222 | *r4 = readl(&dev->IndexRegs->Mailbox[4]); | ||
223 | |||
224 | /* Clear the synch command doorbell */ | ||
225 | src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | ||
226 | |||
227 | /* Restore interrupt mask */ | ||
228 | aac_adapter_enable_int(dev); | ||
229 | return 0; | ||
230 | |||
231 | } | ||
232 | |||
233 | /** | ||
234 | * aac_src_interrupt_adapter - interrupt adapter | ||
235 | * @dev: Adapter | ||
236 | * | ||
237 | * Send an interrupt to the i960 and breakpoint it. | ||
238 | */ | ||
239 | |||
240 | static void aac_src_interrupt_adapter(struct aac_dev *dev) | ||
241 | { | ||
242 | src_sync_cmd(dev, BREAKPOINT_REQUEST, | ||
243 | 0, 0, 0, 0, 0, 0, | ||
244 | NULL, NULL, NULL, NULL, NULL); | ||
245 | } | ||
246 | |||
247 | /** | ||
248 | * aac_src_notify_adapter - send an event to the adapter | ||
249 | * @dev: Adapter | ||
250 | * @event: Event to send | ||
251 | * | ||
252 | * Notify the i960 that something it probably cares about has | ||
253 | * happened. | ||
254 | */ | ||
255 | |||
256 | static void aac_src_notify_adapter(struct aac_dev *dev, u32 event) | ||
257 | { | ||
258 | switch (event) { | ||
259 | |||
260 | case AdapNormCmdQue: | ||
261 | src_writel(dev, MUnit.ODR_C, | ||
262 | INBOUNDDOORBELL_1 << SRC_ODR_SHIFT); | ||
263 | break; | ||
264 | case HostNormRespNotFull: | ||
265 | src_writel(dev, MUnit.ODR_C, | ||
266 | INBOUNDDOORBELL_4 << SRC_ODR_SHIFT); | ||
267 | break; | ||
268 | case AdapNormRespQue: | ||
269 | src_writel(dev, MUnit.ODR_C, | ||
270 | INBOUNDDOORBELL_2 << SRC_ODR_SHIFT); | ||
271 | break; | ||
272 | case HostNormCmdNotFull: | ||
273 | src_writel(dev, MUnit.ODR_C, | ||
274 | INBOUNDDOORBELL_3 << SRC_ODR_SHIFT); | ||
275 | break; | ||
276 | case FastIo: | ||
277 | src_writel(dev, MUnit.ODR_C, | ||
278 | INBOUNDDOORBELL_6 << SRC_ODR_SHIFT); | ||
279 | break; | ||
280 | case AdapPrintfDone: | ||
281 | src_writel(dev, MUnit.ODR_C, | ||
282 | INBOUNDDOORBELL_5 << SRC_ODR_SHIFT); | ||
283 | break; | ||
284 | default: | ||
285 | BUG(); | ||
286 | break; | ||
287 | } | ||
288 | } | ||
289 | |||
290 | /** | ||
291 | * aac_src_start_adapter - activate adapter | ||
292 | * @dev: Adapter | ||
293 | * | ||
294 | * Start up processing on an i960 based AAC adapter | ||
295 | */ | ||
296 | |||
297 | static void aac_src_start_adapter(struct aac_dev *dev) | ||
298 | { | ||
299 | struct aac_init *init; | ||
300 | |||
301 | init = dev->init; | ||
302 | init->HostElapsedSeconds = cpu_to_le32(get_seconds()); | ||
303 | |||
304 | /* We can only use a 32 bit address here */ | ||
305 | src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, | ||
306 | 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL); | ||
307 | } | ||
308 | |||
309 | /** | ||
310 | * aac_src_check_health | ||
311 | * @dev: device to check if healthy | ||
312 | * | ||
313 | * Will attempt to determine if the specified adapter is alive and | ||
314 | * capable of handling requests, returning 0 if alive. | ||
315 | */ | ||
316 | static int aac_src_check_health(struct aac_dev *dev) | ||
317 | { | ||
318 | u32 status = src_readl(dev, MUnit.OMR); | ||
319 | |||
320 | /* | ||
321 | * Check to see if the board failed any self tests. | ||
322 | */ | ||
323 | if (unlikely(status & SELF_TEST_FAILED)) | ||
324 | return -1; | ||
325 | |||
326 | /* | ||
327 | * Check to see if the board panic'd. | ||
328 | */ | ||
329 | if (unlikely(status & KERNEL_PANIC)) | ||
330 | return (status >> 16) & 0xFF; | ||
331 | /* | ||
332 | * Wait for the adapter to be up and running. | ||
333 | */ | ||
334 | if (unlikely(!(status & KERNEL_UP_AND_RUNNING))) | ||
335 | return -3; | ||
336 | /* | ||
337 | * Everything is OK | ||
338 | */ | ||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | /** | ||
343 | * aac_src_deliver_message | ||
344 | * @fib: fib to issue | ||
345 | * | ||
346 | * Will send a fib, returning 0 if successful. | ||
347 | */ | ||
348 | static int aac_src_deliver_message(struct fib *fib) | ||
349 | { | ||
350 | struct aac_dev *dev = fib->dev; | ||
351 | struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; | ||
352 | unsigned long qflags; | ||
353 | u32 fibsize; | ||
354 | u64 address; | ||
355 | struct aac_fib_xporthdr *pFibX; | ||
356 | |||
357 | spin_lock_irqsave(q->lock, qflags); | ||
358 | q->numpending++; | ||
359 | spin_unlock_irqrestore(q->lock, qflags); | ||
360 | |||
361 | /* Calculate the amount to the fibsize bits */ | ||
362 | fibsize = (sizeof(struct aac_fib_xporthdr) + | ||
363 | fib->hw_fib_va->header.Size + 127) / 128 - 1; | ||
364 | if (fibsize > (ALIGN32 - 1)) | ||
365 | fibsize = ALIGN32 - 1; | ||
366 | |||
367 | /* Fill XPORT header */ | ||
368 | pFibX = (struct aac_fib_xporthdr *) | ||
369 | ((unsigned char *)fib->hw_fib_va - | ||
370 | sizeof(struct aac_fib_xporthdr)); | ||
371 | pFibX->Handle = fib->hw_fib_va->header.SenderData + 1; | ||
372 | pFibX->HostAddress = fib->hw_fib_pa; | ||
373 | pFibX->Size = fib->hw_fib_va->header.Size; | ||
374 | address = fib->hw_fib_pa - (u64)sizeof(struct aac_fib_xporthdr); | ||
375 | |||
376 | src_writel(dev, MUnit.IQ_H, (u32)(address >> 32)); | ||
377 | src_writel(dev, MUnit.IQ_L, (u32)(address & 0xffffffff) + fibsize); | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | /** | ||
382 | * aac_src_ioremap | ||
383 | * @size: mapping resize request | ||
384 | * | ||
385 | */ | ||
386 | static int aac_src_ioremap(struct aac_dev *dev, u32 size) | ||
387 | { | ||
388 | if (!size) { | ||
389 | iounmap(dev->regs.src.bar0); | ||
390 | dev->regs.src.bar0 = NULL; | ||
391 | iounmap(dev->base); | ||
392 | dev->base = NULL; | ||
393 | return 0; | ||
394 | } | ||
395 | dev->regs.src.bar1 = ioremap(pci_resource_start(dev->pdev, 2), | ||
396 | AAC_MIN_SRC_BAR1_SIZE); | ||
397 | dev->base = NULL; | ||
398 | if (dev->regs.src.bar1 == NULL) | ||
399 | return -1; | ||
400 | dev->base = dev->regs.src.bar0 = ioremap(dev->scsi_host_ptr->base, | ||
401 | size); | ||
402 | if (dev->base == NULL) { | ||
403 | iounmap(dev->regs.src.bar1); | ||
404 | dev->regs.src.bar1 = NULL; | ||
405 | return -1; | ||
406 | } | ||
407 | dev->IndexRegs = &((struct src_registers __iomem *) | ||
408 | dev->base)->IndexRegs; | ||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | static int aac_src_restart_adapter(struct aac_dev *dev, int bled) | ||
413 | { | ||
414 | u32 var, reset_mask; | ||
415 | |||
416 | if (bled >= 0) { | ||
417 | if (bled) | ||
418 | printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n", | ||
419 | dev->name, dev->id, bled); | ||
420 | bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, | ||
421 | 0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL); | ||
422 | if (bled || (var != 0x00000001)) | ||
423 | bled = -EINVAL; | ||
424 | if (dev->supplement_adapter_info.SupportedOptions2 & | ||
425 | AAC_OPTION_DOORBELL_RESET) { | ||
426 | src_writel(dev, MUnit.IDR, reset_mask); | ||
427 | msleep(5000); /* Delay 5 seconds */ | ||
428 | } | ||
429 | } | ||
430 | |||
431 | if (src_readl(dev, MUnit.OMR) & KERNEL_PANIC) | ||
432 | return -ENODEV; | ||
433 | |||
434 | if (startup_timeout < 300) | ||
435 | startup_timeout = 300; | ||
436 | |||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | /** | ||
441 | * aac_src_select_comm - Select communications method | ||
442 | * @dev: Adapter | ||
443 | * @comm: communications method | ||
444 | */ | ||
445 | int aac_src_select_comm(struct aac_dev *dev, int comm) | ||
446 | { | ||
447 | switch (comm) { | ||
448 | case AAC_COMM_MESSAGE: | ||
449 | dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message; | ||
450 | dev->a_ops.adapter_intr = aac_src_intr_message; | ||
451 | dev->a_ops.adapter_deliver = aac_src_deliver_message; | ||
452 | break; | ||
453 | default: | ||
454 | return 1; | ||
455 | } | ||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | /** | ||
460 | * aac_src_init - initialize an Cardinal Frey Bar card | ||
461 | * @dev: device to configure | ||
462 | * | ||
463 | */ | ||
464 | |||
465 | int aac_src_init(struct aac_dev *dev) | ||
466 | { | ||
467 | unsigned long start; | ||
468 | unsigned long status; | ||
469 | int restart = 0; | ||
470 | int instance = dev->id; | ||
471 | const char *name = dev->name; | ||
472 | |||
473 | dev->a_ops.adapter_ioremap = aac_src_ioremap; | ||
474 | dev->a_ops.adapter_comm = aac_src_select_comm; | ||
475 | |||
476 | dev->base_size = AAC_MIN_SRC_BAR0_SIZE; | ||
477 | if (aac_adapter_ioremap(dev, dev->base_size)) { | ||
478 | printk(KERN_WARNING "%s: unable to map adapter.\n", name); | ||
479 | goto error_iounmap; | ||
480 | } | ||
481 | |||
482 | /* Failure to reset here is an option ... */ | ||
483 | dev->a_ops.adapter_sync_cmd = src_sync_cmd; | ||
484 | dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; | ||
485 | if ((aac_reset_devices || reset_devices) && | ||
486 | !aac_src_restart_adapter(dev, 0)) | ||
487 | ++restart; | ||
488 | /* | ||
489 | * Check to see if the board panic'd while booting. | ||
490 | */ | ||
491 | status = src_readl(dev, MUnit.OMR); | ||
492 | if (status & KERNEL_PANIC) { | ||
493 | if (aac_src_restart_adapter(dev, aac_src_check_health(dev))) | ||
494 | goto error_iounmap; | ||
495 | ++restart; | ||
496 | } | ||
497 | /* | ||
498 | * Check to see if the board failed any self tests. | ||
499 | */ | ||
500 | status = src_readl(dev, MUnit.OMR); | ||
501 | if (status & SELF_TEST_FAILED) { | ||
502 | printk(KERN_ERR "%s%d: adapter self-test failed.\n", | ||
503 | dev->name, instance); | ||
504 | goto error_iounmap; | ||
505 | } | ||
506 | /* | ||
507 | * Check to see if the monitor panic'd while booting. | ||
508 | */ | ||
509 | if (status & MONITOR_PANIC) { | ||
510 | printk(KERN_ERR "%s%d: adapter monitor panic.\n", | ||
511 | dev->name, instance); | ||
512 | goto error_iounmap; | ||
513 | } | ||
514 | start = jiffies; | ||
515 | /* | ||
516 | * Wait for the adapter to be up and running. Wait up to 3 minutes | ||
517 | */ | ||
518 | while (!((status = src_readl(dev, MUnit.OMR)) & | ||
519 | KERNEL_UP_AND_RUNNING)) { | ||
520 | if ((restart && | ||
521 | (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) || | ||
522 | time_after(jiffies, start+HZ*startup_timeout)) { | ||
523 | printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", | ||
524 | dev->name, instance, status); | ||
525 | goto error_iounmap; | ||
526 | } | ||
527 | if (!restart && | ||
528 | ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) || | ||
529 | time_after(jiffies, start + HZ * | ||
530 | ((startup_timeout > 60) | ||
531 | ? (startup_timeout - 60) | ||
532 | : (startup_timeout / 2))))) { | ||
533 | if (likely(!aac_src_restart_adapter(dev, | ||
534 | aac_src_check_health(dev)))) | ||
535 | start = jiffies; | ||
536 | ++restart; | ||
537 | } | ||
538 | msleep(1); | ||
539 | } | ||
540 | if (restart && aac_commit) | ||
541 | aac_commit = 1; | ||
542 | /* | ||
543 | * Fill in the common function dispatch table. | ||
544 | */ | ||
545 | dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter; | ||
546 | dev->a_ops.adapter_disable_int = aac_src_disable_interrupt; | ||
547 | dev->a_ops.adapter_notify = aac_src_notify_adapter; | ||
548 | dev->a_ops.adapter_sync_cmd = src_sync_cmd; | ||
549 | dev->a_ops.adapter_check_health = aac_src_check_health; | ||
550 | dev->a_ops.adapter_restart = aac_src_restart_adapter; | ||
551 | |||
552 | /* | ||
553 | * First clear out all interrupts. Then enable the one's that we | ||
554 | * can handle. | ||
555 | */ | ||
556 | aac_adapter_comm(dev, AAC_COMM_MESSAGE); | ||
557 | aac_adapter_disable_int(dev); | ||
558 | src_writel(dev, MUnit.ODR_C, 0xffffffff); | ||
559 | aac_adapter_enable_int(dev); | ||
560 | |||
561 | if (aac_init_adapter(dev) == NULL) | ||
562 | goto error_iounmap; | ||
563 | if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1) | ||
564 | goto error_iounmap; | ||
565 | |||
566 | dev->msi = aac_msi && !pci_enable_msi(dev->pdev); | ||
567 | |||
568 | if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, | ||
569 | IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) { | ||
570 | |||
571 | if (dev->msi) | ||
572 | pci_disable_msi(dev->pdev); | ||
573 | |||
574 | printk(KERN_ERR "%s%d: Interrupt unavailable.\n", | ||
575 | name, instance); | ||
576 | goto error_iounmap; | ||
577 | } | ||
578 | dev->dbg_base = pci_resource_start(dev->pdev, 2); | ||
579 | dev->dbg_base_mapped = dev->regs.src.bar1; | ||
580 | dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE; | ||
581 | |||
582 | aac_adapter_enable_int(dev); | ||
583 | /* | ||
584 | * Tell the adapter that all is configured, and it can | ||
585 | * start accepting requests | ||
586 | */ | ||
587 | aac_src_start_adapter(dev); | ||
588 | |||
589 | return 0; | ||
590 | |||
591 | error_iounmap: | ||
592 | |||
593 | return -1; | ||
594 | } | ||