diff options
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas.c')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.c | 133 |
1 files changed, 94 insertions, 39 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 |