diff options
author | Sumant Patro <sumantp@lsil.com> | 2006-01-25 15:02:40 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2006-01-29 12:25:30 -0500 |
commit | 1341c939222f4d1cc8d9eb2b794f26f089fe0a61 (patch) | |
tree | acafd546c590b8661f9f67b9a293f7742e50bd7c /drivers | |
parent | cb59aa6a7ca1ae40fd436c45dff568a83f3fab2f (diff) |
[SCSI] megaraid_sas: new template defined to represent each type of controllers
This patch defines a new template to represent each type of
controllers (identified by the processor used). The template has
members that is set with appropriate values during driver
initialisation. This change is done to support new controllers with
minimal change to existing code. In future, for a new controller
support, a template will be declared and its members initialised
appropriately.
Signed-off-by: Sumant Patro <Sumant.Patro@lsil.com>
Rejections fixed and
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.c | 133 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.h | 18 |
2 files changed, 109 insertions, 42 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 2fb53af8de2a..a487f414960e 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * 2 of the License, or (at your option) any later version. | 10 | * 2 of the License, or (at your option) any later version. |
11 | * | 11 | * |
12 | * FILE : megaraid_sas.c | 12 | * FILE : megaraid_sas.c |
13 | * Version : v00.00.02.01 | 13 | * Version : v00.00.02.02 |
14 | * | 14 | * |
15 | * Authors: | 15 | * Authors: |
16 | * Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com> | 16 | * Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com> |
@@ -55,13 +55,13 @@ static struct pci_device_id megasas_pci_table[] = { | |||
55 | 55 | ||
56 | { | 56 | { |
57 | PCI_VENDOR_ID_LSI_LOGIC, | 57 | PCI_VENDOR_ID_LSI_LOGIC, |
58 | PCI_DEVICE_ID_LSI_SAS1064R, | 58 | PCI_DEVICE_ID_LSI_SAS1064R, // xscale IOP |
59 | PCI_ANY_ID, | 59 | PCI_ANY_ID, |
60 | PCI_ANY_ID, | 60 | PCI_ANY_ID, |
61 | }, | 61 | }, |
62 | { | 62 | { |
63 | PCI_VENDOR_ID_DELL, | 63 | PCI_VENDOR_ID_DELL, |
64 | PCI_DEVICE_ID_DELL_PERC5, | 64 | PCI_DEVICE_ID_DELL_PERC5, // xscale IOP |
65 | PCI_ANY_ID, | 65 | PCI_ANY_ID, |
66 | PCI_ANY_ID, | 66 | PCI_ANY_ID, |
67 | }, | 67 | }, |
@@ -119,12 +119,18 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) | |||
119 | spin_unlock_irqrestore(&instance->cmd_pool_lock, flags); | 119 | spin_unlock_irqrestore(&instance->cmd_pool_lock, flags); |
120 | } | 120 | } |
121 | 121 | ||
122 | |||
123 | /** | ||
124 | * The following functions are defined for xscale | ||
125 | * (deviceid : 1064R, PERC5) controllers | ||
126 | */ | ||
127 | |||
122 | /** | 128 | /** |
123 | * megasas_enable_intr - Enables interrupts | 129 | * megasas_enable_intr_xscale - Enables interrupts |
124 | * @regs: MFI register set | 130 | * @regs: MFI register set |
125 | */ | 131 | */ |
126 | static inline void | 132 | static inline void |
127 | megasas_enable_intr(struct megasas_register_set __iomem * regs) | 133 | megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs) |
128 | { | 134 | { |
129 | writel(1, &(regs)->outbound_intr_mask); | 135 | writel(1, &(regs)->outbound_intr_mask); |
130 | 136 | ||
@@ -133,13 +139,73 @@ megasas_enable_intr(struct megasas_register_set __iomem * regs) | |||
133 | } | 139 | } |
134 | 140 | ||
135 | /** | 141 | /** |
142 | * megasas_read_fw_status_reg_xscale - returns the current FW status value | ||
143 | * @regs: MFI register set | ||
144 | */ | ||
145 | static u32 | ||
146 | megasas_read_fw_status_reg_xscale(struct megasas_register_set __iomem * regs) | ||
147 | { | ||
148 | return readl(&(regs)->outbound_msg_0); | ||
149 | } | ||
150 | /** | ||
151 | * megasas_clear_interrupt_xscale - Check & clear interrupt | ||
152 | * @regs: MFI register set | ||
153 | */ | ||
154 | static int | ||
155 | megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs) | ||
156 | { | ||
157 | u32 status; | ||
158 | /* | ||
159 | * Check if it is our interrupt | ||
160 | */ | ||
161 | status = readl(®s->outbound_intr_status); | ||
162 | |||
163 | if (!(status & MFI_OB_INTR_STATUS_MASK)) { | ||
164 | return 1; | ||
165 | } | ||
166 | |||
167 | /* | ||
168 | * Clear the interrupt by writing back the same value | ||
169 | */ | ||
170 | writel(status, ®s->outbound_intr_status); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * megasas_fire_cmd_xscale - Sends command to the FW | ||
177 | * @frame_phys_addr : Physical address of cmd | ||
178 | * @frame_count : Number of frames for the command | ||
179 | * @regs : MFI register set | ||
180 | */ | ||
181 | static inline void | ||
182 | megasas_fire_cmd_xscale(dma_addr_t frame_phys_addr,u32 frame_count, struct megasas_register_set __iomem *regs) | ||
183 | { | ||
184 | writel((frame_phys_addr >> 3)|(frame_count), | ||
185 | &(regs)->inbound_queue_port); | ||
186 | } | ||
187 | |||
188 | static struct megasas_instance_template megasas_instance_template_xscale = { | ||
189 | |||
190 | .fire_cmd = megasas_fire_cmd_xscale, | ||
191 | .enable_intr = megasas_enable_intr_xscale, | ||
192 | .clear_intr = megasas_clear_intr_xscale, | ||
193 | .read_fw_status_reg = megasas_read_fw_status_reg_xscale, | ||
194 | }; | ||
195 | |||
196 | /** | ||
197 | * This is the end of set of functions & definitions specific | ||
198 | * to xscale (deviceid : 1064R, PERC5) controllers | ||
199 | */ | ||
200 | |||
201 | /** | ||
136 | * megasas_disable_intr - Disables interrupts | 202 | * megasas_disable_intr - Disables interrupts |
137 | * @regs: MFI register set | 203 | * @regs: MFI register set |
138 | */ | 204 | */ |
139 | static inline void | 205 | static inline void |
140 | megasas_disable_intr(struct megasas_register_set __iomem * regs) | 206 | megasas_disable_intr(struct megasas_register_set __iomem * regs) |
141 | { | 207 | { |
142 | u32 mask = readl(®s->outbound_intr_mask) & (~0x00000001); | 208 | u32 mask = 0x1f; |
143 | writel(mask, ®s->outbound_intr_mask); | 209 | writel(mask, ®s->outbound_intr_mask); |
144 | 210 | ||
145 | /* Dummy readl to force pci flush */ | 211 | /* Dummy readl to force pci flush */ |
@@ -167,8 +233,7 @@ megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) | |||
167 | /* | 233 | /* |
168 | * Issue the frame using inbound queue port | 234 | * Issue the frame using inbound queue port |
169 | */ | 235 | */ |
170 | writel(cmd->frame_phys_addr >> 3, | 236 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); |
171 | &instance->reg_set->inbound_queue_port); | ||
172 | 237 | ||
173 | /* | 238 | /* |
174 | * Wait for cmd_status to change | 239 | * Wait for cmd_status to change |
@@ -198,8 +263,7 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance, | |||
198 | { | 263 | { |
199 | cmd->cmd_status = ENODATA; | 264 | cmd->cmd_status = ENODATA; |
200 | 265 | ||
201 | writel(cmd->frame_phys_addr >> 3, | 266 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); |
202 | &instance->reg_set->inbound_queue_port); | ||
203 | 267 | ||
204 | wait_event(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA)); | 268 | wait_event(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA)); |
205 | 269 | ||
@@ -242,8 +306,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, | |||
242 | cmd->sync_cmd = 1; | 306 | cmd->sync_cmd = 1; |
243 | cmd->cmd_status = 0xFF; | 307 | cmd->cmd_status = 0xFF; |
244 | 308 | ||
245 | writel(cmd->frame_phys_addr >> 3, | 309 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); |
246 | &instance->reg_set->inbound_queue_port); | ||
247 | 310 | ||
248 | /* | 311 | /* |
249 | * Wait for this cmd to complete | 312 | * Wait for this cmd to complete |
@@ -633,8 +696,7 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) | |||
633 | instance->fw_outstanding++; | 696 | instance->fw_outstanding++; |
634 | spin_unlock_irqrestore(&instance->instance_lock, flags); | 697 | spin_unlock_irqrestore(&instance->instance_lock, flags); |
635 | 698 | ||
636 | writel(((cmd->frame_phys_addr >> 3) | (cmd->frame_count - 1)), | 699 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set); |
637 | &instance->reg_set->inbound_queue_port); | ||
638 | 700 | ||
639 | return 0; | 701 | return 0; |
640 | 702 | ||
@@ -1045,7 +1107,6 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, | |||
1045 | static int | 1107 | static int |
1046 | megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) | 1108 | megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) |
1047 | { | 1109 | { |
1048 | u32 status; | ||
1049 | u32 producer; | 1110 | u32 producer; |
1050 | u32 consumer; | 1111 | u32 consumer; |
1051 | u32 context; | 1112 | u32 context; |
@@ -1053,17 +1114,10 @@ megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) | |||
1053 | 1114 | ||
1054 | /* | 1115 | /* |
1055 | * Check if it is our interrupt | 1116 | * Check if it is our interrupt |
1117 | * Clear the interrupt | ||
1056 | */ | 1118 | */ |
1057 | status = readl(&instance->reg_set->outbound_intr_status); | 1119 | if(instance->instancet->clear_intr(instance->reg_set)) |
1058 | |||
1059 | if (!(status & MFI_OB_INTR_STATUS_MASK)) { | ||
1060 | return IRQ_NONE; | 1120 | return IRQ_NONE; |
1061 | } | ||
1062 | |||
1063 | /* | ||
1064 | * Clear the interrupt by writing back the same value | ||
1065 | */ | ||
1066 | writel(status, &instance->reg_set->outbound_intr_status); | ||
1067 | 1121 | ||
1068 | producer = *instance->producer; | 1122 | producer = *instance->producer; |
1069 | consumer = *instance->consumer; | 1123 | consumer = *instance->consumer; |
@@ -1097,7 +1151,7 @@ static irqreturn_t megasas_isr(int irq, void *devp, struct pt_regs *regs) | |||
1097 | 1151 | ||
1098 | /** | 1152 | /** |
1099 | * megasas_transition_to_ready - Move the FW to READY state | 1153 | * megasas_transition_to_ready - Move the FW to READY state |
1100 | * @reg_set: MFI register set | 1154 | * @instance: Adapter soft state |
1101 | * | 1155 | * |
1102 | * During the initialization, FW passes can potentially be in any one of | 1156 | * During the initialization, FW passes can potentially be in any one of |
1103 | * several possible states. If the FW in operational, waiting-for-handshake | 1157 | * several possible states. If the FW in operational, waiting-for-handshake |
@@ -1105,14 +1159,14 @@ static irqreturn_t megasas_isr(int irq, void *devp, struct pt_regs *regs) | |||
1105 | * has to wait for the ready state. | 1159 | * has to wait for the ready state. |
1106 | */ | 1160 | */ |
1107 | static int | 1161 | static int |
1108 | megasas_transition_to_ready(struct megasas_register_set __iomem * reg_set) | 1162 | megasas_transition_to_ready(struct megasas_instance* instance) |
1109 | { | 1163 | { |
1110 | int i; | 1164 | int i; |
1111 | u8 max_wait; | 1165 | u8 max_wait; |
1112 | u32 fw_state; | 1166 | u32 fw_state; |
1113 | u32 cur_state; | 1167 | u32 cur_state; |
1114 | 1168 | ||
1115 | fw_state = readl(®_set->outbound_msg_0) & MFI_STATE_MASK; | 1169 | fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK; |
1116 | 1170 | ||
1117 | while (fw_state != MFI_STATE_READY) { | 1171 | while (fw_state != MFI_STATE_READY) { |
1118 | 1172 | ||
@@ -1130,7 +1184,7 @@ megasas_transition_to_ready(struct megasas_register_set __iomem * reg_set) | |||
1130 | * Set the CLR bit in inbound doorbell | 1184 | * Set the CLR bit in inbound doorbell |
1131 | */ | 1185 | */ |
1132 | writel(MFI_INIT_CLEAR_HANDSHAKE, | 1186 | writel(MFI_INIT_CLEAR_HANDSHAKE, |
1133 | ®_set->inbound_doorbell); | 1187 | &instance->reg_set->inbound_doorbell); |
1134 | 1188 | ||
1135 | max_wait = 2; | 1189 | max_wait = 2; |
1136 | cur_state = MFI_STATE_WAIT_HANDSHAKE; | 1190 | cur_state = MFI_STATE_WAIT_HANDSHAKE; |
@@ -1140,8 +1194,8 @@ megasas_transition_to_ready(struct megasas_register_set __iomem * reg_set) | |||
1140 | /* | 1194 | /* |
1141 | * Bring it to READY state; assuming max wait 2 secs | 1195 | * Bring it to READY state; assuming max wait 2 secs |
1142 | */ | 1196 | */ |
1143 | megasas_disable_intr(reg_set); | 1197 | megasas_disable_intr(instance->reg_set); |
1144 | writel(MFI_INIT_READY, ®_set->inbound_doorbell); | 1198 | writel(MFI_INIT_READY, &instance->reg_set->inbound_doorbell); |
1145 | 1199 | ||
1146 | max_wait = 10; | 1200 | max_wait = 10; |
1147 | cur_state = MFI_STATE_OPERATIONAL; | 1201 | cur_state = MFI_STATE_OPERATIONAL; |
@@ -1190,8 +1244,8 @@ megasas_transition_to_ready(struct megasas_register_set __iomem * reg_set) | |||
1190 | * The cur_state should not last for more than max_wait secs | 1244 | * The cur_state should not last for more than max_wait secs |
1191 | */ | 1245 | */ |
1192 | for (i = 0; i < (max_wait * 1000); i++) { | 1246 | for (i = 0; i < (max_wait * 1000); i++) { |
1193 | fw_state = MFI_STATE_MASK & | 1247 | fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & |
1194 | readl(®_set->outbound_msg_0); | 1248 | MFI_STATE_MASK ; |
1195 | 1249 | ||
1196 | if (fw_state == cur_state) { | 1250 | if (fw_state == cur_state) { |
1197 | msleep(1); | 1251 | msleep(1); |
@@ -1553,18 +1607,20 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
1553 | 1607 | ||
1554 | reg_set = instance->reg_set; | 1608 | reg_set = instance->reg_set; |
1555 | 1609 | ||
1610 | instance->instancet = &megasas_instance_template_xscale; | ||
1611 | |||
1556 | /* | 1612 | /* |
1557 | * We expect the FW state to be READY | 1613 | * We expect the FW state to be READY |
1558 | */ | 1614 | */ |
1559 | if (megasas_transition_to_ready(instance->reg_set)) | 1615 | if (megasas_transition_to_ready(instance)) |
1560 | goto fail_ready_state; | 1616 | goto fail_ready_state; |
1561 | 1617 | ||
1562 | /* | 1618 | /* |
1563 | * Get various operational parameters from status register | 1619 | * Get various operational parameters from status register |
1564 | */ | 1620 | */ |
1565 | instance->max_fw_cmds = readl(®_set->outbound_msg_0) & 0x00FFFF; | 1621 | instance->max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF; |
1566 | instance->max_num_sge = (readl(®_set->outbound_msg_0) & 0xFF0000) >> | 1622 | instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >> |
1567 | 0x10; | 1623 | 0x10; |
1568 | /* | 1624 | /* |
1569 | * Create a pool of commands | 1625 | * Create a pool of commands |
1570 | */ | 1626 | */ |
@@ -1873,8 +1929,7 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, | |||
1873 | /* | 1929 | /* |
1874 | * Issue the aen registration frame | 1930 | * Issue the aen registration frame |
1875 | */ | 1931 | */ |
1876 | writel(cmd->frame_phys_addr >> 3, | 1932 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); |
1877 | &instance->reg_set->inbound_queue_port); | ||
1878 | 1933 | ||
1879 | return 0; | 1934 | return 0; |
1880 | } | 1935 | } |
@@ -2063,7 +2118,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2063 | goto fail_irq; | 2118 | goto fail_irq; |
2064 | } | 2119 | } |
2065 | 2120 | ||
2066 | megasas_enable_intr(instance->reg_set); | 2121 | instance->instancet->enable_intr(instance->reg_set); |
2067 | 2122 | ||
2068 | /* | 2123 | /* |
2069 | * Store instance in PCI softstate | 2124 | * Store instance in PCI softstate |
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 67e07d30258f..d6d166c0663f 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h | |||
@@ -18,9 +18,9 @@ | |||
18 | /** | 18 | /** |
19 | * MegaRAID SAS Driver meta data | 19 | * MegaRAID SAS Driver meta data |
20 | */ | 20 | */ |
21 | #define MEGASAS_VERSION "00.00.02.01" | 21 | #define MEGASAS_VERSION "00.00.02.02" |
22 | #define MEGASAS_RELDATE "Dec 19, 2005" | 22 | #define MEGASAS_RELDATE "Jan 23, 2006" |
23 | #define MEGASAS_EXT_VERSION "Mon Dec 19 14:36:26 PST 2005" | 23 | #define MEGASAS_EXT_VERSION "Mon Jan 23 14:09:01 PST 2006" |
24 | /* | 24 | /* |
25 | * ===================================== | 25 | * ===================================== |
26 | * MegaRAID SAS MFI firmware definitions | 26 | * MegaRAID SAS MFI firmware definitions |
@@ -1012,6 +1012,16 @@ struct megasas_evt_detail { | |||
1012 | 1012 | ||
1013 | } __attribute__ ((packed)); | 1013 | } __attribute__ ((packed)); |
1014 | 1014 | ||
1015 | struct megasas_instance_template { | ||
1016 | void (*fire_cmd)(dma_addr_t ,u32 ,struct megasas_register_set __iomem *); | ||
1017 | |||
1018 | void (*enable_intr)(struct megasas_register_set __iomem *) ; | ||
1019 | |||
1020 | int (*clear_intr)(struct megasas_register_set __iomem *); | ||
1021 | |||
1022 | u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *); | ||
1023 | }; | ||
1024 | |||
1015 | struct megasas_instance { | 1025 | struct megasas_instance { |
1016 | 1026 | ||
1017 | u32 *producer; | 1027 | u32 *producer; |
@@ -1055,6 +1065,8 @@ struct megasas_instance { | |||
1055 | u32 fw_outstanding; | 1065 | u32 fw_outstanding; |
1056 | u32 hw_crit_error; | 1066 | u32 hw_crit_error; |
1057 | spinlock_t instance_lock; | 1067 | spinlock_t instance_lock; |
1068 | |||
1069 | struct megasas_instance_template *instancet; | ||
1058 | }; | 1070 | }; |
1059 | 1071 | ||
1060 | #define MEGASAS_IS_LOGICAL(scp) \ | 1072 | #define MEGASAS_IS_LOGICAL(scp) \ |