aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/megaraid/megaraid_sas.c
diff options
context:
space:
mode:
authorSumant Patro <sumantp@lsil.com>2006-01-25 15:02:40 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2006-01-29 12:25:30 -0500
commit1341c939222f4d1cc8d9eb2b794f26f089fe0a61 (patch)
treeacafd546c590b8661f9f67b9a293f7742e50bd7c /drivers/scsi/megaraid/megaraid_sas.c
parentcb59aa6a7ca1ae40fd436c45dff568a83f3fab2f (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/scsi/megaraid/megaraid_sas.c')
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c133
1 files changed, 94 insertions, 39 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 2fb53af8de2..a487f414960 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 */
126static inline void 132static inline void
127megasas_enable_intr(struct megasas_register_set __iomem * regs) 133megasas_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 */
145static u32
146megasas_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 */
154static int
155megasas_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(&regs->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, &regs->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 */
181static inline void
182megasas_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
188static 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 */
139static inline void 205static inline void
140megasas_disable_intr(struct megasas_register_set __iomem * regs) 206megasas_disable_intr(struct megasas_register_set __iomem * regs)
141{ 207{
142 u32 mask = readl(&regs->outbound_intr_mask) & (~0x00000001); 208 u32 mask = 0x1f;
143 writel(mask, &regs->outbound_intr_mask); 209 writel(mask, &regs->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,
1045static int 1107static int
1046megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) 1108megasas_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 */
1107static int 1161static int
1108megasas_transition_to_ready(struct megasas_register_set __iomem * reg_set) 1162megasas_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(&reg_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 &reg_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, &reg_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(&reg_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(&reg_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(&reg_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