diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_mbx.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 984 |
1 files changed, 755 insertions, 229 deletions
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index f3720fa0adbf..ab361be003d3 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -58,9 +58,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
58 | { | 58 | { |
59 | int rval; | 59 | int rval; |
60 | unsigned long flags = 0; | 60 | unsigned long flags = 0; |
61 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | 61 | device_reg_t __iomem *reg = ha->iobase; |
62 | struct timer_list tmp_intr_timer; | 62 | struct timer_list tmp_intr_timer; |
63 | uint8_t abort_active = test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); | 63 | uint8_t abort_active; |
64 | uint8_t io_lock_on = ha->flags.init_done; | 64 | uint8_t io_lock_on = ha->flags.init_done; |
65 | uint16_t command; | 65 | uint16_t command; |
66 | uint16_t *iptr; | 66 | uint16_t *iptr; |
@@ -71,19 +71,20 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
71 | unsigned long wait_time; | 71 | unsigned long wait_time; |
72 | 72 | ||
73 | rval = QLA_SUCCESS; | 73 | rval = QLA_SUCCESS; |
74 | abort_active = test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); | ||
75 | |||
76 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) | ||
74 | 77 | ||
75 | DEBUG11(printk("qla2x00_mailbox_command(%ld): entered.\n", | ||
76 | ha->host_no);) | ||
77 | /* | 78 | /* |
78 | * Wait for active mailbox commands to finish by waiting at most | 79 | * Wait for active mailbox commands to finish by waiting at most tov |
79 | * tov seconds. This is to serialize actual issuing of mailbox cmds | 80 | * seconds. This is to serialize actual issuing of mailbox cmds during |
80 | * during non ISP abort time. | 81 | * non ISP abort time. |
81 | */ | 82 | */ |
82 | if (!abort_active) { | 83 | if (!abort_active) { |
83 | if (qla2x00_down_timeout(&ha->mbx_cmd_sem, mcp->tov * HZ)) { | 84 | if (qla2x00_down_timeout(&ha->mbx_cmd_sem, mcp->tov * HZ)) { |
84 | /* Timeout occurred. Return error. */ | 85 | /* Timeout occurred. Return error. */ |
85 | DEBUG2_3_11(printk("qla2x00_mailbox_command(%ld): cmd " | 86 | DEBUG2_3_11(printk("%s(%ld): cmd access timeout. " |
86 | "access timeout. Exiting.\n", ha->host_no);) | 87 | "Exiting.\n", __func__, ha->host_no);) |
87 | return QLA_FUNCTION_TIMEOUT; | 88 | return QLA_FUNCTION_TIMEOUT; |
88 | } | 89 | } |
89 | } | 90 | } |
@@ -96,13 +97,16 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
96 | if (!abort_active) | 97 | if (!abort_active) |
97 | spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags); | 98 | spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags); |
98 | 99 | ||
99 | DEBUG11(printk("scsi%d: prepare to issue mbox cmd=0x%x.\n", | 100 | DEBUG11(printk("scsi(%ld): prepare to issue mbox cmd=0x%x.\n", |
100 | (int)ha->host_no, mcp->mb[0]);) | 101 | ha->host_no, mcp->mb[0]);) |
101 | 102 | ||
102 | spin_lock_irqsave(&ha->hardware_lock, flags); | 103 | spin_lock_irqsave(&ha->hardware_lock, flags); |
103 | 104 | ||
104 | /* Load mailbox registers. */ | 105 | /* Load mailbox registers. */ |
105 | optr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 0); | 106 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) |
107 | optr = (uint16_t __iomem *)®->isp24.mailbox0; | ||
108 | else | ||
109 | optr = (uint16_t __iomem *)MAILBOX_REG(ha, ®->isp, 0); | ||
106 | 110 | ||
107 | iptr = mcp->mb; | 111 | iptr = mcp->mb; |
108 | command = mcp->mb[0]; | 112 | command = mcp->mb[0]; |
@@ -110,7 +114,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
110 | 114 | ||
111 | for (cnt = 0; cnt < ha->mbx_count; cnt++) { | 115 | for (cnt = 0; cnt < ha->mbx_count; cnt++) { |
112 | if (IS_QLA2200(ha) && cnt == 8) | 116 | if (IS_QLA2200(ha) && cnt == 8) |
113 | optr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 8); | 117 | optr = |
118 | (uint16_t __iomem *)MAILBOX_REG(ha, ®->isp, 8); | ||
114 | if (mboxes & BIT_0) | 119 | if (mboxes & BIT_0) |
115 | WRT_REG_WORD(optr, *iptr); | 120 | WRT_REG_WORD(optr, *iptr); |
116 | 121 | ||
@@ -120,16 +125,15 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
120 | } | 125 | } |
121 | 126 | ||
122 | #if defined(QL_DEBUG_LEVEL_1) | 127 | #if defined(QL_DEBUG_LEVEL_1) |
123 | printk("qla2x00_mailbox_command: Loaded MBX registers " | 128 | printk("%s(%ld): Loaded MBX registers (displayed in bytes) = \n", |
124 | "(displayed in bytes) = \n"); | 129 | __func__, ha->host_no); |
125 | qla2x00_dump_buffer((uint8_t *)mcp->mb, 16); | 130 | qla2x00_dump_buffer((uint8_t *)mcp->mb, 16); |
126 | printk("\n"); | 131 | printk("\n"); |
127 | qla2x00_dump_buffer(((uint8_t *)mcp->mb + 0x10), 16); | 132 | qla2x00_dump_buffer(((uint8_t *)mcp->mb + 0x10), 16); |
128 | printk("\n"); | 133 | printk("\n"); |
129 | qla2x00_dump_buffer(((uint8_t *)mcp->mb + 0x20), 8); | 134 | qla2x00_dump_buffer(((uint8_t *)mcp->mb + 0x20), 8); |
130 | printk("\n"); | 135 | printk("\n"); |
131 | printk("qla2x00_mailbox_command: I/O address = %lx.\n", | 136 | printk("%s(%ld): I/O address = %p.\n", __func__, ha->host_no, optr); |
132 | (u_long)optr); | ||
133 | qla2x00_dump_regs(ha); | 137 | qla2x00_dump_regs(ha); |
134 | #endif | 138 | #endif |
135 | 139 | ||
@@ -138,17 +142,15 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
138 | clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | 142 | clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); |
139 | 143 | ||
140 | /* Unlock mbx registers and wait for interrupt */ | 144 | /* Unlock mbx registers and wait for interrupt */ |
141 | 145 | DEBUG11(printk("%s(%ld): going to unlock irq & waiting for interrupt. " | |
142 | DEBUG11(printk("qla2x00_mailbox_command: going to unlock irq & " | 146 | "jiffies=%lx.\n", __func__, ha->host_no, jiffies);) |
143 | "waiting for interrupt. jiffies=%lx.\n", jiffies);) | ||
144 | 147 | ||
145 | /* Wait for mbx cmd completion until timeout */ | 148 | /* Wait for mbx cmd completion until timeout */ |
146 | 149 | ||
147 | if (!abort_active && io_lock_on) { | 150 | if (!abort_active && io_lock_on) { |
148 | /* sleep on completion semaphore */ | 151 | /* sleep on completion semaphore */ |
149 | DEBUG11(printk("qla2x00_mailbox_command(%ld): " | 152 | DEBUG11(printk("%s(%ld): INTERRUPT MODE. Initializing timer.\n", |
150 | "INTERRUPT MODE. Initializing timer.\n", | 153 | __func__, ha->host_no);) |
151 | ha->host_no);) | ||
152 | 154 | ||
153 | init_timer(&tmp_intr_timer); | 155 | init_timer(&tmp_intr_timer); |
154 | tmp_intr_timer.data = (unsigned long)&ha->mbx_intr_sem; | 156 | tmp_intr_timer.data = (unsigned long)&ha->mbx_intr_sem; |
@@ -156,16 +158,19 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
156 | tmp_intr_timer.function = | 158 | tmp_intr_timer.function = |
157 | (void (*)(unsigned long))qla2x00_mbx_sem_timeout; | 159 | (void (*)(unsigned long))qla2x00_mbx_sem_timeout; |
158 | 160 | ||
159 | DEBUG11(printk("qla2x00_mailbox_command(%ld): " | 161 | DEBUG11(printk("%s(%ld): Adding timer.\n", __func__, |
160 | "Adding timer.\n", ha->host_no);) | 162 | ha->host_no);) |
161 | add_timer(&tmp_intr_timer); | 163 | add_timer(&tmp_intr_timer); |
162 | 164 | ||
163 | DEBUG11(printk("qla2x00_mailbox_command: going to " | 165 | DEBUG11(printk("%s(%ld): going to unlock & sleep. " |
164 | "unlock & sleep. time=0x%lx.\n", jiffies);) | 166 | "time=0x%lx.\n", __func__, ha->host_no, jiffies);) |
165 | 167 | ||
166 | set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); | 168 | set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); |
167 | 169 | ||
168 | WRT_REG_WORD(®->hccr, HCCR_SET_HOST_INT); | 170 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) |
171 | WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); | ||
172 | else | ||
173 | WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); | ||
169 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 174 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
170 | 175 | ||
171 | if (!abort_active) | 176 | if (!abort_active) |
@@ -176,19 +181,20 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
176 | */ | 181 | */ |
177 | down(&ha->mbx_intr_sem); | 182 | down(&ha->mbx_intr_sem); |
178 | 183 | ||
179 | DEBUG11(printk("qla2x00_mailbox_command:" | 184 | DEBUG11(printk("%s(%ld): waking up. time=0x%lx\n", __func__, |
180 | "waking up." | 185 | ha->host_no, jiffies);) |
181 | "time=0x%lx\n", jiffies);) | ||
182 | clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); | 186 | clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); |
183 | 187 | ||
184 | /* delete the timer */ | 188 | /* delete the timer */ |
185 | del_timer(&tmp_intr_timer); | 189 | del_timer(&tmp_intr_timer); |
186 | } else { | 190 | } else { |
191 | DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__, | ||
192 | ha->host_no, command);) | ||
187 | 193 | ||
188 | DEBUG3_11(printk("qla2x00_mailbox_command(%ld): cmd=%x " | 194 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) |
189 | "POLLING MODE.\n", ha->host_no, command);) | 195 | WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); |
190 | 196 | else | |
191 | WRT_REG_WORD(®->hccr, HCCR_SET_HOST_INT); | 197 | WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); |
192 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 198 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
193 | if (!abort_active) | 199 | if (!abort_active) |
194 | spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags); | 200 | spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags); |
@@ -212,8 +218,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
212 | if (ha->flags.mbox_int) { | 218 | if (ha->flags.mbox_int) { |
213 | uint16_t *iptr2; | 219 | uint16_t *iptr2; |
214 | 220 | ||
215 | DEBUG3_11(printk("qla2x00_mailbox_cmd: cmd %x completed.\n", | 221 | DEBUG3_11(printk("%s(%ld): cmd %x completed.\n", __func__, |
216 | command);) | 222 | ha->host_no, command);) |
217 | 223 | ||
218 | /* Got interrupt. Clear the flag. */ | 224 | /* Got interrupt. Clear the flag. */ |
219 | ha->flags.mbox_int = 0; | 225 | ha->flags.mbox_int = 0; |
@@ -238,12 +244,22 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
238 | 244 | ||
239 | #if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) || \ | 245 | #if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) || \ |
240 | defined(QL_DEBUG_LEVEL_11) | 246 | defined(QL_DEBUG_LEVEL_11) |
241 | printk("qla2x00_mailbox_command(%ld): **** MB Command Timeout " | 247 | uint16_t mb0; |
242 | "for cmd %x ****\n", ha->host_no, command); | 248 | uint32_t ictrl; |
243 | printk("qla2x00_mailbox_command: icontrol=%x jiffies=%lx\n", | 249 | |
244 | RD_REG_WORD(®->ictrl), jiffies); | 250 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { |
245 | printk("qla2x00_mailbox_command: *** mailbox[0] = 0x%x ***\n", | 251 | mb0 = RD_REG_WORD(®->isp24.mailbox0); |
246 | RD_REG_WORD(optr)); | 252 | ictrl = RD_REG_DWORD(®->isp24.ictrl); |
253 | } else { | ||
254 | mb0 = RD_MAILBOX_REG(ha, reg->isp, 0); | ||
255 | ictrl = RD_REG_WORD(®->isp.ictrl); | ||
256 | } | ||
257 | printk("%s(%ld): **** MB Command Timeout for cmd %x ****\n", | ||
258 | __func__, ha->host_no, command); | ||
259 | printk("%s(%ld): icontrol=%x jiffies=%lx\n", __func__, | ||
260 | ha->host_no, ictrl, jiffies); | ||
261 | printk("%s(%ld): *** mailbox[0] = 0x%x ***\n", __func__, | ||
262 | ha->host_no, mb0); | ||
247 | qla2x00_dump_regs(ha); | 263 | qla2x00_dump_regs(ha); |
248 | #endif | 264 | #endif |
249 | 265 | ||
@@ -259,22 +275,21 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
259 | ha->mcp = NULL; | 275 | ha->mcp = NULL; |
260 | 276 | ||
261 | if (!abort_active) { | 277 | if (!abort_active) { |
262 | DEBUG11(printk("qla2x00_mailbox_cmd: checking for additional " | 278 | DEBUG11(printk("%s(%ld): checking for additional resp " |
263 | "resp interrupt.\n");) | 279 | "interrupt.\n", __func__, ha->host_no);) |
264 | 280 | ||
265 | /* polling mode for non isp_abort commands. */ | 281 | /* polling mode for non isp_abort commands. */ |
266 | qla2x00_poll(ha); | 282 | qla2x00_poll(ha); |
267 | } | 283 | } |
268 | 284 | ||
269 | if (rval == QLA_FUNCTION_TIMEOUT) { | 285 | if (rval == QLA_FUNCTION_TIMEOUT && |
286 | mcp->mb[0] != MBC_GEN_SYSTEM_ERROR) { | ||
270 | if (!io_lock_on || (mcp->flags & IOCTL_CMD)) { | 287 | if (!io_lock_on || (mcp->flags & IOCTL_CMD)) { |
271 | /* not in dpc. schedule it for dpc to take over. */ | 288 | /* not in dpc. schedule it for dpc to take over. */ |
272 | DEBUG(printk("qla2x00_mailbox_command(%ld): timeout " | 289 | DEBUG(printk("%s(%ld): timeout schedule " |
273 | "schedule isp_abort_needed.\n", | 290 | "isp_abort_needed.\n", __func__, ha->host_no);) |
274 | ha->host_no);) | 291 | DEBUG2_3_11(printk("%s(%ld): timeout schedule " |
275 | DEBUG2_3_11(printk("qla2x00_mailbox_command(%ld): " | 292 | "isp_abort_needed.\n", __func__, ha->host_no);) |
276 | "timeout schedule isp_abort_needed.\n", | ||
277 | ha->host_no);) | ||
278 | qla_printk(KERN_WARNING, ha, | 293 | qla_printk(KERN_WARNING, ha, |
279 | "Mailbox command timeout occured. Scheduling ISP " | 294 | "Mailbox command timeout occured. Scheduling ISP " |
280 | "abort.\n"); | 295 | "abort.\n"); |
@@ -283,12 +298,11 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
283 | up(ha->dpc_wait); | 298 | up(ha->dpc_wait); |
284 | 299 | ||
285 | } else if (!abort_active) { | 300 | } else if (!abort_active) { |
286 | |||
287 | /* call abort directly since we are in the DPC thread */ | 301 | /* call abort directly since we are in the DPC thread */ |
288 | DEBUG(printk("qla2x00_mailbox_command(%ld): timeout " | 302 | DEBUG(printk("%s(%ld): timeout calling abort_isp\n", |
289 | "calling abort_isp\n", ha->host_no);) | 303 | __func__, ha->host_no);) |
290 | DEBUG2_3_11(printk("qla2x00_mailbox_command(%ld): " | 304 | DEBUG2_3_11(printk("%s(%ld): timeout calling " |
291 | "timeout calling abort_isp\n", ha->host_no);) | 305 | "abort_isp\n", __func__, ha->host_no);) |
292 | qla_printk(KERN_WARNING, ha, | 306 | qla_printk(KERN_WARNING, ha, |
293 | "Mailbox command timeout occured. Issuing ISP " | 307 | "Mailbox command timeout occured. Issuing ISP " |
294 | "abort.\n"); | 308 | "abort.\n"); |
@@ -296,15 +310,14 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
296 | set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); | 310 | set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); |
297 | clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | 311 | clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); |
298 | if (qla2x00_abort_isp(ha)) { | 312 | if (qla2x00_abort_isp(ha)) { |
299 | /* failed. retry later. */ | 313 | /* Failed. retry later. */ |
300 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | 314 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); |
301 | } | 315 | } |
302 | clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); | 316 | clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); |
303 | 317 | DEBUG(printk("%s(%ld): finished abort_isp\n", __func__, | |
304 | DEBUG(printk("qla2x00_mailbox_command: finished " | 318 | ha->host_no);) |
305 | "abort_isp\n");) | 319 | DEBUG2_3_11(printk("%s(%ld): finished abort_isp\n", |
306 | DEBUG2_3_11(printk("qla2x00_mailbox_command: finished " | 320 | __func__, ha->host_no);) |
307 | "abort_isp\n");) | ||
308 | } | 321 | } |
309 | } | 322 | } |
310 | 323 | ||
@@ -313,17 +326,13 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
313 | up(&ha->mbx_cmd_sem); | 326 | up(&ha->mbx_cmd_sem); |
314 | 327 | ||
315 | if (rval) { | 328 | if (rval) { |
316 | DEBUG2_3_11(printk("qla2x00_mailbox_command(%ld): **** FAILED. " | 329 | DEBUG2_3_11(printk("%s(%ld): **** FAILED. mbx0=%x, mbx1=%x, " |
317 | "mbx0=%x, mbx1=%x, mbx2=%x, cmd=%x ****\n", | 330 | "mbx2=%x, cmd=%x ****\n", __func__, ha->host_no, |
318 | ha->host_no, mcp->mb[0], mcp->mb[1], mcp->mb[2], command);) | 331 | mcp->mb[0], mcp->mb[1], mcp->mb[2], command);) |
319 | } else { | 332 | } else { |
320 | DEBUG11(printk("qla2x00_mailbox_command(%ld): done.\n", | 333 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);) |
321 | ha->host_no);) | ||
322 | } | 334 | } |
323 | 335 | ||
324 | DEBUG11(printk("qla2x00_mailbox_command(%ld): exiting.\n", | ||
325 | ha->host_no);) | ||
326 | |||
327 | return rval; | 336 | return rval; |
328 | } | 337 | } |
329 | 338 | ||
@@ -418,64 +427,40 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint16_t risc_addr, | |||
418 | */ | 427 | */ |
419 | int | 428 | int |
420 | qla2x00_load_ram_ext(scsi_qla_host_t *ha, dma_addr_t req_dma, | 429 | qla2x00_load_ram_ext(scsi_qla_host_t *ha, dma_addr_t req_dma, |
421 | uint32_t risc_addr, uint16_t risc_code_size) | 430 | uint32_t risc_addr, uint32_t risc_code_size) |
422 | { | 431 | { |
423 | int rval; | 432 | int rval; |
424 | mbx_cmd_t mc; | 433 | mbx_cmd_t mc; |
425 | mbx_cmd_t *mcp = &mc; | 434 | mbx_cmd_t *mcp = &mc; |
426 | uint32_t req_len; | ||
427 | dma_addr_t nml_dma; | ||
428 | uint32_t nml_len; | ||
429 | uint32_t normalized; | ||
430 | 435 | ||
431 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | 436 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); |
432 | 437 | ||
433 | req_len = risc_code_size; | ||
434 | nml_dma = 0; | ||
435 | nml_len = 0; | ||
436 | |||
437 | normalized = qla2x00_normalize_dma_addr(&req_dma, &req_len, &nml_dma, | ||
438 | &nml_len); | ||
439 | |||
440 | /* Load first segment */ | ||
441 | mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; | 438 | mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; |
442 | mcp->mb[1] = LSW(risc_addr); | 439 | mcp->mb[1] = LSW(risc_addr); |
443 | mcp->mb[2] = MSW(req_dma); | 440 | mcp->mb[2] = MSW(req_dma); |
444 | mcp->mb[3] = LSW(req_dma); | 441 | mcp->mb[3] = LSW(req_dma); |
445 | mcp->mb[4] = (uint16_t)req_len; | ||
446 | mcp->mb[6] = MSW(MSD(req_dma)); | 442 | mcp->mb[6] = MSW(MSD(req_dma)); |
447 | mcp->mb[7] = LSW(MSD(req_dma)); | 443 | mcp->mb[7] = LSW(MSD(req_dma)); |
448 | mcp->mb[8] = MSW(risc_addr); | 444 | mcp->mb[8] = MSW(risc_addr); |
449 | mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; | 445 | mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; |
446 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { | ||
447 | mcp->mb[4] = MSW(risc_code_size); | ||
448 | mcp->mb[5] = LSW(risc_code_size); | ||
449 | mcp->out_mb |= MBX_5|MBX_4; | ||
450 | } else { | ||
451 | mcp->mb[4] = LSW(risc_code_size); | ||
452 | mcp->out_mb |= MBX_4; | ||
453 | } | ||
454 | |||
450 | mcp->in_mb = MBX_0; | 455 | mcp->in_mb = MBX_0; |
451 | mcp->tov = 30; | 456 | mcp->tov = 30; |
452 | mcp->flags = 0; | 457 | mcp->flags = 0; |
453 | rval = qla2x00_mailbox_command(ha, mcp); | 458 | rval = qla2x00_mailbox_command(ha, mcp); |
454 | 459 | ||
455 | /* Load second segment - if necessary */ | ||
456 | if (normalized && (rval == QLA_SUCCESS)) { | ||
457 | risc_addr += req_len; | ||
458 | mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; | ||
459 | mcp->mb[1] = LSW(risc_addr); | ||
460 | mcp->mb[2] = MSW(nml_dma); | ||
461 | mcp->mb[3] = LSW(nml_dma); | ||
462 | mcp->mb[4] = (uint16_t)nml_len; | ||
463 | mcp->mb[6] = MSW(MSD(nml_dma)); | ||
464 | mcp->mb[7] = LSW(MSD(nml_dma)); | ||
465 | mcp->mb[8] = MSW(risc_addr); | ||
466 | mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; | ||
467 | mcp->in_mb = MBX_0; | ||
468 | mcp->tov = 30; | ||
469 | mcp->flags = 0; | ||
470 | rval = qla2x00_mailbox_command(ha, mcp); | ||
471 | } | ||
472 | |||
473 | if (rval != QLA_SUCCESS) { | 460 | if (rval != QLA_SUCCESS) { |
474 | /*EMPTY*/ | 461 | DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__, |
475 | DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", | 462 | ha->host_no, rval, mcp->mb[0])); |
476 | __func__, ha->host_no, rval, mcp->mb[0])); | ||
477 | } else { | 463 | } else { |
478 | /*EMPTY*/ | ||
479 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); | 464 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); |
480 | } | 465 | } |
481 | 466 | ||
@@ -484,42 +469,62 @@ qla2x00_load_ram_ext(scsi_qla_host_t *ha, dma_addr_t req_dma, | |||
484 | 469 | ||
485 | /* | 470 | /* |
486 | * qla2x00_execute_fw | 471 | * qla2x00_execute_fw |
487 | * Start adapter firmware. | 472 | * Start adapter firmware. |
488 | * | 473 | * |
489 | * Input: | 474 | * Input: |
490 | * ha = adapter block pointer. | 475 | * ha = adapter block pointer. |
491 | * TARGET_QUEUE_LOCK must be released. | 476 | * TARGET_QUEUE_LOCK must be released. |
492 | * ADAPTER_STATE_LOCK must be released. | 477 | * ADAPTER_STATE_LOCK must be released. |
493 | * | 478 | * |
494 | * Returns: | 479 | * Returns: |
495 | * qla2x00 local function return status code. | 480 | * qla2x00 local function return status code. |
496 | * | 481 | * |
497 | * Context: | 482 | * Context: |
498 | * Kernel context. | 483 | * Kernel context. |
499 | */ | 484 | */ |
500 | int | 485 | int |
501 | qla2x00_execute_fw(scsi_qla_host_t *ha) | 486 | qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr) |
502 | { | 487 | { |
503 | int rval; | 488 | int rval; |
504 | mbx_cmd_t mc; | 489 | mbx_cmd_t mc; |
505 | mbx_cmd_t *mcp = &mc; | 490 | mbx_cmd_t *mcp = &mc; |
506 | 491 | ||
507 | DEBUG11(printk("qla2x00_execute_fw(%ld): entered.\n", ha->host_no);) | 492 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) |
508 | 493 | ||
509 | mcp->mb[0] = MBC_EXECUTE_FIRMWARE; | 494 | mcp->mb[0] = MBC_EXECUTE_FIRMWARE; |
510 | mcp->mb[1] = *ha->brd_info->fw_info[0].fwstart; | 495 | mcp->out_mb = MBX_0; |
511 | mcp->out_mb = MBX_1|MBX_0; | 496 | mcp->in_mb = MBX_0; |
512 | if (IS_QLA2322(ha) || IS_QLA6322(ha)) { | 497 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { |
513 | mcp->mb[2] = 0; | 498 | mcp->mb[1] = MSW(risc_addr); |
514 | mcp->out_mb |= MBX_2; | 499 | mcp->mb[2] = LSW(risc_addr); |
500 | mcp->mb[3] = 0; | ||
501 | mcp->out_mb |= MBX_3|MBX_2|MBX_1; | ||
502 | mcp->in_mb |= MBX_1; | ||
503 | } else { | ||
504 | mcp->mb[1] = LSW(risc_addr); | ||
505 | mcp->out_mb |= MBX_1; | ||
506 | if (IS_QLA2322(ha) || IS_QLA6322(ha)) { | ||
507 | mcp->mb[2] = 0; | ||
508 | mcp->out_mb |= MBX_2; | ||
509 | } | ||
515 | } | 510 | } |
516 | 511 | ||
517 | mcp->in_mb = MBX_0; | ||
518 | mcp->tov = 30; | 512 | mcp->tov = 30; |
519 | mcp->flags = 0; | 513 | mcp->flags = 0; |
520 | rval = qla2x00_mailbox_command(ha, mcp); | 514 | rval = qla2x00_mailbox_command(ha, mcp); |
521 | 515 | ||
522 | DEBUG11(printk("qla2x00_execute_fw(%ld): done.\n", ha->host_no);) | 516 | if (rval != QLA_SUCCESS) { |
517 | DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__, | ||
518 | ha->host_no, rval, mcp->mb[0])); | ||
519 | } else { | ||
520 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { | ||
521 | DEBUG11(printk("%s(%ld): done exchanges=%x.\n", | ||
522 | __func__, ha->host_no, mcp->mb[1]);) | ||
523 | } else { | ||
524 | DEBUG11(printk("%s(%ld): done.\n", __func__, | ||
525 | ha->host_no);) | ||
526 | } | ||
527 | } | ||
523 | 528 | ||
524 | return rval; | 529 | return rval; |
525 | } | 530 | } |
@@ -612,6 +617,7 @@ qla2x00_get_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts) | |||
612 | DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, | 617 | DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, |
613 | ha->host_no, rval)); | 618 | ha->host_no, rval)); |
614 | } else { | 619 | } else { |
620 | fwopts[0] = mcp->mb[0]; | ||
615 | fwopts[1] = mcp->mb[1]; | 621 | fwopts[1] = mcp->mb[1]; |
616 | fwopts[2] = mcp->mb[2]; | 622 | fwopts[2] = mcp->mb[2]; |
617 | fwopts[3] = mcp->mb[3]; | 623 | fwopts[3] = mcp->mb[3]; |
@@ -650,19 +656,26 @@ qla2x00_set_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts) | |||
650 | mcp->mb[1] = fwopts[1]; | 656 | mcp->mb[1] = fwopts[1]; |
651 | mcp->mb[2] = fwopts[2]; | 657 | mcp->mb[2] = fwopts[2]; |
652 | mcp->mb[3] = fwopts[3]; | 658 | mcp->mb[3] = fwopts[3]; |
653 | mcp->mb[10] = fwopts[10]; | 659 | mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; |
654 | mcp->mb[11] = fwopts[11]; | ||
655 | mcp->mb[12] = 0; /* Undocumented, but used */ | ||
656 | mcp->out_mb = MBX_12|MBX_11|MBX_10|MBX_3|MBX_2|MBX_1|MBX_0; | ||
657 | mcp->in_mb = MBX_0; | 660 | mcp->in_mb = MBX_0; |
661 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { | ||
662 | mcp->in_mb |= MBX_1; | ||
663 | } else { | ||
664 | mcp->mb[10] = fwopts[10]; | ||
665 | mcp->mb[11] = fwopts[11]; | ||
666 | mcp->mb[12] = 0; /* Undocumented, but used */ | ||
667 | mcp->out_mb |= MBX_12|MBX_11|MBX_10; | ||
668 | } | ||
658 | mcp->tov = 30; | 669 | mcp->tov = 30; |
659 | mcp->flags = 0; | 670 | mcp->flags = 0; |
660 | rval = qla2x00_mailbox_command(ha, mcp); | 671 | rval = qla2x00_mailbox_command(ha, mcp); |
661 | 672 | ||
673 | fwopts[0] = mcp->mb[0]; | ||
674 | |||
662 | if (rval != QLA_SUCCESS) { | 675 | if (rval != QLA_SUCCESS) { |
663 | /*EMPTY*/ | 676 | /*EMPTY*/ |
664 | DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, | 677 | DEBUG2_3_11(printk("%s(%ld): failed=%x (%x/%x).\n", __func__, |
665 | ha->host_no, rval)); | 678 | ha->host_no, rval, mcp->mb[0], mcp->mb[1])); |
666 | } else { | 679 | } else { |
667 | /*EMPTY*/ | 680 | /*EMPTY*/ |
668 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); | 681 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); |
@@ -747,31 +760,38 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *ha) | |||
747 | * Kernel context. | 760 | * Kernel context. |
748 | */ | 761 | */ |
749 | int | 762 | int |
750 | qla2x00_verify_checksum(scsi_qla_host_t *ha) | 763 | qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr) |
751 | { | 764 | { |
752 | int rval; | 765 | int rval; |
753 | mbx_cmd_t mc; | 766 | mbx_cmd_t mc; |
754 | mbx_cmd_t *mcp = &mc; | 767 | mbx_cmd_t *mcp = &mc; |
755 | 768 | ||
756 | DEBUG11(printk("qla2x00_verify_checksum(%ld): entered.\n", | 769 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) |
757 | ha->host_no);) | ||
758 | 770 | ||
759 | mcp->mb[0] = MBC_VERIFY_CHECKSUM; | 771 | mcp->mb[0] = MBC_VERIFY_CHECKSUM; |
760 | mcp->mb[1] = *ha->brd_info->fw_info[0].fwstart; | 772 | mcp->out_mb = MBX_0; |
761 | mcp->out_mb = MBX_1|MBX_0; | 773 | mcp->in_mb = MBX_0; |
762 | mcp->in_mb = MBX_2|MBX_0; | 774 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { |
775 | mcp->mb[1] = MSW(risc_addr); | ||
776 | mcp->mb[2] = LSW(risc_addr); | ||
777 | mcp->out_mb |= MBX_2|MBX_1; | ||
778 | mcp->in_mb |= MBX_2|MBX_1; | ||
779 | } else { | ||
780 | mcp->mb[1] = LSW(risc_addr); | ||
781 | mcp->out_mb |= MBX_1; | ||
782 | mcp->in_mb |= MBX_1; | ||
783 | } | ||
784 | |||
763 | mcp->tov = 30; | 785 | mcp->tov = 30; |
764 | mcp->flags = 0; | 786 | mcp->flags = 0; |
765 | rval = qla2x00_mailbox_command(ha, mcp); | 787 | rval = qla2x00_mailbox_command(ha, mcp); |
766 | 788 | ||
767 | if (rval != QLA_SUCCESS) { | 789 | if (rval != QLA_SUCCESS) { |
768 | /*EMPTY*/ | 790 | DEBUG2_3_11(printk("%s(%ld): failed=%x chk sum=%x.\n", __func__, |
769 | DEBUG2_3_11(printk("qla2x00_verify_checksum(%ld): failed=%x.\n", | 791 | ha->host_no, rval, (IS_QLA24XX(ha) || IS_QLA25XX(ha) ? |
770 | ha->host_no, rval);) | 792 | (mcp->mb[2] << 16) | mcp->mb[1]: mcp->mb[1]));) |
771 | } else { | 793 | } else { |
772 | /*EMPTY*/ | 794 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);) |
773 | DEBUG11(printk("qla2x00_verify_checksum(%ld): done.\n", | ||
774 | ha->host_no);) | ||
775 | } | 795 | } |
776 | 796 | ||
777 | return rval; | 797 | return rval; |
@@ -817,10 +837,10 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr, | |||
817 | 837 | ||
818 | if (rval != QLA_SUCCESS) { | 838 | if (rval != QLA_SUCCESS) { |
819 | /*EMPTY*/ | 839 | /*EMPTY*/ |
820 | DEBUG(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x", | 840 | DEBUG(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x\n", |
821 | ha->host_no,rval);) | 841 | ha->host_no, rval);) |
822 | DEBUG2(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x", | 842 | DEBUG2(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x\n", |
823 | ha->host_no,rval);) | 843 | ha->host_no, rval);) |
824 | } else { | 844 | } else { |
825 | sts_entry_t *sts_entry = (sts_entry_t *) buffer; | 845 | sts_entry_t *sts_entry = (sts_entry_t *) buffer; |
826 | 846 | ||
@@ -922,41 +942,40 @@ qla2x00_abort_target(fc_port_t *fcport) | |||
922 | int rval; | 942 | int rval; |
923 | mbx_cmd_t mc; | 943 | mbx_cmd_t mc; |
924 | mbx_cmd_t *mcp = &mc; | 944 | mbx_cmd_t *mcp = &mc; |
945 | scsi_qla_host_t *ha; | ||
925 | 946 | ||
926 | DEBUG11(printk("qla2x00_abort_target(%ld): entered.\n", | 947 | if (fcport == NULL) |
927 | fcport->ha->host_no);) | ||
928 | |||
929 | if (fcport == NULL) { | ||
930 | /* no target to abort */ | ||
931 | return 0; | 948 | return 0; |
932 | } | ||
933 | 949 | ||
950 | DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no);) | ||
951 | |||
952 | ha = fcport->ha; | ||
934 | mcp->mb[0] = MBC_ABORT_TARGET; | 953 | mcp->mb[0] = MBC_ABORT_TARGET; |
935 | mcp->out_mb = MBX_2|MBX_1|MBX_0; | 954 | mcp->out_mb = MBX_2|MBX_1|MBX_0; |
936 | if (HAS_EXTENDED_IDS(fcport->ha)) { | 955 | if (HAS_EXTENDED_IDS(ha)) { |
937 | mcp->mb[1] = fcport->loop_id; | 956 | mcp->mb[1] = fcport->loop_id; |
938 | mcp->mb[10] = 0; | 957 | mcp->mb[10] = 0; |
939 | mcp->out_mb |= MBX_10; | 958 | mcp->out_mb |= MBX_10; |
940 | } else { | 959 | } else { |
941 | mcp->mb[1] = fcport->loop_id << 8; | 960 | mcp->mb[1] = fcport->loop_id << 8; |
942 | } | 961 | } |
943 | mcp->mb[2] = fcport->ha->loop_reset_delay; | 962 | mcp->mb[2] = ha->loop_reset_delay; |
944 | 963 | ||
945 | mcp->in_mb = MBX_0; | 964 | mcp->in_mb = MBX_0; |
946 | mcp->tov = 30; | 965 | mcp->tov = 30; |
947 | mcp->flags = 0; | 966 | mcp->flags = 0; |
948 | rval = qla2x00_mailbox_command(fcport->ha, mcp); | 967 | rval = qla2x00_mailbox_command(ha, mcp); |
949 | 968 | ||
950 | /* Issue marker command. */ | 969 | /* Issue marker command. */ |
951 | fcport->ha->marker_needed = 1; | 970 | ha->marker_needed = 1; |
952 | 971 | ||
953 | if (rval != QLA_SUCCESS) { | 972 | if (rval != QLA_SUCCESS) { |
954 | DEBUG2_3_11(printk("qla2x00_abort_target(%ld): failed=%x.\n", | 973 | DEBUG2_3_11(printk("qla2x00_abort_target(%ld): failed=%x.\n", |
955 | fcport->ha->host_no, rval);) | 974 | ha->host_no, rval);) |
956 | } else { | 975 | } else { |
957 | /*EMPTY*/ | 976 | /*EMPTY*/ |
958 | DEBUG11(printk("qla2x00_abort_target(%ld): done.\n", | 977 | DEBUG11(printk("qla2x00_abort_target(%ld): done.\n", |
959 | fcport->ha->host_no);) | 978 | ha->host_no);) |
960 | } | 979 | } |
961 | 980 | ||
962 | return rval; | 981 | return rval; |
@@ -1206,82 +1225,117 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) | |||
1206 | mbx_cmd_t mc; | 1225 | mbx_cmd_t mc; |
1207 | mbx_cmd_t *mcp = &mc; | 1226 | mbx_cmd_t *mcp = &mc; |
1208 | port_database_t *pd; | 1227 | port_database_t *pd; |
1228 | struct port_database_24xx *pd24; | ||
1209 | dma_addr_t pd_dma; | 1229 | dma_addr_t pd_dma; |
1210 | 1230 | ||
1211 | DEBUG11(printk("qla2x00_get_port_database(%ld): entered.\n", | 1231 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) |
1212 | ha->host_no);) | ||
1213 | 1232 | ||
1214 | pd = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &pd_dma); | 1233 | pd24 = NULL; |
1234 | pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma); | ||
1215 | if (pd == NULL) { | 1235 | if (pd == NULL) { |
1216 | DEBUG2_3_11(printk("qla2x00_get_port_database(%ld): **** " | 1236 | DEBUG2_3(printk("%s(%ld): failed to allocate Port Database " |
1217 | "Mem Alloc Failed ****", ha->host_no);) | 1237 | "structure.\n", __func__, ha->host_no)); |
1218 | return QLA_MEMORY_ALLOC_FAILED; | 1238 | return QLA_MEMORY_ALLOC_FAILED; |
1219 | } | 1239 | } |
1220 | memset(pd, 0, PORT_DATABASE_SIZE); | 1240 | memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE)); |
1221 | 1241 | ||
1222 | if (opt != 0) | 1242 | mcp->mb[0] = MBC_GET_PORT_DATABASE; |
1243 | if (opt != 0 && !IS_QLA24XX(ha) && !IS_QLA25XX(ha)) | ||
1223 | mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE; | 1244 | mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE; |
1224 | else | ||
1225 | mcp->mb[0] = MBC_GET_PORT_DATABASE; | ||
1226 | mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; | ||
1227 | if (HAS_EXTENDED_IDS(ha)) { | ||
1228 | mcp->mb[1] = fcport->loop_id; | ||
1229 | mcp->mb[10] = opt; | ||
1230 | mcp->out_mb |= MBX_10; | ||
1231 | } else { | ||
1232 | mcp->mb[1] = fcport->loop_id << 8 | opt; | ||
1233 | } | ||
1234 | mcp->mb[2] = MSW(pd_dma); | 1245 | mcp->mb[2] = MSW(pd_dma); |
1235 | mcp->mb[3] = LSW(pd_dma); | 1246 | mcp->mb[3] = LSW(pd_dma); |
1236 | mcp->mb[6] = MSW(MSD(pd_dma)); | 1247 | mcp->mb[6] = MSW(MSD(pd_dma)); |
1237 | mcp->mb[7] = LSW(MSD(pd_dma)); | 1248 | mcp->mb[7] = LSW(MSD(pd_dma)); |
1238 | 1249 | mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; | |
1239 | mcp->in_mb = MBX_0; | 1250 | mcp->in_mb = MBX_0; |
1240 | mcp->buf_size = PORT_DATABASE_SIZE; | 1251 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { |
1252 | mcp->mb[1] = fcport->loop_id; | ||
1253 | mcp->mb[10] = opt; | ||
1254 | mcp->out_mb |= MBX_10|MBX_1; | ||
1255 | mcp->in_mb |= MBX_1; | ||
1256 | } else if (HAS_EXTENDED_IDS(ha)) { | ||
1257 | mcp->mb[1] = fcport->loop_id; | ||
1258 | mcp->mb[10] = opt; | ||
1259 | mcp->out_mb |= MBX_10|MBX_1; | ||
1260 | } else { | ||
1261 | mcp->mb[1] = fcport->loop_id << 8 | opt; | ||
1262 | mcp->out_mb |= MBX_1; | ||
1263 | } | ||
1264 | mcp->buf_size = (IS_QLA24XX(ha) || IS_QLA25XX(ha) ? | ||
1265 | PORT_DATABASE_24XX_SIZE : PORT_DATABASE_SIZE); | ||
1241 | mcp->flags = MBX_DMA_IN; | 1266 | mcp->flags = MBX_DMA_IN; |
1242 | mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); | 1267 | mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); |
1243 | rval = qla2x00_mailbox_command(ha, mcp); | 1268 | rval = qla2x00_mailbox_command(ha, mcp); |
1244 | if (rval != QLA_SUCCESS) | 1269 | if (rval != QLA_SUCCESS) |
1245 | goto gpd_error_out; | 1270 | goto gpd_error_out; |
1246 | 1271 | ||
1247 | /* Check for logged in state. */ | 1272 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { |
1248 | if (pd->master_state != PD_STATE_PORT_LOGGED_IN && | 1273 | pd24 = (struct port_database_24xx *) pd; |
1249 | pd->slave_state != PD_STATE_PORT_LOGGED_IN) { | 1274 | |
1250 | rval = QLA_FUNCTION_FAILED; | 1275 | /* Check for logged in state. */ |
1251 | goto gpd_error_out; | 1276 | if (pd24->current_login_state != PDS_PRLI_COMPLETE && |
1252 | } | 1277 | pd24->last_login_state != PDS_PRLI_COMPLETE) { |
1253 | 1278 | DEBUG2(printk("%s(%ld): Unable to verify " | |
1254 | /* Names are little-endian. */ | 1279 | "login-state (%x/%x) for loop_id %x\n", |
1255 | memcpy(fcport->node_name, pd->node_name, WWN_SIZE); | 1280 | __func__, ha->host_no, |
1256 | memcpy(fcport->port_name, pd->port_name, WWN_SIZE); | 1281 | pd24->current_login_state, |
1257 | 1282 | pd24->last_login_state, fcport->loop_id)); | |
1258 | /* Get port_id of device. */ | 1283 | rval = QLA_FUNCTION_FAILED; |
1259 | fcport->d_id.b.al_pa = pd->port_id[2]; | 1284 | goto gpd_error_out; |
1260 | fcport->d_id.b.area = pd->port_id[3]; | 1285 | } |
1261 | fcport->d_id.b.domain = pd->port_id[0]; | ||
1262 | fcport->d_id.b.rsvd_1 = 0; | ||
1263 | 1286 | ||
1264 | /* Check for device require authentication. */ | 1287 | /* Names are little-endian. */ |
1265 | pd->common_features & BIT_5 ? (fcport->flags |= FCF_AUTH_REQ) : | 1288 | memcpy(fcport->node_name, pd24->node_name, WWN_SIZE); |
1266 | (fcport->flags &= ~FCF_AUTH_REQ); | 1289 | memcpy(fcport->port_name, pd24->port_name, WWN_SIZE); |
1290 | |||
1291 | /* Get port_id of device. */ | ||
1292 | fcport->d_id.b.domain = pd24->port_id[0]; | ||
1293 | fcport->d_id.b.area = pd24->port_id[1]; | ||
1294 | fcport->d_id.b.al_pa = pd24->port_id[2]; | ||
1295 | fcport->d_id.b.rsvd_1 = 0; | ||
1296 | |||
1297 | /* If not target must be initiator or unknown type. */ | ||
1298 | if ((pd24->prli_svc_param_word_3[0] & BIT_4) == 0) | ||
1299 | fcport->port_type = FCT_INITIATOR; | ||
1300 | else | ||
1301 | fcport->port_type = FCT_TARGET; | ||
1302 | } else { | ||
1303 | /* Check for logged in state. */ | ||
1304 | if (pd->master_state != PD_STATE_PORT_LOGGED_IN && | ||
1305 | pd->slave_state != PD_STATE_PORT_LOGGED_IN) { | ||
1306 | rval = QLA_FUNCTION_FAILED; | ||
1307 | goto gpd_error_out; | ||
1308 | } | ||
1267 | 1309 | ||
1268 | /* If not target must be initiator or unknown type. */ | 1310 | /* Names are little-endian. */ |
1269 | if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0) | 1311 | memcpy(fcport->node_name, pd->node_name, WWN_SIZE); |
1270 | fcport->port_type = FCT_INITIATOR; | 1312 | memcpy(fcport->port_name, pd->port_name, WWN_SIZE); |
1271 | else | 1313 | |
1272 | fcport->port_type = FCT_TARGET; | 1314 | /* Get port_id of device. */ |
1315 | fcport->d_id.b.domain = pd->port_id[0]; | ||
1316 | fcport->d_id.b.area = pd->port_id[3]; | ||
1317 | fcport->d_id.b.al_pa = pd->port_id[2]; | ||
1318 | fcport->d_id.b.rsvd_1 = 0; | ||
1319 | |||
1320 | /* Check for device require authentication. */ | ||
1321 | pd->common_features & BIT_5 ? (fcport->flags |= FCF_AUTH_REQ) : | ||
1322 | (fcport->flags &= ~FCF_AUTH_REQ); | ||
1323 | |||
1324 | /* If not target must be initiator or unknown type. */ | ||
1325 | if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0) | ||
1326 | fcport->port_type = FCT_INITIATOR; | ||
1327 | else | ||
1328 | fcport->port_type = FCT_TARGET; | ||
1329 | } | ||
1273 | 1330 | ||
1274 | gpd_error_out: | 1331 | gpd_error_out: |
1275 | dma_pool_free(ha->s_dma_pool, pd, pd_dma); | 1332 | dma_pool_free(ha->s_dma_pool, pd, pd_dma); |
1276 | 1333 | ||
1277 | if (rval != QLA_SUCCESS) { | 1334 | if (rval != QLA_SUCCESS) { |
1278 | /*EMPTY*/ | 1335 | DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n", |
1279 | DEBUG2_3_11(printk("qla2x00_get_port_database(%ld): " | 1336 | __func__, ha->host_no, rval, mcp->mb[0], mcp->mb[1])); |
1280 | "failed=%x.\n", ha->host_no, rval);) | ||
1281 | } else { | 1337 | } else { |
1282 | /*EMPTY*/ | 1338 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); |
1283 | DEBUG11(printk("qla2x00_get_port_database(%ld): done.\n", | ||
1284 | ha->host_no);) | ||
1285 | } | 1339 | } |
1286 | 1340 | ||
1287 | return rval; | 1341 | return rval; |
@@ -1426,21 +1480,27 @@ qla2x00_lip_reset(scsi_qla_host_t *ha) | |||
1426 | mbx_cmd_t mc; | 1480 | mbx_cmd_t mc; |
1427 | mbx_cmd_t *mcp = &mc; | 1481 | mbx_cmd_t *mcp = &mc; |
1428 | 1482 | ||
1429 | DEBUG11(printk("qla2x00_lip_reset(%ld): entered.\n", | 1483 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) |
1430 | ha->host_no);) | ||
1431 | 1484 | ||
1432 | mcp->mb[0] = MBC_LIP_RESET; | 1485 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { |
1433 | mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; | 1486 | mcp->mb[0] = MBC_LIP_FULL_LOGIN; |
1434 | if (HAS_EXTENDED_IDS(ha)) { | 1487 | mcp->mb[1] = BIT_0; |
1435 | mcp->mb[1] = 0x00ff; | 1488 | mcp->mb[2] = 0xff; |
1436 | mcp->mb[10] = 0; | 1489 | mcp->mb[3] = 0; |
1437 | mcp->out_mb |= MBX_10; | 1490 | mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; |
1438 | } else { | 1491 | } else { |
1439 | mcp->mb[1] = 0xff00; | 1492 | mcp->mb[0] = MBC_LIP_RESET; |
1493 | mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; | ||
1494 | if (HAS_EXTENDED_IDS(ha)) { | ||
1495 | mcp->mb[1] = 0x00ff; | ||
1496 | mcp->mb[10] = 0; | ||
1497 | mcp->out_mb |= MBX_10; | ||
1498 | } else { | ||
1499 | mcp->mb[1] = 0xff00; | ||
1500 | } | ||
1501 | mcp->mb[2] = ha->loop_reset_delay; | ||
1502 | mcp->mb[3] = 0; | ||
1440 | } | 1503 | } |
1441 | mcp->mb[2] = ha->loop_reset_delay; | ||
1442 | mcp->mb[3] = 0; | ||
1443 | |||
1444 | mcp->in_mb = MBX_0; | 1504 | mcp->in_mb = MBX_0; |
1445 | mcp->tov = 30; | 1505 | mcp->tov = 30; |
1446 | mcp->flags = 0; | 1506 | mcp->flags = 0; |
@@ -1448,11 +1508,11 @@ qla2x00_lip_reset(scsi_qla_host_t *ha) | |||
1448 | 1508 | ||
1449 | if (rval != QLA_SUCCESS) { | 1509 | if (rval != QLA_SUCCESS) { |
1450 | /*EMPTY*/ | 1510 | /*EMPTY*/ |
1451 | DEBUG2_3_11(printk("qla2x00_lip_reset(%ld): failed=%x.\n", | 1511 | DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", |
1452 | ha->host_no, rval);) | 1512 | __func__, ha->host_no, rval);) |
1453 | } else { | 1513 | } else { |
1454 | /*EMPTY*/ | 1514 | /*EMPTY*/ |
1455 | DEBUG11(printk("qla2x00_lip_reset(%ld): done.\n", ha->host_no);) | 1515 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);) |
1456 | } | 1516 | } |
1457 | 1517 | ||
1458 | return rval; | 1518 | return rval; |
@@ -1517,6 +1577,97 @@ qla2x00_send_sns(scsi_qla_host_t *ha, dma_addr_t sns_phys_address, | |||
1517 | return rval; | 1577 | return rval; |
1518 | } | 1578 | } |
1519 | 1579 | ||
1580 | int | ||
1581 | qla24xx_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, | ||
1582 | uint8_t area, uint8_t al_pa, uint16_t *mb, uint8_t opt) | ||
1583 | { | ||
1584 | int rval; | ||
1585 | |||
1586 | struct logio_entry_24xx *lg; | ||
1587 | dma_addr_t lg_dma; | ||
1588 | uint32_t iop[2]; | ||
1589 | |||
1590 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) | ||
1591 | |||
1592 | lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma); | ||
1593 | if (lg == NULL) { | ||
1594 | DEBUG2_3(printk("%s(%ld): failed to allocate Login IOCB.\n", | ||
1595 | __func__, ha->host_no)); | ||
1596 | return QLA_MEMORY_ALLOC_FAILED; | ||
1597 | } | ||
1598 | memset(lg, 0, sizeof(struct logio_entry_24xx)); | ||
1599 | |||
1600 | lg->entry_type = LOGINOUT_PORT_IOCB_TYPE; | ||
1601 | lg->entry_count = 1; | ||
1602 | lg->nport_handle = cpu_to_le16(loop_id); | ||
1603 | lg->control_flags = __constant_cpu_to_le16(LCF_COMMAND_PLOGI); | ||
1604 | if (opt & BIT_0) | ||
1605 | lg->control_flags |= __constant_cpu_to_le16(LCF_COND_PLOGI); | ||
1606 | lg->port_id[0] = al_pa; | ||
1607 | lg->port_id[1] = area; | ||
1608 | lg->port_id[2] = domain; | ||
1609 | rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0); | ||
1610 | if (rval != QLA_SUCCESS) { | ||
1611 | DEBUG2_3_11(printk("%s(%ld): failed to issue Login IOCB " | ||
1612 | "(%x).\n", __func__, ha->host_no, rval);) | ||
1613 | } else if (lg->entry_status != 0) { | ||
1614 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
1615 | "-- error status (%x).\n", __func__, ha->host_no, | ||
1616 | lg->entry_status)); | ||
1617 | rval = QLA_FUNCTION_FAILED; | ||
1618 | } else if (lg->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { | ||
1619 | iop[0] = le32_to_cpu(lg->io_parameter[0]); | ||
1620 | iop[1] = le32_to_cpu(lg->io_parameter[1]); | ||
1621 | |||
1622 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
1623 | "-- completion status (%x) ioparam=%x/%x.\n", __func__, | ||
1624 | ha->host_no, le16_to_cpu(lg->comp_status), iop[0], | ||
1625 | iop[1])); | ||
1626 | |||
1627 | switch (iop[0]) { | ||
1628 | case LSC_SCODE_PORTID_USED: | ||
1629 | mb[0] = MBS_PORT_ID_USED; | ||
1630 | mb[1] = LSW(iop[1]); | ||
1631 | break; | ||
1632 | case LSC_SCODE_NPORT_USED: | ||
1633 | mb[0] = MBS_LOOP_ID_USED; | ||
1634 | break; | ||
1635 | case LSC_SCODE_NOLINK: | ||
1636 | case LSC_SCODE_NOIOCB: | ||
1637 | case LSC_SCODE_NOXCB: | ||
1638 | case LSC_SCODE_CMD_FAILED: | ||
1639 | case LSC_SCODE_NOFABRIC: | ||
1640 | case LSC_SCODE_FW_NOT_READY: | ||
1641 | case LSC_SCODE_NOT_LOGGED_IN: | ||
1642 | case LSC_SCODE_NOPCB: | ||
1643 | case LSC_SCODE_ELS_REJECT: | ||
1644 | case LSC_SCODE_CMD_PARAM_ERR: | ||
1645 | case LSC_SCODE_NONPORT: | ||
1646 | case LSC_SCODE_LOGGED_IN: | ||
1647 | case LSC_SCODE_NOFLOGI_ACC: | ||
1648 | default: | ||
1649 | mb[0] = MBS_COMMAND_ERROR; | ||
1650 | break; | ||
1651 | } | ||
1652 | } else { | ||
1653 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);) | ||
1654 | |||
1655 | iop[0] = le32_to_cpu(lg->io_parameter[0]); | ||
1656 | |||
1657 | mb[0] = MBS_COMMAND_COMPLETE; | ||
1658 | mb[1] = 0; | ||
1659 | if (iop[0] & BIT_4) { | ||
1660 | if (iop[0] & BIT_8) | ||
1661 | mb[1] |= BIT_1; | ||
1662 | } else | ||
1663 | mb[1] = BIT_0; | ||
1664 | } | ||
1665 | |||
1666 | dma_pool_free(ha->s_dma_pool, lg, lg_dma); | ||
1667 | |||
1668 | return rval; | ||
1669 | } | ||
1670 | |||
1520 | /* | 1671 | /* |
1521 | * qla2x00_login_fabric | 1672 | * qla2x00_login_fabric |
1522 | * Issue login fabric port mailbox command. | 1673 | * Issue login fabric port mailbox command. |
@@ -1669,6 +1820,57 @@ qla2x00_login_local_device(scsi_qla_host_t *ha, uint16_t loop_id, | |||
1669 | return (rval); | 1820 | return (rval); |
1670 | } | 1821 | } |
1671 | 1822 | ||
1823 | int | ||
1824 | qla24xx_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, | ||
1825 | uint8_t area, uint8_t al_pa) | ||
1826 | { | ||
1827 | int rval; | ||
1828 | struct logio_entry_24xx *lg; | ||
1829 | dma_addr_t lg_dma; | ||
1830 | |||
1831 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) | ||
1832 | |||
1833 | lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma); | ||
1834 | if (lg == NULL) { | ||
1835 | DEBUG2_3(printk("%s(%ld): failed to allocate Logout IOCB.\n", | ||
1836 | __func__, ha->host_no)); | ||
1837 | return QLA_MEMORY_ALLOC_FAILED; | ||
1838 | } | ||
1839 | memset(lg, 0, sizeof(struct logio_entry_24xx)); | ||
1840 | |||
1841 | lg->entry_type = LOGINOUT_PORT_IOCB_TYPE; | ||
1842 | lg->entry_count = 1; | ||
1843 | lg->nport_handle = cpu_to_le16(loop_id); | ||
1844 | lg->control_flags = | ||
1845 | __constant_cpu_to_le16(LCF_COMMAND_LOGO|LCF_EXPL_LOGO); | ||
1846 | lg->port_id[0] = al_pa; | ||
1847 | lg->port_id[1] = area; | ||
1848 | lg->port_id[2] = domain; | ||
1849 | rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0); | ||
1850 | if (rval != QLA_SUCCESS) { | ||
1851 | DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB " | ||
1852 | "(%x).\n", __func__, ha->host_no, rval);) | ||
1853 | } else if (lg->entry_status != 0) { | ||
1854 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
1855 | "-- error status (%x).\n", __func__, ha->host_no, | ||
1856 | lg->entry_status)); | ||
1857 | rval = QLA_FUNCTION_FAILED; | ||
1858 | } else if (lg->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { | ||
1859 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
1860 | "-- completion status (%x) ioparam=%x/%x.\n", __func__, | ||
1861 | ha->host_no, le16_to_cpu(lg->comp_status), | ||
1862 | le32_to_cpu(lg->io_parameter[0]), | ||
1863 | le32_to_cpu(lg->io_parameter[1]));) | ||
1864 | } else { | ||
1865 | /*EMPTY*/ | ||
1866 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);) | ||
1867 | } | ||
1868 | |||
1869 | dma_pool_free(ha->s_dma_pool, lg, lg_dma); | ||
1870 | |||
1871 | return rval; | ||
1872 | } | ||
1873 | |||
1672 | /* | 1874 | /* |
1673 | * qla2x00_fabric_logout | 1875 | * qla2x00_fabric_logout |
1674 | * Issue logout fabric port mailbox command. | 1876 | * Issue logout fabric port mailbox command. |
@@ -1686,7 +1888,8 @@ qla2x00_login_local_device(scsi_qla_host_t *ha, uint16_t loop_id, | |||
1686 | * Kernel context. | 1888 | * Kernel context. |
1687 | */ | 1889 | */ |
1688 | int | 1890 | int |
1689 | qla2x00_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id) | 1891 | qla2x00_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, |
1892 | uint8_t area, uint8_t al_pa) | ||
1690 | { | 1893 | { |
1691 | int rval; | 1894 | int rval; |
1692 | mbx_cmd_t mc; | 1895 | mbx_cmd_t mc; |
@@ -1750,7 +1953,7 @@ qla2x00_full_login_lip(scsi_qla_host_t *ha) | |||
1750 | 1953 | ||
1751 | mcp->mb[0] = MBC_LIP_FULL_LOGIN; | 1954 | mcp->mb[0] = MBC_LIP_FULL_LOGIN; |
1752 | mcp->mb[1] = 0; | 1955 | mcp->mb[1] = 0; |
1753 | mcp->mb[2] = 0; | 1956 | mcp->mb[2] = 0xff; |
1754 | mcp->mb[3] = 0; | 1957 | mcp->mb[3] = 0; |
1755 | mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; | 1958 | mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; |
1756 | mcp->in_mb = MBX_0; | 1959 | mcp->in_mb = MBX_0; |
@@ -1761,7 +1964,7 @@ qla2x00_full_login_lip(scsi_qla_host_t *ha) | |||
1761 | if (rval != QLA_SUCCESS) { | 1964 | if (rval != QLA_SUCCESS) { |
1762 | /*EMPTY*/ | 1965 | /*EMPTY*/ |
1763 | DEBUG2_3_11(printk("qla2x00_full_login_lip(%ld): failed=%x.\n", | 1966 | DEBUG2_3_11(printk("qla2x00_full_login_lip(%ld): failed=%x.\n", |
1764 | ha->instance, rval);) | 1967 | ha->host_no, rval);) |
1765 | } else { | 1968 | } else { |
1766 | /*EMPTY*/ | 1969 | /*EMPTY*/ |
1767 | DEBUG11(printk("qla2x00_full_login_lip(%ld): done.\n", | 1970 | DEBUG11(printk("qla2x00_full_login_lip(%ld): done.\n", |
@@ -1798,11 +2001,20 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma, | |||
1798 | return QLA_FUNCTION_FAILED; | 2001 | return QLA_FUNCTION_FAILED; |
1799 | 2002 | ||
1800 | mcp->mb[0] = MBC_GET_ID_LIST; | 2003 | mcp->mb[0] = MBC_GET_ID_LIST; |
1801 | mcp->mb[1] = MSW(id_list_dma); | 2004 | mcp->out_mb = MBX_0; |
1802 | mcp->mb[2] = LSW(id_list_dma); | 2005 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { |
1803 | mcp->mb[3] = MSW(MSD(id_list_dma)); | 2006 | mcp->mb[2] = MSW(id_list_dma); |
1804 | mcp->mb[6] = LSW(MSD(id_list_dma)); | 2007 | mcp->mb[3] = LSW(id_list_dma); |
1805 | mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; | 2008 | mcp->mb[6] = MSW(MSD(id_list_dma)); |
2009 | mcp->mb[7] = LSW(MSD(id_list_dma)); | ||
2010 | mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2; | ||
2011 | } else { | ||
2012 | mcp->mb[1] = MSW(id_list_dma); | ||
2013 | mcp->mb[2] = LSW(id_list_dma); | ||
2014 | mcp->mb[3] = MSW(MSD(id_list_dma)); | ||
2015 | mcp->mb[6] = LSW(MSD(id_list_dma)); | ||
2016 | mcp->out_mb |= MBX_6|MBX_3|MBX_2|MBX_1; | ||
2017 | } | ||
1806 | mcp->in_mb = MBX_1|MBX_0; | 2018 | mcp->in_mb = MBX_1|MBX_0; |
1807 | mcp->tov = 30; | 2019 | mcp->tov = 30; |
1808 | mcp->flags = 0; | 2020 | mcp->flags = 0; |
@@ -1938,4 +2150,318 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map) | |||
1938 | 2150 | ||
1939 | return rval; | 2151 | return rval; |
1940 | } | 2152 | } |
2153 | |||
2154 | uint8_t | ||
2155 | qla24xx_get_isp_stats(scsi_qla_host_t *ha, uint32_t *dwbuf, uint32_t dwords, | ||
2156 | uint16_t *status) | ||
2157 | { | ||
2158 | int rval; | ||
2159 | mbx_cmd_t mc; | ||
2160 | mbx_cmd_t *mcp = &mc; | ||
2161 | uint32_t *sbuf, *siter; | ||
2162 | dma_addr_t sbuf_dma; | ||
2163 | |||
2164 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) | ||
2165 | |||
2166 | if (dwords > (DMA_POOL_SIZE / 4)) { | ||
2167 | DEBUG2_3_11(printk("%s(%ld): Unabled to retrieve %d DWORDs " | ||
2168 | "(max %d).\n", __func__, ha->host_no, dwords, | ||
2169 | DMA_POOL_SIZE / 4)); | ||
2170 | return BIT_0; | ||
2171 | } | ||
2172 | sbuf = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &sbuf_dma); | ||
2173 | if (sbuf == NULL) { | ||
2174 | DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n", | ||
2175 | __func__, ha->host_no)); | ||
2176 | return BIT_0; | ||
2177 | } | ||
2178 | memset(sbuf, 0, DMA_POOL_SIZE); | ||
2179 | |||
2180 | mcp->mb[0] = MBC_GET_LINK_PRIV_STATS; | ||
2181 | mcp->mb[2] = MSW(sbuf_dma); | ||
2182 | mcp->mb[3] = LSW(sbuf_dma); | ||
2183 | mcp->mb[6] = MSW(MSD(sbuf_dma)); | ||
2184 | mcp->mb[7] = LSW(MSD(sbuf_dma)); | ||
2185 | mcp->mb[8] = dwords; | ||
2186 | mcp->mb[10] = 0; | ||
2187 | mcp->out_mb = MBX_10|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; | ||
2188 | mcp->in_mb = MBX_2|MBX_1|MBX_0; | ||
2189 | mcp->tov = 30; | ||
2190 | mcp->flags = IOCTL_CMD; | ||
2191 | rval = qla2x00_mailbox_command(ha, mcp); | ||
2192 | |||
2193 | if (rval == QLA_SUCCESS) { | ||
2194 | if (mcp->mb[0] != MBS_COMMAND_COMPLETE) { | ||
2195 | DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n", | ||
2196 | __func__, ha->host_no, mcp->mb[0])); | ||
2197 | status[0] = mcp->mb[0]; | ||
2198 | rval = BIT_1; | ||
2199 | } else { | ||
2200 | /* Copy over data -- firmware data is LE. */ | ||
2201 | siter = sbuf; | ||
2202 | while (dwords--) | ||
2203 | *dwbuf++ = le32_to_cpu(*siter++); | ||
2204 | } | ||
2205 | } else { | ||
2206 | /* Failed. */ | ||
2207 | DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, | ||
2208 | ha->host_no, rval)); | ||
2209 | rval = BIT_1; | ||
2210 | } | ||
2211 | |||
2212 | dma_pool_free(ha->s_dma_pool, sbuf, sbuf_dma); | ||
2213 | |||
2214 | return rval; | ||
2215 | } | ||
1941 | #endif | 2216 | #endif |
2217 | |||
2218 | int | ||
2219 | qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp) | ||
2220 | { | ||
2221 | int rval; | ||
2222 | fc_port_t *fcport; | ||
2223 | unsigned long flags = 0; | ||
2224 | |||
2225 | struct abort_entry_24xx *abt; | ||
2226 | dma_addr_t abt_dma; | ||
2227 | uint32_t handle; | ||
2228 | |||
2229 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) | ||
2230 | |||
2231 | fcport = sp->fcport; | ||
2232 | if (atomic_read(&ha->loop_state) == LOOP_DOWN || | ||
2233 | atomic_read(&fcport->state) == FCS_DEVICE_LOST) { | ||
2234 | return QLA_FUNCTION_FAILED; | ||
2235 | } | ||
2236 | |||
2237 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
2238 | for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) { | ||
2239 | if (ha->outstanding_cmds[handle] == sp) | ||
2240 | break; | ||
2241 | } | ||
2242 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2243 | if (handle == MAX_OUTSTANDING_COMMANDS) { | ||
2244 | /* Command not found. */ | ||
2245 | return QLA_FUNCTION_FAILED; | ||
2246 | } | ||
2247 | |||
2248 | abt = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &abt_dma); | ||
2249 | if (abt == NULL) { | ||
2250 | DEBUG2_3(printk("%s(%ld): failed to allocate Abort IOCB.\n", | ||
2251 | __func__, ha->host_no)); | ||
2252 | return QLA_MEMORY_ALLOC_FAILED; | ||
2253 | } | ||
2254 | memset(abt, 0, sizeof(struct abort_entry_24xx)); | ||
2255 | |||
2256 | abt->entry_type = ABORT_IOCB_TYPE; | ||
2257 | abt->entry_count = 1; | ||
2258 | abt->nport_handle = cpu_to_le16(fcport->loop_id); | ||
2259 | abt->handle_to_abort = handle; | ||
2260 | abt->port_id[0] = fcport->d_id.b.al_pa; | ||
2261 | abt->port_id[1] = fcport->d_id.b.area; | ||
2262 | abt->port_id[2] = fcport->d_id.b.domain; | ||
2263 | rval = qla2x00_issue_iocb(ha, abt, abt_dma, 0); | ||
2264 | if (rval != QLA_SUCCESS) { | ||
2265 | DEBUG2_3_11(printk("%s(%ld): failed to issue IOCB (%x).\n", | ||
2266 | __func__, ha->host_no, rval);) | ||
2267 | } else if (abt->entry_status != 0) { | ||
2268 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
2269 | "-- error status (%x).\n", __func__, ha->host_no, | ||
2270 | abt->entry_status)); | ||
2271 | rval = QLA_FUNCTION_FAILED; | ||
2272 | } else if (abt->nport_handle != __constant_cpu_to_le16(0)) { | ||
2273 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
2274 | "-- completion status (%x).\n", __func__, ha->host_no, | ||
2275 | le16_to_cpu(abt->nport_handle));) | ||
2276 | rval = QLA_FUNCTION_FAILED; | ||
2277 | } else { | ||
2278 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);) | ||
2279 | sp->flags |= SRB_ABORT_PENDING; | ||
2280 | } | ||
2281 | |||
2282 | dma_pool_free(ha->s_dma_pool, abt, abt_dma); | ||
2283 | |||
2284 | return rval; | ||
2285 | } | ||
2286 | |||
2287 | struct tsk_mgmt_cmd { | ||
2288 | union { | ||
2289 | struct tsk_mgmt_entry tsk; | ||
2290 | struct sts_entry_24xx sts; | ||
2291 | } p; | ||
2292 | }; | ||
2293 | |||
2294 | int | ||
2295 | qla24xx_abort_target(fc_port_t *fcport) | ||
2296 | { | ||
2297 | int rval; | ||
2298 | struct tsk_mgmt_cmd *tsk; | ||
2299 | dma_addr_t tsk_dma; | ||
2300 | scsi_qla_host_t *ha; | ||
2301 | |||
2302 | if (fcport == NULL) | ||
2303 | return 0; | ||
2304 | |||
2305 | DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no);) | ||
2306 | |||
2307 | ha = fcport->ha; | ||
2308 | tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma); | ||
2309 | if (tsk == NULL) { | ||
2310 | DEBUG2_3(printk("%s(%ld): failed to allocate Task Management " | ||
2311 | "IOCB.\n", __func__, ha->host_no)); | ||
2312 | return QLA_MEMORY_ALLOC_FAILED; | ||
2313 | } | ||
2314 | memset(tsk, 0, sizeof(struct tsk_mgmt_cmd)); | ||
2315 | |||
2316 | tsk->p.tsk.entry_type = TSK_MGMT_IOCB_TYPE; | ||
2317 | tsk->p.tsk.entry_count = 1; | ||
2318 | tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id); | ||
2319 | tsk->p.tsk.timeout = __constant_cpu_to_le16(25); | ||
2320 | tsk->p.tsk.control_flags = __constant_cpu_to_le32(TCF_TARGET_RESET); | ||
2321 | tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa; | ||
2322 | tsk->p.tsk.port_id[1] = fcport->d_id.b.area; | ||
2323 | tsk->p.tsk.port_id[2] = fcport->d_id.b.domain; | ||
2324 | rval = qla2x00_issue_iocb(ha, tsk, tsk_dma, 0); | ||
2325 | if (rval != QLA_SUCCESS) { | ||
2326 | DEBUG2_3_11(printk("%s(%ld): failed to issue Target Reset IOCB " | ||
2327 | "(%x).\n", __func__, ha->host_no, rval);) | ||
2328 | goto atarget_done; | ||
2329 | } else if (tsk->p.sts.entry_status != 0) { | ||
2330 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
2331 | "-- error status (%x).\n", __func__, ha->host_no, | ||
2332 | tsk->p.sts.entry_status)); | ||
2333 | rval = QLA_FUNCTION_FAILED; | ||
2334 | goto atarget_done; | ||
2335 | } else if (tsk->p.sts.comp_status != | ||
2336 | __constant_cpu_to_le16(CS_COMPLETE)) { | ||
2337 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
2338 | "-- completion status (%x).\n", __func__, | ||
2339 | ha->host_no, le16_to_cpu(tsk->p.sts.comp_status));) | ||
2340 | rval = QLA_FUNCTION_FAILED; | ||
2341 | goto atarget_done; | ||
2342 | } | ||
2343 | |||
2344 | /* Issue marker IOCB. */ | ||
2345 | rval = qla2x00_marker(ha, fcport->loop_id, 0, MK_SYNC_ID); | ||
2346 | if (rval != QLA_SUCCESS) { | ||
2347 | DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB " | ||
2348 | "(%x).\n", __func__, ha->host_no, rval);) | ||
2349 | } else { | ||
2350 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);) | ||
2351 | } | ||
2352 | |||
2353 | atarget_done: | ||
2354 | dma_pool_free(ha->s_dma_pool, tsk, tsk_dma); | ||
2355 | |||
2356 | return rval; | ||
2357 | } | ||
2358 | |||
2359 | int | ||
2360 | qla2x00_system_error(scsi_qla_host_t *ha) | ||
2361 | { | ||
2362 | int rval; | ||
2363 | mbx_cmd_t mc; | ||
2364 | mbx_cmd_t *mcp = &mc; | ||
2365 | |||
2366 | if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) | ||
2367 | return QLA_FUNCTION_FAILED; | ||
2368 | |||
2369 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | ||
2370 | |||
2371 | mcp->mb[0] = MBC_GEN_SYSTEM_ERROR; | ||
2372 | mcp->out_mb = MBX_0; | ||
2373 | mcp->in_mb = MBX_0; | ||
2374 | mcp->tov = 5; | ||
2375 | mcp->flags = 0; | ||
2376 | rval = qla2x00_mailbox_command(ha, mcp); | ||
2377 | |||
2378 | if (rval != QLA_SUCCESS) { | ||
2379 | DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, | ||
2380 | ha->host_no, rval)); | ||
2381 | } else { | ||
2382 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); | ||
2383 | } | ||
2384 | |||
2385 | return rval; | ||
2386 | } | ||
2387 | |||
2388 | /** | ||
2389 | * qla2x00_get_serdes_params() - | ||
2390 | * @ha: HA context | ||
2391 | * | ||
2392 | * Returns | ||
2393 | */ | ||
2394 | int | ||
2395 | qla2x00_get_serdes_params(scsi_qla_host_t *ha, uint16_t *sw_em_1g, | ||
2396 | uint16_t *sw_em_2g, uint16_t *sw_em_4g) | ||
2397 | { | ||
2398 | int rval; | ||
2399 | mbx_cmd_t mc; | ||
2400 | mbx_cmd_t *mcp = &mc; | ||
2401 | |||
2402 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | ||
2403 | |||
2404 | mcp->mb[0] = MBC_SERDES_PARAMS; | ||
2405 | mcp->mb[1] = 0; | ||
2406 | mcp->out_mb = MBX_1|MBX_0; | ||
2407 | mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_0; | ||
2408 | mcp->tov = 30; | ||
2409 | mcp->flags = 0; | ||
2410 | rval = qla2x00_mailbox_command(ha, mcp); | ||
2411 | |||
2412 | if (rval != QLA_SUCCESS) { | ||
2413 | /*EMPTY*/ | ||
2414 | DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__, | ||
2415 | ha->host_no, rval, mcp->mb[0])); | ||
2416 | } else { | ||
2417 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); | ||
2418 | |||
2419 | if (sw_em_1g) | ||
2420 | *sw_em_1g = mcp->mb[2]; | ||
2421 | if (sw_em_2g) | ||
2422 | *sw_em_2g = mcp->mb[3]; | ||
2423 | if (sw_em_4g) | ||
2424 | *sw_em_4g = mcp->mb[4]; | ||
2425 | } | ||
2426 | |||
2427 | return rval; | ||
2428 | } | ||
2429 | |||
2430 | /** | ||
2431 | * qla2x00_set_serdes_params() - | ||
2432 | * @ha: HA context | ||
2433 | * | ||
2434 | * Returns | ||
2435 | */ | ||
2436 | int | ||
2437 | qla2x00_set_serdes_params(scsi_qla_host_t *ha, uint16_t sw_em_1g, | ||
2438 | uint16_t sw_em_2g, uint16_t sw_em_4g) | ||
2439 | { | ||
2440 | int rval; | ||
2441 | mbx_cmd_t mc; | ||
2442 | mbx_cmd_t *mcp = &mc; | ||
2443 | |||
2444 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | ||
2445 | |||
2446 | mcp->mb[0] = MBC_SERDES_PARAMS; | ||
2447 | mcp->mb[1] = BIT_0; | ||
2448 | mcp->mb[2] = sw_em_1g; | ||
2449 | mcp->mb[3] = sw_em_2g; | ||
2450 | mcp->mb[4] = sw_em_4g; | ||
2451 | mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; | ||
2452 | mcp->in_mb = MBX_0; | ||
2453 | mcp->tov = 30; | ||
2454 | mcp->flags = 0; | ||
2455 | rval = qla2x00_mailbox_command(ha, mcp); | ||
2456 | |||
2457 | if (rval != QLA_SUCCESS) { | ||
2458 | /*EMPTY*/ | ||
2459 | DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__, | ||
2460 | ha->host_no, rval, mcp->mb[0])); | ||
2461 | } else { | ||
2462 | /*EMPTY*/ | ||
2463 | DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); | ||
2464 | } | ||
2465 | |||
2466 | return rval; | ||
2467 | } | ||