blob: 49ce197876b487646e3667df649fbe0bdd442665 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Andrew Vasquezfa90c542005-10-27 11:10:08 -07002 * QLogic Fibre Channel HBA Driver
3 * Copyright (c) 2003-2005 QLogic Corporation
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
Andrew Vasquezfa90c542005-10-27 11:10:08 -07005 * See LICENSE.qla2xxx for copyright and licensing details.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 */
7#include "qla_def.h"
8
9#include <linux/delay.h>
10
11static void
12qla2x00_mbx_sem_timeout(unsigned long data)
13{
14 struct semaphore *sem_ptr = (struct semaphore *)data;
15
16 DEBUG11(printk("qla2x00_sem_timeout: entered.\n");)
17
18 if (sem_ptr != NULL) {
19 up(sem_ptr);
20 }
21
22 DEBUG11(printk("qla2x00_mbx_sem_timeout: exiting.\n");)
23}
24
25/*
26 * qla2x00_mailbox_command
27 * Issue mailbox command and waits for completion.
28 *
29 * Input:
30 * ha = adapter block pointer.
31 * mcp = driver internal mbx struct pointer.
32 *
33 * Output:
34 * mb[MAX_MAILBOX_REGISTER_COUNT] = returned mailbox data.
35 *
36 * Returns:
37 * 0 : QLA_SUCCESS = cmd performed success
38 * 1 : QLA_FUNCTION_FAILED (error encountered)
39 * 6 : QLA_FUNCTION_TIMEOUT (timeout condition encountered)
40 *
41 * Context:
42 * Kernel context.
43 */
44static int
45qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
46{
47 int rval;
48 unsigned long flags = 0;
Andrew Vasquez1c7c6352005-07-06 10:30:57 -070049 device_reg_t __iomem *reg = ha->iobase;
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 struct timer_list tmp_intr_timer;
Andrew Vasquez1c7c6352005-07-06 10:30:57 -070051 uint8_t abort_active;
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 uint8_t io_lock_on = ha->flags.init_done;
53 uint16_t command;
54 uint16_t *iptr;
55 uint16_t __iomem *optr;
56 uint32_t cnt;
57 uint32_t mboxes;
58 unsigned long mbx_flags = 0;
59 unsigned long wait_time;
60
61 rval = QLA_SUCCESS;
Andrew Vasquez1c7c6352005-07-06 10:30:57 -070062 abort_active = test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Andrew Vasquez1c7c6352005-07-06 10:30:57 -070064 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
65
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 /*
Andrew Vasquez1c7c6352005-07-06 10:30:57 -070067 * Wait for active mailbox commands to finish by waiting at most tov
68 * seconds. This is to serialize actual issuing of mailbox cmds during
69 * non ISP abort time.
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 */
71 if (!abort_active) {
72 if (qla2x00_down_timeout(&ha->mbx_cmd_sem, mcp->tov * HZ)) {
73 /* Timeout occurred. Return error. */
Andrew Vasquez1c7c6352005-07-06 10:30:57 -070074 DEBUG2_3_11(printk("%s(%ld): cmd access timeout. "
75 "Exiting.\n", __func__, ha->host_no);)
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 return QLA_FUNCTION_TIMEOUT;
77 }
78 }
79
80 ha->flags.mbox_busy = 1;
81 /* Save mailbox command for debug */
82 ha->mcp = mcp;
83
84 /* Try to get mailbox register access */
85 if (!abort_active)
86 spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags);
87
Andrew Vasquez1c7c6352005-07-06 10:30:57 -070088 DEBUG11(printk("scsi(%ld): prepare to issue mbox cmd=0x%x.\n",
89 ha->host_no, mcp->mb[0]);)
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
91 spin_lock_irqsave(&ha->hardware_lock, flags);
92
93 /* Load mailbox registers. */
Andrew Vasquez1c7c6352005-07-06 10:30:57 -070094 if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
95 optr = (uint16_t __iomem *)&reg->isp24.mailbox0;
96 else
97 optr = (uint16_t __iomem *)MAILBOX_REG(ha, &reg->isp, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070098
99 iptr = mcp->mb;
100 command = mcp->mb[0];
101 mboxes = mcp->out_mb;
102
103 for (cnt = 0; cnt < ha->mbx_count; cnt++) {
104 if (IS_QLA2200(ha) && cnt == 8)
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700105 optr =
106 (uint16_t __iomem *)MAILBOX_REG(ha, &reg->isp, 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 if (mboxes & BIT_0)
108 WRT_REG_WORD(optr, *iptr);
109
110 mboxes >>= 1;
111 optr++;
112 iptr++;
113 }
114
115#if defined(QL_DEBUG_LEVEL_1)
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700116 printk("%s(%ld): Loaded MBX registers (displayed in bytes) = \n",
117 __func__, ha->host_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 qla2x00_dump_buffer((uint8_t *)mcp->mb, 16);
119 printk("\n");
120 qla2x00_dump_buffer(((uint8_t *)mcp->mb + 0x10), 16);
121 printk("\n");
122 qla2x00_dump_buffer(((uint8_t *)mcp->mb + 0x20), 8);
123 printk("\n");
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700124 printk("%s(%ld): I/O address = %p.\n", __func__, ha->host_no, optr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 qla2x00_dump_regs(ha);
126#endif
127
128 /* Issue set host interrupt command to send cmd out. */
129 ha->flags.mbox_int = 0;
130 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
131
132 /* Unlock mbx registers and wait for interrupt */
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700133 DEBUG11(printk("%s(%ld): going to unlock irq & waiting for interrupt. "
134 "jiffies=%lx.\n", __func__, ha->host_no, jiffies);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135
136 /* Wait for mbx cmd completion until timeout */
137
138 if (!abort_active && io_lock_on) {
139 /* sleep on completion semaphore */
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700140 DEBUG11(printk("%s(%ld): INTERRUPT MODE. Initializing timer.\n",
141 __func__, ha->host_no);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
143 init_timer(&tmp_intr_timer);
144 tmp_intr_timer.data = (unsigned long)&ha->mbx_intr_sem;
145 tmp_intr_timer.expires = jiffies + mcp->tov * HZ;
146 tmp_intr_timer.function =
147 (void (*)(unsigned long))qla2x00_mbx_sem_timeout;
148
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700149 DEBUG11(printk("%s(%ld): Adding timer.\n", __func__,
150 ha->host_no);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 add_timer(&tmp_intr_timer);
152
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700153 DEBUG11(printk("%s(%ld): going to unlock & sleep. "
154 "time=0x%lx.\n", __func__, ha->host_no, jiffies);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
156 set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
157
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700158 if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
159 WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
160 else
161 WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 spin_unlock_irqrestore(&ha->hardware_lock, flags);
163
164 if (!abort_active)
165 spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags);
166
167 /* Wait for either the timer to expire
168 * or the mbox completion interrupt
169 */
170 down(&ha->mbx_intr_sem);
171
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700172 DEBUG11(printk("%s(%ld): waking up. time=0x%lx\n", __func__,
173 ha->host_no, jiffies);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
175
176 /* delete the timer */
177 del_timer(&tmp_intr_timer);
178 } else {
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700179 DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__,
180 ha->host_no, command);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700182 if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
183 WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
184 else
185 WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 spin_unlock_irqrestore(&ha->hardware_lock, flags);
187 if (!abort_active)
188 spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags);
189
190 wait_time = jiffies + mcp->tov * HZ; /* wait at most tov secs */
191 while (!ha->flags.mbox_int) {
192 if (time_after(jiffies, wait_time))
193 break;
194
195 /* Check for pending interrupts. */
196 qla2x00_poll(ha);
197
andrew.vasquez@qlogic.com59989832006-01-13 17:05:10 -0800198 if (command != MBC_LOAD_RISC_RAM_EXTENDED &&
199 !ha->flags.mbox_int)
200 msleep(10);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 } /* while */
202 }
203
204 if (!abort_active)
205 spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags);
206
207 /* Check whether we timed out */
208 if (ha->flags.mbox_int) {
209 uint16_t *iptr2;
210
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700211 DEBUG3_11(printk("%s(%ld): cmd %x completed.\n", __func__,
212 ha->host_no, command);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213
214 /* Got interrupt. Clear the flag. */
215 ha->flags.mbox_int = 0;
216 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
217
Andrew Vasquez 354d6b22005-04-23 02:47:27 -0400218 if (ha->mailbox_out[0] != MBS_COMMAND_COMPLETE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 rval = QLA_FUNCTION_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220
221 /* Load return mailbox registers. */
222 iptr2 = mcp->mb;
223 iptr = (uint16_t *)&ha->mailbox_out[0];
224 mboxes = mcp->in_mb;
225 for (cnt = 0; cnt < ha->mbx_count; cnt++) {
226 if (mboxes & BIT_0)
227 *iptr2 = *iptr;
228
229 mboxes >>= 1;
230 iptr2++;
231 iptr++;
232 }
233 } else {
234
235#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3) || \
236 defined(QL_DEBUG_LEVEL_11)
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700237 uint16_t mb0;
238 uint32_t ictrl;
239
240 if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
241 mb0 = RD_REG_WORD(&reg->isp24.mailbox0);
242 ictrl = RD_REG_DWORD(&reg->isp24.ictrl);
243 } else {
Andrew Vasquezcca53352005-08-26 19:08:30 -0700244 mb0 = RD_MAILBOX_REG(ha, &reg->isp, 0);
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700245 ictrl = RD_REG_WORD(&reg->isp.ictrl);
246 }
247 printk("%s(%ld): **** MB Command Timeout for cmd %x ****\n",
248 __func__, ha->host_no, command);
249 printk("%s(%ld): icontrol=%x jiffies=%lx\n", __func__,
250 ha->host_no, ictrl, jiffies);
251 printk("%s(%ld): *** mailbox[0] = 0x%x ***\n", __func__,
252 ha->host_no, mb0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 qla2x00_dump_regs(ha);
254#endif
255
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 rval = QLA_FUNCTION_TIMEOUT;
257 }
258
259 if (!abort_active)
260 spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags);
261
262 ha->flags.mbox_busy = 0;
263
264 /* Clean up */
265 ha->mcp = NULL;
266
267 if (!abort_active) {
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700268 DEBUG11(printk("%s(%ld): checking for additional resp "
269 "interrupt.\n", __func__, ha->host_no);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
271 /* polling mode for non isp_abort commands. */
272 qla2x00_poll(ha);
273 }
274
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700275 if (rval == QLA_FUNCTION_TIMEOUT &&
276 mcp->mb[0] != MBC_GEN_SYSTEM_ERROR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 if (!io_lock_on || (mcp->flags & IOCTL_CMD)) {
278 /* not in dpc. schedule it for dpc to take over. */
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700279 DEBUG(printk("%s(%ld): timeout schedule "
280 "isp_abort_needed.\n", __func__, ha->host_no);)
281 DEBUG2_3_11(printk("%s(%ld): timeout schedule "
282 "isp_abort_needed.\n", __func__, ha->host_no);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 qla_printk(KERN_WARNING, ha,
284 "Mailbox command timeout occured. Scheduling ISP "
285 "abort.\n");
286 set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700287 if (ha->dpc_wait && !ha->dpc_active)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 up(ha->dpc_wait);
289
290 } else if (!abort_active) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 /* call abort directly since we are in the DPC thread */
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700292 DEBUG(printk("%s(%ld): timeout calling abort_isp\n",
293 __func__, ha->host_no);)
294 DEBUG2_3_11(printk("%s(%ld): timeout calling "
295 "abort_isp\n", __func__, ha->host_no);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 qla_printk(KERN_WARNING, ha,
297 "Mailbox command timeout occured. Issuing ISP "
298 "abort.\n");
299
300 set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
301 clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
302 if (qla2x00_abort_isp(ha)) {
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700303 /* Failed. retry later. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
305 }
306 clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700307 DEBUG(printk("%s(%ld): finished abort_isp\n", __func__,
308 ha->host_no);)
309 DEBUG2_3_11(printk("%s(%ld): finished abort_isp\n",
310 __func__, ha->host_no);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 }
312 }
313
314 /* Allow next mbx cmd to come in. */
315 if (!abort_active)
316 up(&ha->mbx_cmd_sem);
317
318 if (rval) {
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700319 DEBUG2_3_11(printk("%s(%ld): **** FAILED. mbx0=%x, mbx1=%x, "
320 "mbx2=%x, cmd=%x ****\n", __func__, ha->host_no,
321 mcp->mb[0], mcp->mb[1], mcp->mb[2], command);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 } else {
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700323 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 }
325
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 return rval;
327}
328
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329int
andrew.vasquez@qlogic.com590f98e2006-01-13 17:05:37 -0800330qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr,
331 uint32_t risc_code_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332{
333 int rval;
334 mbx_cmd_t mc;
335 mbx_cmd_t *mcp = &mc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
337 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
338
andrew.vasquez@qlogic.com590f98e2006-01-13 17:05:37 -0800339 if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
340 mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
341 mcp->mb[8] = MSW(risc_addr);
342 mcp->out_mb = MBX_8|MBX_0;
343 } else {
344 mcp->mb[0] = MBC_LOAD_RISC_RAM;
345 mcp->out_mb = MBX_0;
346 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 mcp->mb[1] = LSW(risc_addr);
348 mcp->mb[2] = MSW(req_dma);
349 mcp->mb[3] = LSW(req_dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 mcp->mb[6] = MSW(MSD(req_dma));
351 mcp->mb[7] = LSW(MSD(req_dma));
andrew.vasquez@qlogic.com590f98e2006-01-13 17:05:37 -0800352 mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1;
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700353 if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
354 mcp->mb[4] = MSW(risc_code_size);
355 mcp->mb[5] = LSW(risc_code_size);
356 mcp->out_mb |= MBX_5|MBX_4;
357 } else {
358 mcp->mb[4] = LSW(risc_code_size);
359 mcp->out_mb |= MBX_4;
360 }
361
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 mcp->in_mb = MBX_0;
363 mcp->tov = 30;
364 mcp->flags = 0;
365 rval = qla2x00_mailbox_command(ha, mcp);
366
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 if (rval != QLA_SUCCESS) {
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700368 DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__,
369 ha->host_no, rval, mcp->mb[0]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
372 }
373
374 return rval;
375}
376
377/*
378 * qla2x00_execute_fw
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700379 * Start adapter firmware.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 *
381 * Input:
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700382 * ha = adapter block pointer.
383 * TARGET_QUEUE_LOCK must be released.
384 * ADAPTER_STATE_LOCK must be released.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 *
386 * Returns:
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700387 * qla2x00 local function return status code.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 *
389 * Context:
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700390 * Kernel context.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 */
392int
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700393qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394{
395 int rval;
396 mbx_cmd_t mc;
397 mbx_cmd_t *mcp = &mc;
398
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700399 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
401 mcp->mb[0] = MBC_EXECUTE_FIRMWARE;
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700402 mcp->out_mb = MBX_0;
403 mcp->in_mb = MBX_0;
404 if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
405 mcp->mb[1] = MSW(risc_addr);
406 mcp->mb[2] = LSW(risc_addr);
407 mcp->mb[3] = 0;
408 mcp->out_mb |= MBX_3|MBX_2|MBX_1;
409 mcp->in_mb |= MBX_1;
410 } else {
411 mcp->mb[1] = LSW(risc_addr);
412 mcp->out_mb |= MBX_1;
413 if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
414 mcp->mb[2] = 0;
415 mcp->out_mb |= MBX_2;
416 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 }
418
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 mcp->tov = 30;
420 mcp->flags = 0;
421 rval = qla2x00_mailbox_command(ha, mcp);
422
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700423 if (rval != QLA_SUCCESS) {
424 DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__,
425 ha->host_no, rval, mcp->mb[0]));
426 } else {
427 if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
428 DEBUG11(printk("%s(%ld): done exchanges=%x.\n",
429 __func__, ha->host_no, mcp->mb[1]);)
430 } else {
431 DEBUG11(printk("%s(%ld): done.\n", __func__,
432 ha->host_no);)
433 }
434 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
436 return rval;
437}
438
439/*
440 * qla2x00_get_fw_version
441 * Get firmware version.
442 *
443 * Input:
444 * ha: adapter state pointer.
445 * major: pointer for major number.
446 * minor: pointer for minor number.
447 * subminor: pointer for subminor number.
448 *
449 * Returns:
450 * qla2x00 local function return status code.
451 *
452 * Context:
453 * Kernel context.
454 */
455void
456qla2x00_get_fw_version(scsi_qla_host_t *ha, uint16_t *major, uint16_t *minor,
457 uint16_t *subminor, uint16_t *attributes, uint32_t *memory)
458{
459 int rval;
460 mbx_cmd_t mc;
461 mbx_cmd_t *mcp = &mc;
462
463 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
464
465 mcp->mb[0] = MBC_GET_FIRMWARE_VERSION;
466 mcp->out_mb = MBX_0;
467 mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
468 mcp->flags = 0;
469 mcp->tov = 30;
470 rval = qla2x00_mailbox_command(ha, mcp);
471
472 /* Return mailbox data. */
473 *major = mcp->mb[1];
474 *minor = mcp->mb[2];
475 *subminor = mcp->mb[3];
476 *attributes = mcp->mb[6];
477 if (IS_QLA2100(ha) || IS_QLA2200(ha))
478 *memory = 0x1FFFF; /* Defaults to 128KB. */
479 else
480 *memory = (mcp->mb[5] << 16) | mcp->mb[4];
481
482 if (rval != QLA_SUCCESS) {
483 /*EMPTY*/
484 DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
485 ha->host_no, rval));
486 } else {
487 /*EMPTY*/
488 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
489 }
490}
491
492/*
493 * qla2x00_get_fw_options
494 * Set firmware options.
495 *
496 * Input:
497 * ha = adapter block pointer.
498 * fwopt = pointer for firmware options.
499 *
500 * Returns:
501 * qla2x00 local function return status code.
502 *
503 * Context:
504 * Kernel context.
505 */
506int
507qla2x00_get_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts)
508{
509 int rval;
510 mbx_cmd_t mc;
511 mbx_cmd_t *mcp = &mc;
512
513 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
514
515 mcp->mb[0] = MBC_GET_FIRMWARE_OPTION;
516 mcp->out_mb = MBX_0;
517 mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
518 mcp->tov = 30;
519 mcp->flags = 0;
520 rval = qla2x00_mailbox_command(ha, mcp);
521
522 if (rval != QLA_SUCCESS) {
523 /*EMPTY*/
524 DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
525 ha->host_no, rval));
526 } else {
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700527 fwopts[0] = mcp->mb[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 fwopts[1] = mcp->mb[1];
529 fwopts[2] = mcp->mb[2];
530 fwopts[3] = mcp->mb[3];
531
532 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
533 }
534
535 return rval;
536}
537
538
539/*
540 * qla2x00_set_fw_options
541 * Set firmware options.
542 *
543 * Input:
544 * ha = adapter block pointer.
545 * fwopt = pointer for firmware options.
546 *
547 * Returns:
548 * qla2x00 local function return status code.
549 *
550 * Context:
551 * Kernel context.
552 */
553int
554qla2x00_set_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts)
555{
556 int rval;
557 mbx_cmd_t mc;
558 mbx_cmd_t *mcp = &mc;
559
560 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
561
562 mcp->mb[0] = MBC_SET_FIRMWARE_OPTION;
563 mcp->mb[1] = fwopts[1];
564 mcp->mb[2] = fwopts[2];
565 mcp->mb[3] = fwopts[3];
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700566 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 mcp->in_mb = MBX_0;
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700568 if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
569 mcp->in_mb |= MBX_1;
570 } else {
571 mcp->mb[10] = fwopts[10];
572 mcp->mb[11] = fwopts[11];
573 mcp->mb[12] = 0; /* Undocumented, but used */
574 mcp->out_mb |= MBX_12|MBX_11|MBX_10;
575 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 mcp->tov = 30;
577 mcp->flags = 0;
578 rval = qla2x00_mailbox_command(ha, mcp);
579
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700580 fwopts[0] = mcp->mb[0];
581
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 if (rval != QLA_SUCCESS) {
583 /*EMPTY*/
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700584 DEBUG2_3_11(printk("%s(%ld): failed=%x (%x/%x).\n", __func__,
585 ha->host_no, rval, mcp->mb[0], mcp->mb[1]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 } else {
587 /*EMPTY*/
588 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
589 }
590
591 return rval;
592}
593
594/*
595 * qla2x00_mbx_reg_test
596 * Mailbox register wrap test.
597 *
598 * Input:
599 * ha = adapter block pointer.
600 * TARGET_QUEUE_LOCK must be released.
601 * ADAPTER_STATE_LOCK must be released.
602 *
603 * Returns:
604 * qla2x00 local function return status code.
605 *
606 * Context:
607 * Kernel context.
608 */
609int
610qla2x00_mbx_reg_test(scsi_qla_host_t *ha)
611{
612 int rval;
613 mbx_cmd_t mc;
614 mbx_cmd_t *mcp = &mc;
615
616 DEBUG11(printk("qla2x00_mbx_reg_test(%ld): entered.\n", ha->host_no);)
617
618 mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST;
619 mcp->mb[1] = 0xAAAA;
620 mcp->mb[2] = 0x5555;
621 mcp->mb[3] = 0xAA55;
622 mcp->mb[4] = 0x55AA;
623 mcp->mb[5] = 0xA5A5;
624 mcp->mb[6] = 0x5A5A;
625 mcp->mb[7] = 0x2525;
626 mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
627 mcp->in_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
628 mcp->tov = 30;
629 mcp->flags = 0;
630 rval = qla2x00_mailbox_command(ha, mcp);
631
632 if (rval == QLA_SUCCESS) {
633 if (mcp->mb[1] != 0xAAAA || mcp->mb[2] != 0x5555 ||
634 mcp->mb[3] != 0xAA55 || mcp->mb[4] != 0x55AA)
635 rval = QLA_FUNCTION_FAILED;
636 if (mcp->mb[5] != 0xA5A5 || mcp->mb[6] != 0x5A5A ||
637 mcp->mb[7] != 0x2525)
638 rval = QLA_FUNCTION_FAILED;
639 }
640
641 if (rval != QLA_SUCCESS) {
642 /*EMPTY*/
643 DEBUG2_3_11(printk("qla2x00_mbx_reg_test(%ld): failed=%x.\n",
644 ha->host_no, rval);)
645 } else {
646 /*EMPTY*/
647 DEBUG11(printk("qla2x00_mbx_reg_test(%ld): done.\n",
648 ha->host_no);)
649 }
650
651 return rval;
652}
653
654/*
655 * qla2x00_verify_checksum
656 * Verify firmware checksum.
657 *
658 * Input:
659 * ha = adapter block pointer.
660 * TARGET_QUEUE_LOCK must be released.
661 * ADAPTER_STATE_LOCK must be released.
662 *
663 * Returns:
664 * qla2x00 local function return status code.
665 *
666 * Context:
667 * Kernel context.
668 */
669int
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700670qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671{
672 int rval;
673 mbx_cmd_t mc;
674 mbx_cmd_t *mcp = &mc;
675
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700676 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
678 mcp->mb[0] = MBC_VERIFY_CHECKSUM;
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700679 mcp->out_mb = MBX_0;
680 mcp->in_mb = MBX_0;
681 if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
682 mcp->mb[1] = MSW(risc_addr);
683 mcp->mb[2] = LSW(risc_addr);
684 mcp->out_mb |= MBX_2|MBX_1;
685 mcp->in_mb |= MBX_2|MBX_1;
686 } else {
687 mcp->mb[1] = LSW(risc_addr);
688 mcp->out_mb |= MBX_1;
689 mcp->in_mb |= MBX_1;
690 }
691
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 mcp->tov = 30;
693 mcp->flags = 0;
694 rval = qla2x00_mailbox_command(ha, mcp);
695
696 if (rval != QLA_SUCCESS) {
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700697 DEBUG2_3_11(printk("%s(%ld): failed=%x chk sum=%x.\n", __func__,
698 ha->host_no, rval, (IS_QLA24XX(ha) || IS_QLA25XX(ha) ?
699 (mcp->mb[2] << 16) | mcp->mb[1]: mcp->mb[1]));)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 } else {
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700701 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 }
703
704 return rval;
705}
706
707/*
708 * qla2x00_issue_iocb
709 * Issue IOCB using mailbox command
710 *
711 * Input:
712 * ha = adapter state pointer.
713 * buffer = buffer pointer.
714 * phys_addr = physical address of buffer.
715 * size = size of buffer.
716 * TARGET_QUEUE_LOCK must be released.
717 * ADAPTER_STATE_LOCK must be released.
718 *
719 * Returns:
720 * qla2x00 local function return status code.
721 *
722 * Context:
723 * Kernel context.
724 */
725int
726qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr,
727 size_t size)
728{
729 int rval;
730 mbx_cmd_t mc;
731 mbx_cmd_t *mcp = &mc;
732
733 mcp->mb[0] = MBC_IOCB_COMMAND_A64;
734 mcp->mb[1] = 0;
735 mcp->mb[2] = MSW(phys_addr);
736 mcp->mb[3] = LSW(phys_addr);
737 mcp->mb[6] = MSW(MSD(phys_addr));
738 mcp->mb[7] = LSW(MSD(phys_addr));
739 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
740 mcp->in_mb = MBX_2|MBX_0;
741 mcp->tov = 30;
742 mcp->flags = 0;
743 rval = qla2x00_mailbox_command(ha, mcp);
744
745 if (rval != QLA_SUCCESS) {
746 /*EMPTY*/
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700747 DEBUG(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x\n",
748 ha->host_no, rval);)
749 DEBUG2(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x\n",
750 ha->host_no, rval);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 } else {
Andrew Vasquez8c958a92005-07-06 10:30:47 -0700752 sts_entry_t *sts_entry = (sts_entry_t *) buffer;
753
754 /* Mask reserved bits. */
755 sts_entry->entry_status &=
756 IS_QLA24XX(ha) || IS_QLA25XX(ha) ? RF_MASK_24XX :RF_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 }
758
759 return rval;
760}
761
762/*
763 * qla2x00_abort_command
764 * Abort command aborts a specified IOCB.
765 *
766 * Input:
767 * ha = adapter block pointer.
768 * sp = SB structure pointer.
769 *
770 * Returns:
771 * qla2x00 local function return status code.
772 *
773 * Context:
774 * Kernel context.
775 */
776int
777qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp)
778{
779 unsigned long flags = 0;
780 fc_port_t *fcport;
781 int rval;
782 uint32_t handle;
783 mbx_cmd_t mc;
784 mbx_cmd_t *mcp = &mc;
785
786 DEBUG11(printk("qla2x00_abort_command(%ld): entered.\n", ha->host_no);)
787
bdf79622005-04-17 15:06:53 -0500788 fcport = sp->fcport;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789
790 spin_lock_irqsave(&ha->hardware_lock, flags);
791 for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) {
792 if (ha->outstanding_cmds[handle] == sp)
793 break;
794 }
795 spin_unlock_irqrestore(&ha->hardware_lock, flags);
796
797 if (handle == MAX_OUTSTANDING_COMMANDS) {
798 /* command not found */
799 return QLA_FUNCTION_FAILED;
800 }
801
802 mcp->mb[0] = MBC_ABORT_COMMAND;
803 if (HAS_EXTENDED_IDS(ha))
804 mcp->mb[1] = fcport->loop_id;
805 else
806 mcp->mb[1] = fcport->loop_id << 8;
807 mcp->mb[2] = (uint16_t)handle;
808 mcp->mb[3] = (uint16_t)(handle >> 16);
bdf79622005-04-17 15:06:53 -0500809 mcp->mb[6] = (uint16_t)sp->cmd->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
811 mcp->in_mb = MBX_0;
812 mcp->tov = 30;
813 mcp->flags = 0;
814 rval = qla2x00_mailbox_command(ha, mcp);
815
816 if (rval != QLA_SUCCESS) {
817 DEBUG2_3_11(printk("qla2x00_abort_command(%ld): failed=%x.\n",
818 ha->host_no, rval);)
819 } else {
820 sp->flags |= SRB_ABORT_PENDING;
821 DEBUG11(printk("qla2x00_abort_command(%ld): done.\n",
822 ha->host_no);)
823 }
824
825 return rval;
826}
827
828#if USE_ABORT_TGT
829/*
830 * qla2x00_abort_target
831 * Issue abort target mailbox command.
832 *
833 * Input:
834 * ha = adapter block pointer.
835 *
836 * Returns:
837 * qla2x00 local function return status code.
838 *
839 * Context:
840 * Kernel context.
841 */
842int
843qla2x00_abort_target(fc_port_t *fcport)
844{
845 int rval;
846 mbx_cmd_t mc;
847 mbx_cmd_t *mcp = &mc;
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700848 scsi_qla_host_t *ha;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700850 if (fcport == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700853 DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no);)
854
855 ha = fcport->ha;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 mcp->mb[0] = MBC_ABORT_TARGET;
857 mcp->out_mb = MBX_2|MBX_1|MBX_0;
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700858 if (HAS_EXTENDED_IDS(ha)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 mcp->mb[1] = fcport->loop_id;
860 mcp->mb[10] = 0;
861 mcp->out_mb |= MBX_10;
862 } else {
863 mcp->mb[1] = fcport->loop_id << 8;
864 }
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700865 mcp->mb[2] = ha->loop_reset_delay;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866
867 mcp->in_mb = MBX_0;
868 mcp->tov = 30;
869 mcp->flags = 0;
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700870 rval = qla2x00_mailbox_command(ha, mcp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871
872 /* Issue marker command. */
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700873 ha->marker_needed = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874
875 if (rval != QLA_SUCCESS) {
876 DEBUG2_3_11(printk("qla2x00_abort_target(%ld): failed=%x.\n",
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700877 ha->host_no, rval);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 } else {
879 /*EMPTY*/
880 DEBUG11(printk("qla2x00_abort_target(%ld): done.\n",
Andrew Vasquez1c7c6352005-07-06 10:30:57 -0700881 ha->host_no);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 }
883
884 return rval;
885}
886#endif
887
888/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 * qla2x00_get_adapter_id
890 * Get adapter ID and topology.
891 *
892 * Input:
893 * ha = adapter block pointer.
894 * id = pointer for loop ID.
895 * al_pa = pointer for AL_PA.
896 * area = pointer for area.
897 * domain = pointer for domain.
898 * top = pointer for topology.
899 * TARGET_QUEUE_LOCK must be released.
900 * ADAPTER_STATE_LOCK must be released.
901 *
902 * Returns:
903 * qla2x00 local function return status code.
904 *
905 * Context:
906 * Kernel context.
907 */
908int
909qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa,
910 uint8_t *area, uint8_t *domain, uint16_t *top)
911{
912 int rval;
913 mbx_cmd_t mc;
914 mbx_cmd_t *mcp = &mc;
915
916 DEBUG11(printk("qla2x00_get_adapter_id(%ld): entered.\n",
917 ha->host_no);)
918
919 mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID;
920 mcp->out_mb = MBX_0;
921 mcp->in_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
922 mcp->tov = 30;
923 mcp->flags = 0;
924 rval = qla2x00_mailbox_command(ha, mcp);
Ravi Anand33135aa2005-11-08 14:37:20 -0800925 if (mcp->mb[0] == MBS_COMMAND_ERROR)
926 rval = QLA_COMMAND_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927
928 /* Return data. */
929 *id = mcp->mb[1];
930 *al_pa = LSB(mcp->mb[2]);
931 *area = MSB(mcp->mb[2]);
932 *domain = LSB(mcp->mb[3]);
933 *top = mcp->mb[6];
934
935 if (rval != QLA_SUCCESS) {
936 /*EMPTY*/
937 DEBUG2_3_11(printk("qla2x00_get_adapter_id(%ld): failed=%x.\n",
938 ha->host_no, rval);)
939 } else {
940 /*EMPTY*/
941 DEBUG11(printk("qla2x00_get_adapter_id(%ld): done.\n",
942 ha->host_no);)
943 }
944
945 return rval;
946}
947
948/*
949 * qla2x00_get_retry_cnt
950 * Get current firmware login retry count and delay.
951 *
952 * Input:
953 * ha = adapter block pointer.
954 * retry_cnt = pointer to login retry count.
955 * tov = pointer to login timeout value.
956 *
957 * Returns:
958 * qla2x00 local function return status code.
959 *
960 * Context:
961 * Kernel context.
962 */
963int
964qla2x00_get_retry_cnt(scsi_qla_host_t *ha, uint8_t *retry_cnt, uint8_t *tov,
965 uint16_t *r_a_tov)
966{
967 int rval;
968 uint16_t ratov;
969 mbx_cmd_t mc;
970 mbx_cmd_t *mcp = &mc;
971
972 DEBUG11(printk("qla2x00_get_retry_cnt(%ld): entered.\n",
973 ha->host_no);)
974
975 mcp->mb[0] = MBC_GET_RETRY_COUNT;
976 mcp->out_mb = MBX_0;
977 mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
978 mcp->tov = 30;
979 mcp->flags = 0;
980 rval = qla2x00_mailbox_command(ha, mcp);
981
982 if (rval != QLA_SUCCESS) {
983 /*EMPTY*/
984 DEBUG2_3_11(printk("qla2x00_get_retry_cnt(%ld): failed = %x.\n",
985 ha->host_no, mcp->mb[0]);)
986 } else {
987 /* Convert returned data and check our values. */
988 *r_a_tov = mcp->mb[3] / 2;
989 ratov = (mcp->mb[3]/2) / 10; /* mb[3] value is in 100ms */
990 if (mcp->mb[1] * ratov > (*retry_cnt) * (*tov)) {
991 /* Update to the larger values */
992 *retry_cnt = (uint8_t)mcp->mb[1];
993 *tov = ratov;
994 }
995
996 DEBUG11(printk("qla2x00_get_retry_cnt(%ld): done. mb3=%d "
997 "ratov=%d.\n", ha->host_no, mcp->mb[3], ratov);)
998 }
999
1000 return rval;
1001}
1002
1003/*
1004 * qla2x00_init_firmware
1005 * Initialize adapter firmware.
1006 *
1007 * Input:
1008 * ha = adapter block pointer.
1009 * dptr = Initialization control block pointer.
1010 * size = size of initialization control block.
1011 * TARGET_QUEUE_LOCK must be released.
1012 * ADAPTER_STATE_LOCK must be released.
1013 *
1014 * Returns:
1015 * qla2x00 local function return status code.
1016 *
1017 * Context:
1018 * Kernel context.
1019 */
1020int
1021qla2x00_init_firmware(scsi_qla_host_t *ha, uint16_t size)
1022{
1023 int rval;
1024 mbx_cmd_t mc;
1025 mbx_cmd_t *mcp = &mc;
1026
1027 DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n",
1028 ha->host_no);)
1029
1030 mcp->mb[0] = MBC_INITIALIZE_FIRMWARE;
1031 mcp->mb[2] = MSW(ha->init_cb_dma);
1032 mcp->mb[3] = LSW(ha->init_cb_dma);
1033 mcp->mb[4] = 0;
1034 mcp->mb[5] = 0;
1035 mcp->mb[6] = MSW(MSD(ha->init_cb_dma));
1036 mcp->mb[7] = LSW(MSD(ha->init_cb_dma));
1037 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
1038 mcp->in_mb = MBX_5|MBX_4|MBX_0;
1039 mcp->buf_size = size;
1040 mcp->flags = MBX_DMA_OUT;
1041 mcp->tov = 30;
1042 rval = qla2x00_mailbox_command(ha, mcp);
1043
1044 if (rval != QLA_SUCCESS) {
1045 /*EMPTY*/
1046 DEBUG2_3_11(printk("qla2x00_init_firmware(%ld): failed=%x "
1047 "mb0=%x.\n",
1048 ha->host_no, rval, mcp->mb[0]);)
1049 } else {
1050 /*EMPTY*/
1051 DEBUG11(printk("qla2x00_init_firmware(%ld): done.\n",
1052 ha->host_no);)
1053 }
1054
1055 return rval;
1056}
1057
1058/*
1059 * qla2x00_get_port_database
1060 * Issue normal/enhanced get port database mailbox command
1061 * and copy device name as necessary.
1062 *
1063 * Input:
1064 * ha = adapter state pointer.
1065 * dev = structure pointer.
1066 * opt = enhanced cmd option byte.
1067 *
1068 * Returns:
1069 * qla2x00 local function return status code.
1070 *
1071 * Context:
1072 * Kernel context.
1073 */
1074int
1075qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt)
1076{
1077 int rval;
1078 mbx_cmd_t mc;
1079 mbx_cmd_t *mcp = &mc;
1080 port_database_t *pd;
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001081 struct port_database_24xx *pd24;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 dma_addr_t pd_dma;
1083
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001084 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001086 pd24 = NULL;
1087 pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 if (pd == NULL) {
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001089 DEBUG2_3(printk("%s(%ld): failed to allocate Port Database "
1090 "structure.\n", __func__, ha->host_no));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 return QLA_MEMORY_ALLOC_FAILED;
1092 }
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001093 memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001095 mcp->mb[0] = MBC_GET_PORT_DATABASE;
1096 if (opt != 0 && !IS_QLA24XX(ha) && !IS_QLA25XX(ha))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 mcp->mb[2] = MSW(pd_dma);
1099 mcp->mb[3] = LSW(pd_dma);
1100 mcp->mb[6] = MSW(MSD(pd_dma));
1101 mcp->mb[7] = LSW(MSD(pd_dma));
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001102 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 mcp->in_mb = MBX_0;
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001104 if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
1105 mcp->mb[1] = fcport->loop_id;
1106 mcp->mb[10] = opt;
1107 mcp->out_mb |= MBX_10|MBX_1;
1108 mcp->in_mb |= MBX_1;
1109 } else if (HAS_EXTENDED_IDS(ha)) {
1110 mcp->mb[1] = fcport->loop_id;
1111 mcp->mb[10] = opt;
1112 mcp->out_mb |= MBX_10|MBX_1;
1113 } else {
1114 mcp->mb[1] = fcport->loop_id << 8 | opt;
1115 mcp->out_mb |= MBX_1;
1116 }
1117 mcp->buf_size = (IS_QLA24XX(ha) || IS_QLA25XX(ha) ?
1118 PORT_DATABASE_24XX_SIZE : PORT_DATABASE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 mcp->flags = MBX_DMA_IN;
1120 mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
1121 rval = qla2x00_mailbox_command(ha, mcp);
1122 if (rval != QLA_SUCCESS)
1123 goto gpd_error_out;
1124
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001125 if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
1126 pd24 = (struct port_database_24xx *) pd;
1127
1128 /* Check for logged in state. */
1129 if (pd24->current_login_state != PDS_PRLI_COMPLETE &&
1130 pd24->last_login_state != PDS_PRLI_COMPLETE) {
1131 DEBUG2(printk("%s(%ld): Unable to verify "
1132 "login-state (%x/%x) for loop_id %x\n",
1133 __func__, ha->host_no,
1134 pd24->current_login_state,
1135 pd24->last_login_state, fcport->loop_id));
1136 rval = QLA_FUNCTION_FAILED;
1137 goto gpd_error_out;
1138 }
1139
1140 /* Names are little-endian. */
1141 memcpy(fcport->node_name, pd24->node_name, WWN_SIZE);
1142 memcpy(fcport->port_name, pd24->port_name, WWN_SIZE);
1143
1144 /* Get port_id of device. */
1145 fcport->d_id.b.domain = pd24->port_id[0];
1146 fcport->d_id.b.area = pd24->port_id[1];
1147 fcport->d_id.b.al_pa = pd24->port_id[2];
1148 fcport->d_id.b.rsvd_1 = 0;
1149
1150 /* If not target must be initiator or unknown type. */
1151 if ((pd24->prli_svc_param_word_3[0] & BIT_4) == 0)
1152 fcport->port_type = FCT_INITIATOR;
1153 else
1154 fcport->port_type = FCT_TARGET;
1155 } else {
1156 /* Check for logged in state. */
1157 if (pd->master_state != PD_STATE_PORT_LOGGED_IN &&
1158 pd->slave_state != PD_STATE_PORT_LOGGED_IN) {
1159 rval = QLA_FUNCTION_FAILED;
1160 goto gpd_error_out;
1161 }
1162
1163 /* Names are little-endian. */
1164 memcpy(fcport->node_name, pd->node_name, WWN_SIZE);
1165 memcpy(fcport->port_name, pd->port_name, WWN_SIZE);
1166
1167 /* Get port_id of device. */
1168 fcport->d_id.b.domain = pd->port_id[0];
1169 fcport->d_id.b.area = pd->port_id[3];
1170 fcport->d_id.b.al_pa = pd->port_id[2];
1171 fcport->d_id.b.rsvd_1 = 0;
1172
1173 /* Check for device require authentication. */
1174 pd->common_features & BIT_5 ? (fcport->flags |= FCF_AUTH_REQ) :
1175 (fcport->flags &= ~FCF_AUTH_REQ);
1176
1177 /* If not target must be initiator or unknown type. */
1178 if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
1179 fcport->port_type = FCT_INITIATOR;
1180 else
1181 fcport->port_type = FCT_TARGET;
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07001182
1183 /* Passback COS information. */
1184 fcport->supported_classes = (pd->options & BIT_4) ?
1185 FC_COS_CLASS2: FC_COS_CLASS3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 }
1187
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188gpd_error_out:
1189 dma_pool_free(ha->s_dma_pool, pd, pd_dma);
1190
1191 if (rval != QLA_SUCCESS) {
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001192 DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
1193 __func__, ha->host_no, rval, mcp->mb[0], mcp->mb[1]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 } else {
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001195 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 }
1197
1198 return rval;
1199}
1200
1201/*
1202 * qla2x00_get_firmware_state
1203 * Get adapter firmware state.
1204 *
1205 * Input:
1206 * ha = adapter block pointer.
1207 * dptr = pointer for firmware state.
1208 * TARGET_QUEUE_LOCK must be released.
1209 * ADAPTER_STATE_LOCK must be released.
1210 *
1211 * Returns:
1212 * qla2x00 local function return status code.
1213 *
1214 * Context:
1215 * Kernel context.
1216 */
1217int
1218qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr)
1219{
1220 int rval;
1221 mbx_cmd_t mc;
1222 mbx_cmd_t *mcp = &mc;
1223
1224 DEBUG11(printk("qla2x00_get_firmware_state(%ld): entered.\n",
1225 ha->host_no);)
1226
1227 mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
1228 mcp->out_mb = MBX_0;
1229 mcp->in_mb = MBX_2|MBX_1|MBX_0;
1230 mcp->tov = 30;
1231 mcp->flags = 0;
1232 rval = qla2x00_mailbox_command(ha, mcp);
1233
1234 /* Return firmware state. */
1235 *dptr = mcp->mb[1];
1236
1237 if (rval != QLA_SUCCESS) {
1238 /*EMPTY*/
1239 DEBUG2_3_11(printk("qla2x00_get_firmware_state(%ld): "
1240 "failed=%x.\n", ha->host_no, rval);)
1241 } else {
1242 /*EMPTY*/
1243 DEBUG11(printk("qla2x00_get_firmware_state(%ld): done.\n",
1244 ha->host_no);)
1245 }
1246
1247 return rval;
1248}
1249
1250/*
1251 * qla2x00_get_port_name
1252 * Issue get port name mailbox command.
1253 * Returned name is in big endian format.
1254 *
1255 * Input:
1256 * ha = adapter block pointer.
1257 * loop_id = loop ID of device.
1258 * name = pointer for name.
1259 * TARGET_QUEUE_LOCK must be released.
1260 * ADAPTER_STATE_LOCK must be released.
1261 *
1262 * Returns:
1263 * qla2x00 local function return status code.
1264 *
1265 * Context:
1266 * Kernel context.
1267 */
1268int
1269qla2x00_get_port_name(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t *name,
1270 uint8_t opt)
1271{
1272 int rval;
1273 mbx_cmd_t mc;
1274 mbx_cmd_t *mcp = &mc;
1275
1276 DEBUG11(printk("qla2x00_get_port_name(%ld): entered.\n",
1277 ha->host_no);)
1278
1279 mcp->mb[0] = MBC_GET_PORT_NAME;
1280 mcp->out_mb = MBX_1|MBX_0;
1281 if (HAS_EXTENDED_IDS(ha)) {
1282 mcp->mb[1] = loop_id;
1283 mcp->mb[10] = opt;
1284 mcp->out_mb |= MBX_10;
1285 } else {
1286 mcp->mb[1] = loop_id << 8 | opt;
1287 }
1288
1289 mcp->in_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
1290 mcp->tov = 30;
1291 mcp->flags = 0;
1292 rval = qla2x00_mailbox_command(ha, mcp);
1293
1294 if (rval != QLA_SUCCESS) {
1295 /*EMPTY*/
1296 DEBUG2_3_11(printk("qla2x00_get_port_name(%ld): failed=%x.\n",
1297 ha->host_no, rval);)
1298 } else {
1299 if (name != NULL) {
1300 /* This function returns name in big endian. */
1301 name[0] = LSB(mcp->mb[2]);
1302 name[1] = MSB(mcp->mb[2]);
1303 name[2] = LSB(mcp->mb[3]);
1304 name[3] = MSB(mcp->mb[3]);
1305 name[4] = LSB(mcp->mb[6]);
1306 name[5] = MSB(mcp->mb[6]);
1307 name[6] = LSB(mcp->mb[7]);
1308 name[7] = MSB(mcp->mb[7]);
1309 }
1310
1311 DEBUG11(printk("qla2x00_get_port_name(%ld): done.\n",
1312 ha->host_no);)
1313 }
1314
1315 return rval;
1316}
1317
1318/*
1319 * qla2x00_lip_reset
1320 * Issue LIP reset mailbox command.
1321 *
1322 * Input:
1323 * ha = adapter block pointer.
1324 * TARGET_QUEUE_LOCK must be released.
1325 * ADAPTER_STATE_LOCK must be released.
1326 *
1327 * Returns:
1328 * qla2x00 local function return status code.
1329 *
1330 * Context:
1331 * Kernel context.
1332 */
1333int
1334qla2x00_lip_reset(scsi_qla_host_t *ha)
1335{
1336 int rval;
1337 mbx_cmd_t mc;
1338 mbx_cmd_t *mcp = &mc;
1339
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001340 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001342 if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
1343 mcp->mb[0] = MBC_LIP_FULL_LOGIN;
1344 mcp->mb[1] = BIT_0;
1345 mcp->mb[2] = 0xff;
1346 mcp->mb[3] = 0;
1347 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 } else {
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001349 mcp->mb[0] = MBC_LIP_RESET;
1350 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
1351 if (HAS_EXTENDED_IDS(ha)) {
1352 mcp->mb[1] = 0x00ff;
1353 mcp->mb[10] = 0;
1354 mcp->out_mb |= MBX_10;
1355 } else {
1356 mcp->mb[1] = 0xff00;
1357 }
1358 mcp->mb[2] = ha->loop_reset_delay;
1359 mcp->mb[3] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 mcp->in_mb = MBX_0;
1362 mcp->tov = 30;
1363 mcp->flags = 0;
1364 rval = qla2x00_mailbox_command(ha, mcp);
1365
1366 if (rval != QLA_SUCCESS) {
1367 /*EMPTY*/
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001368 DEBUG2_3_11(printk("%s(%ld): failed=%x.\n",
1369 __func__, ha->host_no, rval);)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 } else {
1371 /*EMPTY*/
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001372 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 }
1374
1375 return rval;
1376}
1377
1378/*
1379 * qla2x00_send_sns
1380 * Send SNS command.
1381 *
1382 * Input:
1383 * ha = adapter block pointer.
1384 * sns = pointer for command.
1385 * cmd_size = command size.
1386 * buf_size = response/command size.
1387 * TARGET_QUEUE_LOCK must be released.
1388 * ADAPTER_STATE_LOCK must be released.
1389 *
1390 * Returns:
1391 * qla2x00 local function return status code.
1392 *
1393 * Context:
1394 * Kernel context.
1395 */
1396int
1397qla2x00_send_sns(scsi_qla_host_t *ha, dma_addr_t sns_phys_address,
1398 uint16_t cmd_size, size_t buf_size)
1399{
1400 int rval;
1401 mbx_cmd_t mc;
1402 mbx_cmd_t *mcp = &mc;
1403
1404 DEBUG11(printk("qla2x00_send_sns(%ld): entered.\n",
1405 ha->host_no);)
1406
1407 DEBUG11(printk("qla2x00_send_sns: retry cnt=%d ratov=%d total "
1408 "tov=%d.\n", ha->retry_count, ha->login_timeout, mcp->tov);)
1409
1410 mcp->mb[0] = MBC_SEND_SNS_COMMAND;
1411 mcp->mb[1] = cmd_size;
1412 mcp->mb[2] = MSW(sns_phys_address);
1413 mcp->mb[3] = LSW(sns_phys_address);
1414 mcp->mb[6] = MSW(MSD(sns_phys_address));
1415 mcp->mb[7] = LSW(MSD(sns_phys_address));
1416 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
1417 mcp->in_mb = MBX_0|MBX_1;
1418 mcp->buf_size = buf_size;
1419 mcp->flags = MBX_DMA_OUT|MBX_DMA_IN;
1420 mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
1421 rval = qla2x00_mailbox_command(ha, mcp);
1422
1423 if (rval != QLA_SUCCESS) {
1424 /*EMPTY*/
1425 DEBUG(printk("qla2x00_send_sns(%ld): failed=%x mb[0]=%x "
1426 "mb[1]=%x.\n", ha->host_no, rval, mcp->mb[0], mcp->mb[1]);)
1427 DEBUG2_3_11(printk("qla2x00_send_sns(%ld): failed=%x mb[0]=%x "
1428 "mb[1]=%x.\n", ha->host_no, rval, mcp->mb[0], mcp->mb[1]);)
1429 } else {
1430 /*EMPTY*/
1431 DEBUG11(printk("qla2x00_send_sns(%ld): done.\n", ha->host_no);)
1432 }
1433
1434 return rval;
1435}
1436
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001437int
1438qla24xx_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
1439 uint8_t area, uint8_t al_pa, uint16_t *mb, uint8_t opt)
1440{
1441 int rval;
1442
1443 struct logio_entry_24xx *lg;
1444 dma_addr_t lg_dma;
1445 uint32_t iop[2];
1446
1447 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
1448
1449 lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
1450 if (lg == NULL) {
1451 DEBUG2_3(printk("%s(%ld): failed to allocate Login IOCB.\n",
1452 __func__, ha->host_no));
1453 return QLA_MEMORY_ALLOC_FAILED;
1454 }
1455 memset(lg, 0, sizeof(struct logio_entry_24xx));
1456
1457 lg->entry_type = LOGINOUT_PORT_IOCB_TYPE;
1458 lg->entry_count = 1;
1459 lg->nport_handle = cpu_to_le16(loop_id);
1460 lg->control_flags = __constant_cpu_to_le16(LCF_COMMAND_PLOGI);
1461 if (opt & BIT_0)
1462 lg->control_flags |= __constant_cpu_to_le16(LCF_COND_PLOGI);
1463 lg->port_id[0] = al_pa;
1464 lg->port_id[1] = area;
1465 lg->port_id[2] = domain;
1466 rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0);
1467 if (rval != QLA_SUCCESS) {
1468 DEBUG2_3_11(printk("%s(%ld): failed to issue Login IOCB "
1469 "(%x).\n", __func__, ha->host_no, rval);)
1470 } else if (lg->entry_status != 0) {
1471 DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
1472 "-- error status (%x).\n", __func__, ha->host_no,
1473 lg->entry_status));
1474 rval = QLA_FUNCTION_FAILED;
1475 } else if (lg->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
1476 iop[0] = le32_to_cpu(lg->io_parameter[0]);
1477 iop[1] = le32_to_cpu(lg->io_parameter[1]);
1478
1479 DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
1480 "-- completion status (%x) ioparam=%x/%x.\n", __func__,
1481 ha->host_no, le16_to_cpu(lg->comp_status), iop[0],
1482 iop[1]));
1483
1484 switch (iop[0]) {
1485 case LSC_SCODE_PORTID_USED:
1486 mb[0] = MBS_PORT_ID_USED;
1487 mb[1] = LSW(iop[1]);
1488 break;
1489 case LSC_SCODE_NPORT_USED:
1490 mb[0] = MBS_LOOP_ID_USED;
1491 break;
1492 case LSC_SCODE_NOLINK:
1493 case LSC_SCODE_NOIOCB:
1494 case LSC_SCODE_NOXCB:
1495 case LSC_SCODE_CMD_FAILED:
1496 case LSC_SCODE_NOFABRIC:
1497 case LSC_SCODE_FW_NOT_READY:
1498 case LSC_SCODE_NOT_LOGGED_IN:
1499 case LSC_SCODE_NOPCB:
1500 case LSC_SCODE_ELS_REJECT:
1501 case LSC_SCODE_CMD_PARAM_ERR:
1502 case LSC_SCODE_NONPORT:
1503 case LSC_SCODE_LOGGED_IN:
1504 case LSC_SCODE_NOFLOGI_ACC:
1505 default:
1506 mb[0] = MBS_COMMAND_ERROR;
1507 break;
1508 }
1509 } else {
1510 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);)
1511
1512 iop[0] = le32_to_cpu(lg->io_parameter[0]);
1513
1514 mb[0] = MBS_COMMAND_COMPLETE;
1515 mb[1] = 0;
1516 if (iop[0] & BIT_4) {
1517 if (iop[0] & BIT_8)
1518 mb[1] |= BIT_1;
1519 } else
1520 mb[1] = BIT_0;
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07001521
1522 /* Passback COS information. */
1523 mb[10] = 0;
1524 if (lg->io_parameter[7] || lg->io_parameter[8])
1525 mb[10] |= BIT_0; /* Class 2. */
1526 if (lg->io_parameter[9] || lg->io_parameter[10])
1527 mb[10] |= BIT_1; /* Class 3. */
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001528 }
1529
1530 dma_pool_free(ha->s_dma_pool, lg, lg_dma);
1531
1532 return rval;
1533}
1534
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535/*
1536 * qla2x00_login_fabric
1537 * Issue login fabric port mailbox command.
1538 *
1539 * Input:
1540 * ha = adapter block pointer.
1541 * loop_id = device loop ID.
1542 * domain = device domain.
1543 * area = device area.
1544 * al_pa = device AL_PA.
1545 * status = pointer for return status.
1546 * opt = command options.
1547 * TARGET_QUEUE_LOCK must be released.
1548 * ADAPTER_STATE_LOCK must be released.
1549 *
1550 * Returns:
1551 * qla2x00 local function return status code.
1552 *
1553 * Context:
1554 * Kernel context.
1555 */
1556int
1557qla2x00_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
1558 uint8_t area, uint8_t al_pa, uint16_t *mb, uint8_t opt)
1559{
1560 int rval;
1561 mbx_cmd_t mc;
1562 mbx_cmd_t *mcp = &mc;
1563
1564 DEBUG11(printk("qla2x00_login_fabric(%ld): entered.\n", ha->host_no);)
1565
1566 mcp->mb[0] = MBC_LOGIN_FABRIC_PORT;
1567 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
1568 if (HAS_EXTENDED_IDS(ha)) {
1569 mcp->mb[1] = loop_id;
1570 mcp->mb[10] = opt;
1571 mcp->out_mb |= MBX_10;
1572 } else {
1573 mcp->mb[1] = (loop_id << 8) | opt;
1574 }
1575 mcp->mb[2] = domain;
1576 mcp->mb[3] = area << 8 | al_pa;
1577
1578 mcp->in_mb = MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
1579 mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
1580 mcp->flags = 0;
1581 rval = qla2x00_mailbox_command(ha, mcp);
1582
1583 /* Return mailbox statuses. */
1584 if (mb != NULL) {
1585 mb[0] = mcp->mb[0];
1586 mb[1] = mcp->mb[1];
1587 mb[2] = mcp->mb[2];
1588 mb[6] = mcp->mb[6];
1589 mb[7] = mcp->mb[7];
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07001590 /* COS retrieved from Get-Port-Database mailbox command. */
1591 mb[10] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 }
1593
1594 if (rval != QLA_SUCCESS) {
1595 /* RLU tmp code: need to change main mailbox_command function to
1596 * return ok even when the mailbox completion value is not
1597 * SUCCESS. The caller needs to be responsible to interpret
1598 * the return values of this mailbox command if we're not
1599 * to change too much of the existing code.
1600 */
1601 if (mcp->mb[0] == 0x4001 || mcp->mb[0] == 0x4002 ||
1602 mcp->mb[0] == 0x4003 || mcp->mb[0] == 0x4005 ||
1603 mcp->mb[0] == 0x4006)
1604 rval = QLA_SUCCESS;
1605
1606 /*EMPTY*/
1607 DEBUG2_3_11(printk("qla2x00_login_fabric(%ld): failed=%x "
1608 "mb[0]=%x mb[1]=%x mb[2]=%x.\n", ha->host_no, rval,
1609 mcp->mb[0], mcp->mb[1], mcp->mb[2]);)
1610 } else {
1611 /*EMPTY*/
1612 DEBUG11(printk("qla2x00_login_fabric(%ld): done.\n",
1613 ha->host_no);)
1614 }
1615
1616 return rval;
1617}
1618
1619/*
1620 * qla2x00_login_local_device
1621 * Issue login loop port mailbox command.
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07001622 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 * Input:
1624 * ha = adapter block pointer.
1625 * loop_id = device loop ID.
1626 * opt = command options.
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07001627 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 * Returns:
1629 * Return status code.
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07001630 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 * Context:
1632 * Kernel context.
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07001633 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 */
1635int
1636qla2x00_login_local_device(scsi_qla_host_t *ha, uint16_t loop_id,
1637 uint16_t *mb_ret, uint8_t opt)
1638{
1639 int rval;
1640 mbx_cmd_t mc;
1641 mbx_cmd_t *mcp = &mc;
1642
1643 DEBUG3(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
1644
1645 mcp->mb[0] = MBC_LOGIN_LOOP_PORT;
1646 if (HAS_EXTENDED_IDS(ha))
1647 mcp->mb[1] = loop_id;
1648 else
1649 mcp->mb[1] = loop_id << 8;
1650 mcp->mb[2] = opt;
1651 mcp->out_mb = MBX_2|MBX_1|MBX_0;
1652 mcp->in_mb = MBX_7|MBX_6|MBX_1|MBX_0;
1653 mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
1654 mcp->flags = 0;
1655 rval = qla2x00_mailbox_command(ha, mcp);
1656
1657 /* Return mailbox statuses. */
1658 if (mb_ret != NULL) {
1659 mb_ret[0] = mcp->mb[0];
1660 mb_ret[1] = mcp->mb[1];
1661 mb_ret[6] = mcp->mb[6];
1662 mb_ret[7] = mcp->mb[7];
1663 }
1664
1665 if (rval != QLA_SUCCESS) {
1666 /* AV tmp code: need to change main mailbox_command function to
1667 * return ok even when the mailbox completion value is not
1668 * SUCCESS. The caller needs to be responsible to interpret
1669 * the return values of this mailbox command if we're not
1670 * to change too much of the existing code.
1671 */
1672 if (mcp->mb[0] == 0x4005 || mcp->mb[0] == 0x4006)
1673 rval = QLA_SUCCESS;
1674
1675 DEBUG(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x "
1676 "mb[6]=%x mb[7]=%x.\n", __func__, ha->host_no, rval,
1677 mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]);)
1678 DEBUG2_3(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x "
1679 "mb[6]=%x mb[7]=%x.\n", __func__, ha->host_no, rval,
1680 mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]);)
1681 } else {
1682 /*EMPTY*/
1683 DEBUG3(printk("%s(%ld): done.\n", __func__, ha->host_no);)
1684 }
1685
1686 return (rval);
1687}
1688
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001689int
1690qla24xx_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
1691 uint8_t area, uint8_t al_pa)
1692{
1693 int rval;
1694 struct logio_entry_24xx *lg;
1695 dma_addr_t lg_dma;
1696
1697 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
1698
1699 lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
1700 if (lg == NULL) {
1701 DEBUG2_3(printk("%s(%ld): failed to allocate Logout IOCB.\n",
1702 __func__, ha->host_no));
1703 return QLA_MEMORY_ALLOC_FAILED;
1704 }
1705 memset(lg, 0, sizeof(struct logio_entry_24xx));
1706
1707 lg->entry_type = LOGINOUT_PORT_IOCB_TYPE;
1708 lg->entry_count = 1;
1709 lg->nport_handle = cpu_to_le16(loop_id);
1710 lg->control_flags =
1711 __constant_cpu_to_le16(LCF_COMMAND_LOGO|LCF_EXPL_LOGO);
1712 lg->port_id[0] = al_pa;
1713 lg->port_id[1] = area;
1714 lg->port_id[2] = domain;
1715 rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0);
1716 if (rval != QLA_SUCCESS) {
1717 DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB "
1718 "(%x).\n", __func__, ha->host_no, rval);)
1719 } else if (lg->entry_status != 0) {
1720 DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
1721 "-- error status (%x).\n", __func__, ha->host_no,
1722 lg->entry_status));
1723 rval = QLA_FUNCTION_FAILED;
1724 } else if (lg->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
1725 DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
1726 "-- completion status (%x) ioparam=%x/%x.\n", __func__,
1727 ha->host_no, le16_to_cpu(lg->comp_status),
1728 le32_to_cpu(lg->io_parameter[0]),
1729 le32_to_cpu(lg->io_parameter[1]));)
1730 } else {
1731 /*EMPTY*/
1732 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);)
1733 }
1734
1735 dma_pool_free(ha->s_dma_pool, lg, lg_dma);
1736
1737 return rval;
1738}
1739
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740/*
1741 * qla2x00_fabric_logout
1742 * Issue logout fabric port mailbox command.
1743 *
1744 * Input:
1745 * ha = adapter block pointer.
1746 * loop_id = device loop ID.
1747 * TARGET_QUEUE_LOCK must be released.
1748 * ADAPTER_STATE_LOCK must be released.
1749 *
1750 * Returns:
1751 * qla2x00 local function return status code.
1752 *
1753 * Context:
1754 * Kernel context.
1755 */
1756int
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001757qla2x00_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
1758 uint8_t area, uint8_t al_pa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759{
1760 int rval;
1761 mbx_cmd_t mc;
1762 mbx_cmd_t *mcp = &mc;
1763
1764 DEBUG11(printk("qla2x00_fabric_logout(%ld): entered.\n",
1765 ha->host_no);)
1766
1767 mcp->mb[0] = MBC_LOGOUT_FABRIC_PORT;
1768 mcp->out_mb = MBX_1|MBX_0;
1769 if (HAS_EXTENDED_IDS(ha)) {
1770 mcp->mb[1] = loop_id;
1771 mcp->mb[10] = 0;
1772 mcp->out_mb |= MBX_10;
1773 } else {
1774 mcp->mb[1] = loop_id << 8;
1775 }
1776
1777 mcp->in_mb = MBX_1|MBX_0;
1778 mcp->tov = 30;
1779 mcp->flags = 0;
1780 rval = qla2x00_mailbox_command(ha, mcp);
1781
1782 if (rval != QLA_SUCCESS) {
1783 /*EMPTY*/
1784 DEBUG2_3_11(printk("qla2x00_fabric_logout(%ld): failed=%x "
1785 "mbx1=%x.\n", ha->host_no, rval, mcp->mb[1]);)
1786 } else {
1787 /*EMPTY*/
1788 DEBUG11(printk("qla2x00_fabric_logout(%ld): done.\n",
1789 ha->host_no);)
1790 }
1791
1792 return rval;
1793}
1794
1795/*
1796 * qla2x00_full_login_lip
1797 * Issue full login LIP mailbox command.
1798 *
1799 * Input:
1800 * ha = adapter block pointer.
1801 * TARGET_QUEUE_LOCK must be released.
1802 * ADAPTER_STATE_LOCK must be released.
1803 *
1804 * Returns:
1805 * qla2x00 local function return status code.
1806 *
1807 * Context:
1808 * Kernel context.
1809 */
1810int
1811qla2x00_full_login_lip(scsi_qla_host_t *ha)
1812{
1813 int rval;
1814 mbx_cmd_t mc;
1815 mbx_cmd_t *mcp = &mc;
1816
1817 DEBUG11(printk("qla2x00_full_login_lip(%ld): entered.\n",
1818 ha->host_no);)
1819
1820 mcp->mb[0] = MBC_LIP_FULL_LOGIN;
1821 mcp->mb[1] = 0;
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001822 mcp->mb[2] = 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 mcp->mb[3] = 0;
1824 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
1825 mcp->in_mb = MBX_0;
1826 mcp->tov = 30;
1827 mcp->flags = 0;
1828 rval = qla2x00_mailbox_command(ha, mcp);
1829
1830 if (rval != QLA_SUCCESS) {
1831 /*EMPTY*/
1832 DEBUG2_3_11(printk("qla2x00_full_login_lip(%ld): failed=%x.\n",
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001833 ha->host_no, rval);)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 } else {
1835 /*EMPTY*/
1836 DEBUG11(printk("qla2x00_full_login_lip(%ld): done.\n",
1837 ha->host_no);)
1838 }
1839
1840 return rval;
1841}
1842
1843/*
1844 * qla2x00_get_id_list
1845 *
1846 * Input:
1847 * ha = adapter block pointer.
1848 *
1849 * Returns:
1850 * qla2x00 local function return status code.
1851 *
1852 * Context:
1853 * Kernel context.
1854 */
1855int
1856qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma,
1857 uint16_t *entries)
1858{
1859 int rval;
1860 mbx_cmd_t mc;
1861 mbx_cmd_t *mcp = &mc;
1862
1863 DEBUG11(printk("qla2x00_get_id_list(%ld): entered.\n",
1864 ha->host_no);)
1865
1866 if (id_list == NULL)
1867 return QLA_FUNCTION_FAILED;
1868
1869 mcp->mb[0] = MBC_GET_ID_LIST;
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07001870 mcp->out_mb = MBX_0;
1871 if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
1872 mcp->mb[2] = MSW(id_list_dma);
1873 mcp->mb[3] = LSW(id_list_dma);
1874 mcp->mb[6] = MSW(MSD(id_list_dma));
1875 mcp->mb[7] = LSW(MSD(id_list_dma));
1876 mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2;
1877 } else {
1878 mcp->mb[1] = MSW(id_list_dma);
1879 mcp->mb[2] = LSW(id_list_dma);
1880 mcp->mb[3] = MSW(MSD(id_list_dma));
1881 mcp->mb[6] = LSW(MSD(id_list_dma));
1882 mcp->out_mb |= MBX_6|MBX_3|MBX_2|MBX_1;
1883 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 mcp->in_mb = MBX_1|MBX_0;
1885 mcp->tov = 30;
1886 mcp->flags = 0;
1887 rval = qla2x00_mailbox_command(ha, mcp);
1888
1889 if (rval != QLA_SUCCESS) {
1890 /*EMPTY*/
1891 DEBUG2_3_11(printk("qla2x00_get_id_list(%ld): failed=%x.\n",
1892 ha->host_no, rval);)
1893 } else {
1894 *entries = mcp->mb[1];
1895 DEBUG11(printk("qla2x00_get_id_list(%ld): done.\n",
1896 ha->host_no);)
1897 }
1898
1899 return rval;
1900}
1901
1902/*
1903 * qla2x00_get_resource_cnts
1904 * Get current firmware resource counts.
1905 *
1906 * Input:
1907 * ha = adapter block pointer.
1908 *
1909 * Returns:
1910 * qla2x00 local function return status code.
1911 *
1912 * Context:
1913 * Kernel context.
1914 */
1915int
1916qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt,
1917 uint16_t *orig_xchg_cnt, uint16_t *cur_iocb_cnt, uint16_t *orig_iocb_cnt)
1918{
1919 int rval;
1920 mbx_cmd_t mc;
1921 mbx_cmd_t *mcp = &mc;
1922
1923 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
1924
1925 mcp->mb[0] = MBC_GET_RESOURCE_COUNTS;
1926 mcp->out_mb = MBX_0;
1927 mcp->in_mb = MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
1928 mcp->tov = 30;
1929 mcp->flags = 0;
1930 rval = qla2x00_mailbox_command(ha, mcp);
1931
1932 if (rval != QLA_SUCCESS) {
1933 /*EMPTY*/
1934 DEBUG2_3_11(printk("%s(%ld): failed = %x.\n", __func__,
1935 ha->host_no, mcp->mb[0]);)
1936 } else {
1937 DEBUG11(printk("%s(%ld): done. mb1=%x mb2=%x mb3=%x mb6=%x "
1938 "mb7=%x mb10=%x.\n", __func__, ha->host_no,
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07001939 mcp->mb[1], mcp->mb[2], mcp->mb[3], mcp->mb[6], mcp->mb[7],
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 mcp->mb[10]));
1941
1942 if (cur_xchg_cnt)
1943 *cur_xchg_cnt = mcp->mb[3];
1944 if (orig_xchg_cnt)
1945 *orig_xchg_cnt = mcp->mb[6];
1946 if (cur_iocb_cnt)
1947 *cur_iocb_cnt = mcp->mb[7];
1948 if (orig_iocb_cnt)
1949 *orig_iocb_cnt = mcp->mb[10];
1950 }
1951
1952 return (rval);
1953}
1954
1955#if defined(QL_DEBUG_LEVEL_3)
1956/*
1957 * qla2x00_get_fcal_position_map
1958 * Get FCAL (LILP) position map using mailbox command
1959 *
1960 * Input:
1961 * ha = adapter state pointer.
1962 * pos_map = buffer pointer (can be NULL).
1963 *
1964 * Returns:
1965 * qla2x00 local function return status code.
1966 *
1967 * Context:
1968 * Kernel context.
1969 */
1970int
1971qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map)
1972{
1973 int rval;
1974 mbx_cmd_t mc;
1975 mbx_cmd_t *mcp = &mc;
1976 char *pmap;
1977 dma_addr_t pmap_dma;
1978
1979 pmap = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &pmap_dma);
1980 if (pmap == NULL) {
1981 DEBUG2_3_11(printk("%s(%ld): **** Mem Alloc Failed ****",
1982 __func__, ha->host_no));
1983 return QLA_MEMORY_ALLOC_FAILED;
1984 }
1985 memset(pmap, 0, FCAL_MAP_SIZE);
1986
1987 mcp->mb[0] = MBC_GET_FC_AL_POSITION_MAP;
1988 mcp->mb[2] = MSW(pmap_dma);
1989 mcp->mb[3] = LSW(pmap_dma);
1990 mcp->mb[6] = MSW(MSD(pmap_dma));
1991 mcp->mb[7] = LSW(MSD(pmap_dma));
1992 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
1993 mcp->in_mb = MBX_1|MBX_0;
1994 mcp->buf_size = FCAL_MAP_SIZE;
1995 mcp->flags = MBX_DMA_IN;
1996 mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
1997 rval = qla2x00_mailbox_command(ha, mcp);
1998
1999 if (rval == QLA_SUCCESS) {
2000 DEBUG11(printk("%s(%ld): (mb0=%x/mb1=%x) FC/AL Position Map "
2001 "size (%x)\n", __func__, ha->host_no, mcp->mb[0],
2002 mcp->mb[1], (unsigned)pmap[0]));
2003 DEBUG11(qla2x00_dump_buffer(pmap, pmap[0] + 1));
2004
2005 if (pos_map)
2006 memcpy(pos_map, pmap, FCAL_MAP_SIZE);
2007 }
2008 dma_pool_free(ha->s_dma_pool, pmap, pmap_dma);
2009
2010 if (rval != QLA_SUCCESS) {
2011 DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
2012 ha->host_no, rval));
2013 } else {
2014 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
2015 }
2016
2017 return rval;
2018}
andrew.vasquez@qlogic.com392e2f62006-01-31 16:05:02 -08002019#endif
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07002020
andrew.vasquez@qlogic.com392e2f62006-01-31 16:05:02 -08002021/*
2022 * qla2x00_get_link_status
2023 *
2024 * Input:
2025 * ha = adapter block pointer.
2026 * loop_id = device loop ID.
2027 * ret_buf = pointer to link status return buffer.
2028 *
2029 * Returns:
2030 * 0 = success.
2031 * BIT_0 = mem alloc error.
2032 * BIT_1 = mailbox error.
2033 */
2034int
2035qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id,
2036 link_stat_t *ret_buf, uint16_t *status)
2037{
2038 int rval;
2039 mbx_cmd_t mc;
2040 mbx_cmd_t *mcp = &mc;
2041 link_stat_t *stat_buf;
2042 dma_addr_t stat_buf_dma;
2043
2044 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
2045
2046 stat_buf = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &stat_buf_dma);
2047 if (stat_buf == NULL) {
2048 DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n",
2049 __func__, ha->host_no));
2050 return BIT_0;
2051 }
2052 memset(stat_buf, 0, sizeof(link_stat_t));
2053
2054 mcp->mb[0] = MBC_GET_LINK_STATUS;
2055 mcp->mb[2] = MSW(stat_buf_dma);
2056 mcp->mb[3] = LSW(stat_buf_dma);
2057 mcp->mb[6] = MSW(MSD(stat_buf_dma));
2058 mcp->mb[7] = LSW(MSD(stat_buf_dma));
2059 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
2060 mcp->in_mb = MBX_0;
2061 if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
2062 mcp->mb[1] = loop_id;
2063 mcp->mb[4] = 0;
2064 mcp->mb[10] = 0;
2065 mcp->out_mb |= MBX_10|MBX_4|MBX_1;
2066 mcp->in_mb |= MBX_1;
2067 } else if (HAS_EXTENDED_IDS(ha)) {
2068 mcp->mb[1] = loop_id;
2069 mcp->mb[10] = 0;
2070 mcp->out_mb |= MBX_10|MBX_1;
2071 } else {
2072 mcp->mb[1] = loop_id << 8;
2073 mcp->out_mb |= MBX_1;
2074 }
2075 mcp->tov = 30;
2076 mcp->flags = IOCTL_CMD;
2077 rval = qla2x00_mailbox_command(ha, mcp);
2078
2079 if (rval == QLA_SUCCESS) {
2080 if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
2081 DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n",
2082 __func__, ha->host_no, mcp->mb[0]);)
2083 status[0] = mcp->mb[0];
2084 rval = BIT_1;
2085 } else {
2086 /* copy over data -- firmware data is LE. */
2087 ret_buf->link_fail_cnt =
2088 le32_to_cpu(stat_buf->link_fail_cnt);
2089 ret_buf->loss_sync_cnt =
2090 le32_to_cpu(stat_buf->loss_sync_cnt);
2091 ret_buf->loss_sig_cnt =
2092 le32_to_cpu(stat_buf->loss_sig_cnt);
2093 ret_buf->prim_seq_err_cnt =
2094 le32_to_cpu(stat_buf->prim_seq_err_cnt);
2095 ret_buf->inval_xmit_word_cnt =
2096 le32_to_cpu(stat_buf->inval_xmit_word_cnt);
2097 ret_buf->inval_crc_cnt =
2098 le32_to_cpu(stat_buf->inval_crc_cnt);
2099
2100 DEBUG11(printk("%s(%ld): stat dump: fail_cnt=%d "
2101 "loss_sync=%d loss_sig=%d seq_err=%d "
2102 "inval_xmt_word=%d inval_crc=%d.\n", __func__,
2103 ha->host_no, stat_buf->link_fail_cnt,
2104 stat_buf->loss_sync_cnt, stat_buf->loss_sig_cnt,
2105 stat_buf->prim_seq_err_cnt,
2106 stat_buf->inval_xmit_word_cnt,
2107 stat_buf->inval_crc_cnt);)
2108 }
2109 } else {
2110 /* Failed. */
2111 DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
2112 ha->host_no, rval);)
2113 rval = BIT_1;
2114 }
2115
2116 dma_pool_free(ha->s_dma_pool, stat_buf, stat_buf_dma);
2117
2118 return rval;
2119}
2120
2121int
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07002122qla24xx_get_isp_stats(scsi_qla_host_t *ha, uint32_t *dwbuf, uint32_t dwords,
2123 uint16_t *status)
2124{
2125 int rval;
2126 mbx_cmd_t mc;
2127 mbx_cmd_t *mcp = &mc;
2128 uint32_t *sbuf, *siter;
2129 dma_addr_t sbuf_dma;
2130
2131 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
2132
2133 if (dwords > (DMA_POOL_SIZE / 4)) {
2134 DEBUG2_3_11(printk("%s(%ld): Unabled to retrieve %d DWORDs "
2135 "(max %d).\n", __func__, ha->host_no, dwords,
2136 DMA_POOL_SIZE / 4));
2137 return BIT_0;
2138 }
2139 sbuf = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &sbuf_dma);
2140 if (sbuf == NULL) {
2141 DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n",
2142 __func__, ha->host_no));
2143 return BIT_0;
2144 }
2145 memset(sbuf, 0, DMA_POOL_SIZE);
2146
2147 mcp->mb[0] = MBC_GET_LINK_PRIV_STATS;
2148 mcp->mb[2] = MSW(sbuf_dma);
2149 mcp->mb[3] = LSW(sbuf_dma);
2150 mcp->mb[6] = MSW(MSD(sbuf_dma));
2151 mcp->mb[7] = LSW(MSD(sbuf_dma));
2152 mcp->mb[8] = dwords;
2153 mcp->mb[10] = 0;
2154 mcp->out_mb = MBX_10|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
2155 mcp->in_mb = MBX_2|MBX_1|MBX_0;
2156 mcp->tov = 30;
2157 mcp->flags = IOCTL_CMD;
2158 rval = qla2x00_mailbox_command(ha, mcp);
2159
2160 if (rval == QLA_SUCCESS) {
2161 if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
2162 DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n",
2163 __func__, ha->host_no, mcp->mb[0]));
2164 status[0] = mcp->mb[0];
2165 rval = BIT_1;
2166 } else {
2167 /* Copy over data -- firmware data is LE. */
2168 siter = sbuf;
2169 while (dwords--)
2170 *dwbuf++ = le32_to_cpu(*siter++);
2171 }
2172 } else {
2173 /* Failed. */
2174 DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
2175 ha->host_no, rval));
2176 rval = BIT_1;
2177 }
2178
2179 dma_pool_free(ha->s_dma_pool, sbuf, sbuf_dma);
2180
2181 return rval;
2182}
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07002183
2184int
2185qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp)
2186{
2187 int rval;
2188 fc_port_t *fcport;
2189 unsigned long flags = 0;
2190
2191 struct abort_entry_24xx *abt;
2192 dma_addr_t abt_dma;
2193 uint32_t handle;
2194
2195 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
2196
2197 fcport = sp->fcport;
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07002198
2199 spin_lock_irqsave(&ha->hardware_lock, flags);
2200 for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) {
2201 if (ha->outstanding_cmds[handle] == sp)
2202 break;
2203 }
2204 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2205 if (handle == MAX_OUTSTANDING_COMMANDS) {
2206 /* Command not found. */
2207 return QLA_FUNCTION_FAILED;
2208 }
2209
2210 abt = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &abt_dma);
2211 if (abt == NULL) {
2212 DEBUG2_3(printk("%s(%ld): failed to allocate Abort IOCB.\n",
2213 __func__, ha->host_no));
2214 return QLA_MEMORY_ALLOC_FAILED;
2215 }
2216 memset(abt, 0, sizeof(struct abort_entry_24xx));
2217
2218 abt->entry_type = ABORT_IOCB_TYPE;
2219 abt->entry_count = 1;
2220 abt->nport_handle = cpu_to_le16(fcport->loop_id);
2221 abt->handle_to_abort = handle;
2222 abt->port_id[0] = fcport->d_id.b.al_pa;
2223 abt->port_id[1] = fcport->d_id.b.area;
2224 abt->port_id[2] = fcport->d_id.b.domain;
2225 rval = qla2x00_issue_iocb(ha, abt, abt_dma, 0);
2226 if (rval != QLA_SUCCESS) {
2227 DEBUG2_3_11(printk("%s(%ld): failed to issue IOCB (%x).\n",
2228 __func__, ha->host_no, rval);)
2229 } else if (abt->entry_status != 0) {
2230 DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
2231 "-- error status (%x).\n", __func__, ha->host_no,
2232 abt->entry_status));
2233 rval = QLA_FUNCTION_FAILED;
2234 } else if (abt->nport_handle != __constant_cpu_to_le16(0)) {
2235 DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
2236 "-- completion status (%x).\n", __func__, ha->host_no,
2237 le16_to_cpu(abt->nport_handle));)
2238 rval = QLA_FUNCTION_FAILED;
2239 } else {
2240 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);)
2241 sp->flags |= SRB_ABORT_PENDING;
2242 }
2243
2244 dma_pool_free(ha->s_dma_pool, abt, abt_dma);
2245
2246 return rval;
2247}
2248
2249struct tsk_mgmt_cmd {
2250 union {
2251 struct tsk_mgmt_entry tsk;
2252 struct sts_entry_24xx sts;
2253 } p;
2254};
2255
2256int
2257qla24xx_abort_target(fc_port_t *fcport)
2258{
2259 int rval;
2260 struct tsk_mgmt_cmd *tsk;
2261 dma_addr_t tsk_dma;
2262 scsi_qla_host_t *ha;
2263
2264 if (fcport == NULL)
2265 return 0;
2266
2267 DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no);)
2268
2269 ha = fcport->ha;
2270 tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma);
2271 if (tsk == NULL) {
2272 DEBUG2_3(printk("%s(%ld): failed to allocate Task Management "
2273 "IOCB.\n", __func__, ha->host_no));
2274 return QLA_MEMORY_ALLOC_FAILED;
2275 }
2276 memset(tsk, 0, sizeof(struct tsk_mgmt_cmd));
2277
2278 tsk->p.tsk.entry_type = TSK_MGMT_IOCB_TYPE;
2279 tsk->p.tsk.entry_count = 1;
2280 tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id);
2281 tsk->p.tsk.timeout = __constant_cpu_to_le16(25);
2282 tsk->p.tsk.control_flags = __constant_cpu_to_le32(TCF_TARGET_RESET);
2283 tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa;
2284 tsk->p.tsk.port_id[1] = fcport->d_id.b.area;
2285 tsk->p.tsk.port_id[2] = fcport->d_id.b.domain;
2286 rval = qla2x00_issue_iocb(ha, tsk, tsk_dma, 0);
2287 if (rval != QLA_SUCCESS) {
2288 DEBUG2_3_11(printk("%s(%ld): failed to issue Target Reset IOCB "
2289 "(%x).\n", __func__, ha->host_no, rval);)
2290 goto atarget_done;
2291 } else if (tsk->p.sts.entry_status != 0) {
2292 DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
2293 "-- error status (%x).\n", __func__, ha->host_no,
2294 tsk->p.sts.entry_status));
2295 rval = QLA_FUNCTION_FAILED;
2296 goto atarget_done;
2297 } else if (tsk->p.sts.comp_status !=
2298 __constant_cpu_to_le16(CS_COMPLETE)) {
2299 DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
2300 "-- completion status (%x).\n", __func__,
2301 ha->host_no, le16_to_cpu(tsk->p.sts.comp_status));)
2302 rval = QLA_FUNCTION_FAILED;
2303 goto atarget_done;
2304 }
2305
2306 /* Issue marker IOCB. */
2307 rval = qla2x00_marker(ha, fcport->loop_id, 0, MK_SYNC_ID);
2308 if (rval != QLA_SUCCESS) {
2309 DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
2310 "(%x).\n", __func__, ha->host_no, rval);)
2311 } else {
2312 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no);)
2313 }
2314
2315atarget_done:
2316 dma_pool_free(ha->s_dma_pool, tsk, tsk_dma);
2317
2318 return rval;
2319}
2320
2321int
2322qla2x00_system_error(scsi_qla_host_t *ha)
2323{
2324 int rval;
2325 mbx_cmd_t mc;
2326 mbx_cmd_t *mcp = &mc;
2327
2328 if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha))
2329 return QLA_FUNCTION_FAILED;
2330
2331 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
2332
2333 mcp->mb[0] = MBC_GEN_SYSTEM_ERROR;
2334 mcp->out_mb = MBX_0;
2335 mcp->in_mb = MBX_0;
2336 mcp->tov = 5;
2337 mcp->flags = 0;
2338 rval = qla2x00_mailbox_command(ha, mcp);
2339
2340 if (rval != QLA_SUCCESS) {
2341 DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
2342 ha->host_no, rval));
2343 } else {
2344 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
2345 }
2346
2347 return rval;
2348}
2349
2350/**
2351 * qla2x00_get_serdes_params() -
2352 * @ha: HA context
2353 *
2354 * Returns
2355 */
2356int
2357qla2x00_get_serdes_params(scsi_qla_host_t *ha, uint16_t *sw_em_1g,
2358 uint16_t *sw_em_2g, uint16_t *sw_em_4g)
2359{
2360 int rval;
2361 mbx_cmd_t mc;
2362 mbx_cmd_t *mcp = &mc;
2363
2364 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
2365
2366 mcp->mb[0] = MBC_SERDES_PARAMS;
2367 mcp->mb[1] = 0;
2368 mcp->out_mb = MBX_1|MBX_0;
2369 mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_0;
2370 mcp->tov = 30;
2371 mcp->flags = 0;
2372 rval = qla2x00_mailbox_command(ha, mcp);
2373
2374 if (rval != QLA_SUCCESS) {
2375 /*EMPTY*/
2376 DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
2377 ha->host_no, rval, mcp->mb[0]));
2378 } else {
2379 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
2380
2381 if (sw_em_1g)
2382 *sw_em_1g = mcp->mb[2];
2383 if (sw_em_2g)
2384 *sw_em_2g = mcp->mb[3];
2385 if (sw_em_4g)
2386 *sw_em_4g = mcp->mb[4];
2387 }
2388
2389 return rval;
2390}
2391
2392/**
2393 * qla2x00_set_serdes_params() -
2394 * @ha: HA context
2395 *
2396 * Returns
2397 */
2398int
2399qla2x00_set_serdes_params(scsi_qla_host_t *ha, uint16_t sw_em_1g,
2400 uint16_t sw_em_2g, uint16_t sw_em_4g)
2401{
2402 int rval;
2403 mbx_cmd_t mc;
2404 mbx_cmd_t *mcp = &mc;
2405
2406 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
2407
2408 mcp->mb[0] = MBC_SERDES_PARAMS;
2409 mcp->mb[1] = BIT_0;
2410 mcp->mb[2] = sw_em_1g;
2411 mcp->mb[3] = sw_em_2g;
2412 mcp->mb[4] = sw_em_4g;
2413 mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
2414 mcp->in_mb = MBX_0;
2415 mcp->tov = 30;
2416 mcp->flags = 0;
2417 rval = qla2x00_mailbox_command(ha, mcp);
2418
2419 if (rval != QLA_SUCCESS) {
2420 /*EMPTY*/
2421 DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
2422 ha->host_no, rval, mcp->mb[0]));
2423 } else {
2424 /*EMPTY*/
2425 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
2426 }
2427
2428 return rval;
2429}
Andrew Vasquezf6ef3b12005-08-26 19:10:20 -07002430
2431int
2432qla2x00_stop_firmware(scsi_qla_host_t *ha)
2433{
2434 int rval;
2435 mbx_cmd_t mc;
2436 mbx_cmd_t *mcp = &mc;
2437
2438 if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha))
2439 return QLA_FUNCTION_FAILED;
2440
2441 DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
2442
2443 mcp->mb[0] = MBC_STOP_FIRMWARE;
2444 mcp->out_mb = MBX_0;
2445 mcp->in_mb = MBX_0;
2446 mcp->tov = 5;
2447 mcp->flags = 0;
2448 rval = qla2x00_mailbox_command(ha, mcp);
2449
2450 if (rval != QLA_SUCCESS) {
2451 DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
2452 ha->host_no, rval));
2453 } else {
2454 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
2455 }
2456
2457 return rval;
2458}