Commit | Line | Data |
---|---|---|
afaf5a2d DS |
1 | /* |
2 | * QLogic iSCSI HBA Driver | |
3 | * Copyright (c) 2003-2006 QLogic Corporation | |
4 | * | |
5 | * See LICENSE.qla4xxx for copyright and licensing details. | |
6 | */ | |
7 | ||
8 | #include "ql4_def.h" | |
9 | ||
10 | ||
11 | /** | |
12 | * qla4xxx_mailbox_command - issues mailbox commands | |
13 | * @ha: Pointer to host adapter structure. | |
14 | * @inCount: number of mailbox registers to load. | |
15 | * @outCount: number of mailbox registers to return. | |
16 | * @mbx_cmd: data pointer for mailbox in registers. | |
17 | * @mbx_sts: data pointer for mailbox out registers. | |
18 | * | |
19 | * This routine sssue mailbox commands and waits for completion. | |
20 | * If outCount is 0, this routine completes successfully WITHOUT waiting | |
21 | * for the mailbox command to complete. | |
22 | **/ | |
47975477 AB |
23 | static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, |
24 | uint8_t outCount, uint32_t *mbx_cmd, | |
25 | uint32_t *mbx_sts) | |
afaf5a2d DS |
26 | { |
27 | int status = QLA_ERROR; | |
28 | uint8_t i; | |
29 | u_long wait_count; | |
30 | uint32_t intr_status; | |
31 | unsigned long flags = 0; | |
afaf5a2d DS |
32 | |
33 | /* Make sure that pointers are valid */ | |
34 | if (!mbx_cmd || !mbx_sts) { | |
35 | DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts " | |
36 | "pointer\n", ha->host_no, __func__)); | |
477ffb9d DS |
37 | return status; |
38 | } | |
39 | /* Mailbox code active */ | |
40 | wait_count = MBOX_TOV * 100; | |
41 | ||
42 | while (wait_count--) { | |
43 | mutex_lock(&ha->mbox_sem); | |
44 | if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) { | |
45 | set_bit(AF_MBOX_COMMAND, &ha->flags); | |
46 | mutex_unlock(&ha->mbox_sem); | |
47 | break; | |
48 | } | |
49 | mutex_unlock(&ha->mbox_sem); | |
50 | if (!wait_count) { | |
51 | DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n", | |
52 | ha->host_no, __func__)); | |
53 | return status; | |
54 | } | |
55 | msleep(10); | |
afaf5a2d DS |
56 | } |
57 | ||
58 | /* To prevent overwriting mailbox registers for a command that has | |
59 | * not yet been serviced, check to see if a previously issued | |
60 | * mailbox command is interrupting. | |
61 | * ----------------------------------------------------------------- | |
62 | */ | |
63 | spin_lock_irqsave(&ha->hardware_lock, flags); | |
64 | intr_status = readl(&ha->reg->ctrl_status); | |
65 | if (intr_status & CSR_SCSI_PROCESSOR_INTR) { | |
66 | /* Service existing interrupt */ | |
67 | qla4xxx_interrupt_service_routine(ha, intr_status); | |
68 | clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); | |
69 | } | |
70 | ||
71 | /* Send the mailbox command to the firmware */ | |
72 | ha->mbox_status_count = outCount; | |
73 | for (i = 0; i < outCount; i++) | |
74 | ha->mbox_status[i] = 0; | |
75 | ||
76 | /* Load all mailbox registers, except mailbox 0. */ | |
77 | for (i = 1; i < inCount; i++) | |
78 | writel(mbx_cmd[i], &ha->reg->mailbox[i]); | |
79 | ||
80 | /* Wakeup firmware */ | |
81 | writel(mbx_cmd[0], &ha->reg->mailbox[0]); | |
82 | readl(&ha->reg->mailbox[0]); | |
83 | writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status); | |
84 | readl(&ha->reg->ctrl_status); | |
85 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | |
86 | ||
87 | /* Wait for completion */ | |
afaf5a2d DS |
88 | |
89 | /* | |
90 | * If we don't want status, don't wait for the mailbox command to | |
91 | * complete. For example, MBOX_CMD_RESET_FW doesn't return status, | |
92 | * you must poll the inbound Interrupt Mask for completion. | |
93 | */ | |
94 | if (outCount == 0) { | |
95 | status = QLA_SUCCESS; | |
afaf5a2d DS |
96 | goto mbox_exit; |
97 | } | |
98 | /* Wait for command to complete */ | |
99 | wait_count = jiffies + MBOX_TOV * HZ; | |
100 | while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) { | |
101 | if (time_after_eq(jiffies, wait_count)) | |
102 | break; | |
103 | ||
104 | spin_lock_irqsave(&ha->hardware_lock, flags); | |
105 | intr_status = readl(&ha->reg->ctrl_status); | |
106 | if (intr_status & INTR_PENDING) { | |
107 | /* | |
108 | * Service the interrupt. | |
109 | * The ISR will save the mailbox status registers | |
110 | * to a temporary storage location in the adapter | |
111 | * structure. | |
112 | */ | |
113 | ha->mbox_status_count = outCount; | |
114 | qla4xxx_interrupt_service_routine(ha, intr_status); | |
115 | } | |
116 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | |
117 | msleep(10); | |
118 | } | |
afaf5a2d DS |
119 | |
120 | /* Check for mailbox timeout. */ | |
121 | if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) { | |
122 | DEBUG2(printk("scsi%ld: Mailbox Cmd 0x%08X timed out ...," | |
123 | " Scheduling Adapter Reset\n", ha->host_no, | |
124 | mbx_cmd[0])); | |
125 | ha->mailbox_timeout_count++; | |
126 | mbx_sts[0] = (-1); | |
127 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | |
128 | goto mbox_exit; | |
129 | } | |
130 | ||
131 | /* | |
132 | * Copy the mailbox out registers to the caller's mailbox in/out | |
133 | * structure. | |
134 | */ | |
135 | spin_lock_irqsave(&ha->hardware_lock, flags); | |
136 | for (i = 0; i < outCount; i++) | |
137 | mbx_sts[i] = ha->mbox_status[i]; | |
138 | ||
139 | /* Set return status and error flags (if applicable). */ | |
140 | switch (ha->mbox_status[0]) { | |
141 | case MBOX_STS_COMMAND_COMPLETE: | |
142 | status = QLA_SUCCESS; | |
143 | break; | |
144 | ||
145 | case MBOX_STS_INTERMEDIATE_COMPLETION: | |
146 | status = QLA_SUCCESS; | |
147 | break; | |
148 | ||
149 | case MBOX_STS_BUSY: | |
150 | DEBUG2( printk("scsi%ld: %s: Cmd = %08X, ISP BUSY\n", | |
151 | ha->host_no, __func__, mbx_cmd[0])); | |
152 | ha->mailbox_timeout_count++; | |
153 | break; | |
154 | ||
155 | default: | |
156 | DEBUG2(printk("scsi%ld: %s: **** FAILED, cmd = %08X, " | |
157 | "sts = %08X ****\n", ha->host_no, __func__, | |
158 | mbx_cmd[0], mbx_sts[0])); | |
159 | break; | |
160 | } | |
161 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | |
162 | ||
163 | mbox_exit: | |
477ffb9d | 164 | mutex_lock(&ha->mbox_sem); |
afaf5a2d | 165 | clear_bit(AF_MBOX_COMMAND, &ha->flags); |
afaf5a2d | 166 | mutex_unlock(&ha->mbox_sem); |
477ffb9d | 167 | clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); |
afaf5a2d DS |
168 | |
169 | return status; | |
170 | } | |
171 | ||
172 | ||
47975477 AB |
173 | #if 0 |
174 | ||
afaf5a2d DS |
175 | /** |
176 | * qla4xxx_issue_iocb - issue mailbox iocb command | |
177 | * @ha: adapter state pointer. | |
178 | * @buffer: buffer pointer. | |
179 | * @phys_addr: physical address of buffer. | |
180 | * @size: size of buffer. | |
181 | * | |
182 | * Issues iocbs via mailbox commands. | |
183 | * TARGET_QUEUE_LOCK must be released. | |
184 | * ADAPTER_STATE_LOCK must be released. | |
185 | **/ | |
186 | int | |
187 | qla4xxx_issue_iocb(struct scsi_qla_host * ha, void *buffer, | |
188 | dma_addr_t phys_addr, size_t size) | |
189 | { | |
190 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
191 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
192 | int status; | |
193 | ||
194 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
195 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | |
196 | mbox_cmd[0] = MBOX_CMD_EXECUTE_IOCB_A64; | |
197 | mbox_cmd[1] = 0; | |
198 | mbox_cmd[2] = LSDW(phys_addr); | |
199 | mbox_cmd[3] = MSDW(phys_addr); | |
200 | status = qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]); | |
201 | return status; | |
202 | } | |
203 | ||
204 | int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha, | |
205 | uint16_t fw_ddb_index, | |
206 | uint16_t connection_id, | |
207 | uint16_t option) | |
208 | { | |
209 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
210 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
211 | ||
212 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
213 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | |
214 | mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT; | |
215 | mbox_cmd[1] = fw_ddb_index; | |
216 | mbox_cmd[2] = connection_id; | |
217 | mbox_cmd[3] = LOGOUT_OPTION_RELOGIN; | |
218 | if (qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]) != | |
219 | QLA_SUCCESS) { | |
220 | DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT " | |
221 | "option %04x failed sts %04X %04X", | |
222 | ha->host_no, __func__, | |
223 | option, mbox_sts[0], mbox_sts[1])); | |
224 | if (mbox_sts[0] == 0x4005) | |
225 | DEBUG2(printk("%s reason %04X\n", __func__, | |
226 | mbox_sts[1])); | |
227 | } | |
228 | return QLA_SUCCESS; | |
229 | } | |
230 | ||
231 | int qla4xxx_clear_database_entry(struct scsi_qla_host * ha, | |
232 | uint16_t fw_ddb_index) | |
233 | { | |
234 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
235 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
236 | ||
237 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
238 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | |
239 | mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY; | |
240 | mbox_cmd[1] = fw_ddb_index; | |
241 | if (qla4xxx_mailbox_command(ha, 2, 5, &mbox_cmd[0], &mbox_sts[0]) != | |
242 | QLA_SUCCESS) | |
243 | return QLA_ERROR; | |
244 | ||
245 | return QLA_SUCCESS; | |
246 | } | |
247 | ||
47975477 AB |
248 | #endif /* 0 */ |
249 | ||
afaf5a2d DS |
250 | /** |
251 | * qla4xxx_initialize_fw_cb - initializes firmware control block. | |
252 | * @ha: Pointer to host adapter structure. | |
253 | **/ | |
254 | int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha) | |
255 | { | |
256 | struct init_fw_ctrl_blk *init_fw_cb; | |
257 | dma_addr_t init_fw_cb_dma; | |
258 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
259 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
260 | int status = QLA_ERROR; | |
261 | ||
262 | init_fw_cb = dma_alloc_coherent(&ha->pdev->dev, | |
263 | sizeof(struct init_fw_ctrl_blk), | |
264 | &init_fw_cb_dma, GFP_KERNEL); | |
265 | if (init_fw_cb == NULL) { | |
266 | DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n", | |
267 | ha->host_no, __func__)); | |
268 | return 10; | |
269 | } | |
270 | memset(init_fw_cb, 0, sizeof(struct init_fw_ctrl_blk)); | |
271 | ||
272 | /* Get Initialize Firmware Control Block. */ | |
273 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
274 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | |
275 | mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK; | |
276 | mbox_cmd[2] = LSDW(init_fw_cb_dma); | |
277 | mbox_cmd[3] = MSDW(init_fw_cb_dma); | |
278 | if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) != | |
279 | QLA_SUCCESS) { | |
280 | dma_free_coherent(&ha->pdev->dev, | |
281 | sizeof(struct init_fw_ctrl_blk), | |
282 | init_fw_cb, init_fw_cb_dma); | |
283 | return status; | |
284 | } | |
285 | ||
286 | /* Initialize request and response queues. */ | |
287 | qla4xxx_init_rings(ha); | |
288 | ||
289 | /* Fill in the request and response queue information. */ | |
290 | init_fw_cb->ReqQConsumerIndex = cpu_to_le16(ha->request_out); | |
291 | init_fw_cb->ComplQProducerIndex = cpu_to_le16(ha->response_in); | |
292 | init_fw_cb->ReqQLen = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH); | |
293 | init_fw_cb->ComplQLen = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH); | |
294 | init_fw_cb->ReqQAddrLo = cpu_to_le32(LSDW(ha->request_dma)); | |
295 | init_fw_cb->ReqQAddrHi = cpu_to_le32(MSDW(ha->request_dma)); | |
296 | init_fw_cb->ComplQAddrLo = cpu_to_le32(LSDW(ha->response_dma)); | |
297 | init_fw_cb->ComplQAddrHi = cpu_to_le32(MSDW(ha->response_dma)); | |
298 | init_fw_cb->ShadowRegBufAddrLo = | |
299 | cpu_to_le32(LSDW(ha->shadow_regs_dma)); | |
300 | init_fw_cb->ShadowRegBufAddrHi = | |
301 | cpu_to_le32(MSDW(ha->shadow_regs_dma)); | |
302 | ||
303 | /* Set up required options. */ | |
304 | init_fw_cb->FwOptions |= | |
305 | __constant_cpu_to_le16(FWOPT_SESSION_MODE | | |
306 | FWOPT_INITIATOR_MODE); | |
307 | init_fw_cb->FwOptions &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE); | |
308 | ||
309 | /* Save some info in adapter structure. */ | |
310 | ha->firmware_options = le16_to_cpu(init_fw_cb->FwOptions); | |
311 | ha->tcp_options = le16_to_cpu(init_fw_cb->TCPOptions); | |
312 | ha->heartbeat_interval = init_fw_cb->HeartbeatInterval; | |
313 | memcpy(ha->ip_address, init_fw_cb->IPAddr, | |
314 | min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr))); | |
315 | memcpy(ha->subnet_mask, init_fw_cb->SubnetMask, | |
316 | min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask))); | |
317 | memcpy(ha->gateway, init_fw_cb->GatewayIPAddr, | |
318 | min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr))); | |
319 | memcpy(ha->name_string, init_fw_cb->iSCSINameString, | |
320 | min(sizeof(ha->name_string), | |
321 | sizeof(init_fw_cb->iSCSINameString))); | |
322 | memcpy(ha->alias, init_fw_cb->Alias, | |
323 | min(sizeof(ha->alias), sizeof(init_fw_cb->Alias))); | |
324 | ||
325 | /* Save Command Line Paramater info */ | |
326 | ha->port_down_retry_count = le16_to_cpu(init_fw_cb->KeepAliveTimeout); | |
327 | ha->discovery_wait = ql4xdiscoverywait; | |
328 | ||
329 | /* Send Initialize Firmware Control Block. */ | |
330 | mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE; | |
331 | mbox_cmd[1] = 0; | |
332 | mbox_cmd[2] = LSDW(init_fw_cb_dma); | |
333 | mbox_cmd[3] = MSDW(init_fw_cb_dma); | |
334 | if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) == | |
335 | QLA_SUCCESS) | |
336 | status = QLA_SUCCESS; | |
337 | else { | |
338 | DEBUG2(printk("scsi%ld: %s: MBOX_CMD_INITIALIZE_FIRMWARE " | |
339 | "failed w/ status %04X\n", ha->host_no, __func__, | |
340 | mbox_sts[0])); | |
341 | } | |
342 | dma_free_coherent(&ha->pdev->dev, sizeof(struct init_fw_ctrl_blk), | |
343 | init_fw_cb, init_fw_cb_dma); | |
344 | ||
345 | return status; | |
346 | } | |
347 | ||
348 | /** | |
349 | * qla4xxx_get_dhcp_ip_address - gets HBA ip address via DHCP | |
350 | * @ha: Pointer to host adapter structure. | |
351 | **/ | |
352 | int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha) | |
353 | { | |
354 | struct init_fw_ctrl_blk *init_fw_cb; | |
355 | dma_addr_t init_fw_cb_dma; | |
356 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
357 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
358 | ||
359 | init_fw_cb = dma_alloc_coherent(&ha->pdev->dev, | |
360 | sizeof(struct init_fw_ctrl_blk), | |
361 | &init_fw_cb_dma, GFP_KERNEL); | |
362 | if (init_fw_cb == NULL) { | |
363 | printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no, | |
364 | __func__); | |
365 | return 10; | |
366 | } | |
367 | ||
368 | /* Get Initialize Firmware Control Block. */ | |
369 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
370 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | |
371 | memset(init_fw_cb, 0, sizeof(struct init_fw_ctrl_blk)); | |
372 | mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK; | |
373 | mbox_cmd[2] = LSDW(init_fw_cb_dma); | |
374 | mbox_cmd[3] = MSDW(init_fw_cb_dma); | |
375 | ||
376 | if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) != | |
377 | QLA_SUCCESS) { | |
378 | DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n", | |
379 | ha->host_no, __func__)); | |
380 | dma_free_coherent(&ha->pdev->dev, | |
381 | sizeof(struct init_fw_ctrl_blk), | |
382 | init_fw_cb, init_fw_cb_dma); | |
383 | return QLA_ERROR; | |
384 | } | |
385 | ||
386 | /* Save IP Address. */ | |
387 | memcpy(ha->ip_address, init_fw_cb->IPAddr, | |
388 | min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr))); | |
389 | memcpy(ha->subnet_mask, init_fw_cb->SubnetMask, | |
390 | min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask))); | |
391 | memcpy(ha->gateway, init_fw_cb->GatewayIPAddr, | |
392 | min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr))); | |
393 | ||
394 | dma_free_coherent(&ha->pdev->dev, sizeof(struct init_fw_ctrl_blk), | |
395 | init_fw_cb, init_fw_cb_dma); | |
396 | ||
397 | return QLA_SUCCESS; | |
398 | } | |
399 | ||
400 | /** | |
401 | * qla4xxx_get_firmware_state - gets firmware state of HBA | |
402 | * @ha: Pointer to host adapter structure. | |
403 | **/ | |
404 | int qla4xxx_get_firmware_state(struct scsi_qla_host * ha) | |
405 | { | |
406 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
407 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
408 | ||
409 | /* Get firmware version */ | |
410 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
411 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | |
412 | mbox_cmd[0] = MBOX_CMD_GET_FW_STATE; | |
413 | if (qla4xxx_mailbox_command(ha, 1, 4, &mbox_cmd[0], &mbox_sts[0]) != | |
414 | QLA_SUCCESS) { | |
415 | DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ " | |
416 | "status %04X\n", ha->host_no, __func__, | |
417 | mbox_sts[0])); | |
418 | return QLA_ERROR; | |
419 | } | |
420 | ha->firmware_state = mbox_sts[1]; | |
421 | ha->board_id = mbox_sts[2]; | |
422 | ha->addl_fw_state = mbox_sts[3]; | |
423 | DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n", | |
424 | ha->host_no, __func__, ha->firmware_state);) | |
425 | ||
426 | return QLA_SUCCESS; | |
427 | } | |
428 | ||
429 | /** | |
430 | * qla4xxx_get_firmware_status - retrieves firmware status | |
431 | * @ha: Pointer to host adapter structure. | |
432 | **/ | |
433 | int qla4xxx_get_firmware_status(struct scsi_qla_host * ha) | |
434 | { | |
435 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
436 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
437 | ||
438 | /* Get firmware version */ | |
439 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
440 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | |
441 | mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS; | |
442 | if (qla4xxx_mailbox_command(ha, 1, 3, &mbox_cmd[0], &mbox_sts[0]) != | |
443 | QLA_SUCCESS) { | |
444 | DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ " | |
445 | "status %04X\n", ha->host_no, __func__, | |
446 | mbox_sts[0])); | |
447 | return QLA_ERROR; | |
448 | } | |
449 | ||
450 | /* High-water mark of IOCBs */ | |
451 | ha->iocb_hiwat = mbox_sts[2]; | |
452 | if (ha->iocb_hiwat > IOCB_HIWAT_CUSHION) | |
453 | ha->iocb_hiwat -= IOCB_HIWAT_CUSHION; | |
454 | else | |
455 | dev_info(&ha->pdev->dev, "WARNING!!! You have less than %d " | |
456 | "firmare IOCBs available (%d).\n", | |
457 | IOCB_HIWAT_CUSHION, ha->iocb_hiwat); | |
458 | ||
459 | return QLA_SUCCESS; | |
460 | } | |
461 | ||
462 | /** | |
463 | * qla4xxx_get_fwddb_entry - retrieves firmware ddb entry | |
464 | * @ha: Pointer to host adapter structure. | |
465 | * @fw_ddb_index: Firmware's device database index | |
466 | * @fw_ddb_entry: Pointer to firmware's device database entry structure | |
467 | * @num_valid_ddb_entries: Pointer to number of valid ddb entries | |
468 | * @next_ddb_index: Pointer to next valid device database index | |
469 | * @fw_ddb_device_state: Pointer to device state | |
470 | **/ | |
471 | int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha, | |
472 | uint16_t fw_ddb_index, | |
473 | struct dev_db_entry *fw_ddb_entry, | |
474 | dma_addr_t fw_ddb_entry_dma, | |
475 | uint32_t *num_valid_ddb_entries, | |
476 | uint32_t *next_ddb_index, | |
477 | uint32_t *fw_ddb_device_state, | |
478 | uint32_t *conn_err_detail, | |
479 | uint16_t *tcp_source_port_num, | |
480 | uint16_t *connection_id) | |
481 | { | |
482 | int status = QLA_ERROR; | |
483 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
484 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
485 | ||
486 | /* Make sure the device index is valid */ | |
487 | if (fw_ddb_index >= MAX_DDB_ENTRIES) { | |
488 | DEBUG2(printk("scsi%ld: %s: index [%d] out of range.\n", | |
489 | ha->host_no, __func__, fw_ddb_index)); | |
490 | goto exit_get_fwddb; | |
491 | } | |
492 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
493 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | |
494 | mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY; | |
495 | mbox_cmd[1] = (uint32_t) fw_ddb_index; | |
496 | mbox_cmd[2] = LSDW(fw_ddb_entry_dma); | |
497 | mbox_cmd[3] = MSDW(fw_ddb_entry_dma); | |
498 | if (qla4xxx_mailbox_command(ha, 4, 7, &mbox_cmd[0], &mbox_sts[0]) == | |
499 | QLA_ERROR) { | |
500 | DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed" | |
501 | " with status 0x%04X\n", ha->host_no, __func__, | |
502 | mbox_sts[0])); | |
503 | goto exit_get_fwddb; | |
504 | } | |
505 | if (fw_ddb_index != mbox_sts[1]) { | |
506 | DEBUG2(printk("scsi%ld: %s: index mismatch [%d] != [%d].\n", | |
507 | ha->host_no, __func__, fw_ddb_index, | |
508 | mbox_sts[1])); | |
509 | goto exit_get_fwddb; | |
510 | } | |
511 | if (fw_ddb_entry) { | |
512 | dev_info(&ha->pdev->dev, "DDB[%d] MB0 %04x Tot %d Next %d " | |
513 | "State %04x ConnErr %08x %d.%d.%d.%d:%04d \"%s\"\n", | |
514 | fw_ddb_index, mbox_sts[0], mbox_sts[2], mbox_sts[3], | |
515 | mbox_sts[4], mbox_sts[5], fw_ddb_entry->ipAddr[0], | |
516 | fw_ddb_entry->ipAddr[1], fw_ddb_entry->ipAddr[2], | |
517 | fw_ddb_entry->ipAddr[3], | |
518 | le16_to_cpu(fw_ddb_entry->portNumber), | |
519 | fw_ddb_entry->iscsiName); | |
520 | } | |
521 | if (num_valid_ddb_entries) | |
522 | *num_valid_ddb_entries = mbox_sts[2]; | |
523 | if (next_ddb_index) | |
524 | *next_ddb_index = mbox_sts[3]; | |
525 | if (fw_ddb_device_state) | |
526 | *fw_ddb_device_state = mbox_sts[4]; | |
527 | ||
528 | /* | |
529 | * RA: This mailbox has been changed to pass connection error and | |
530 | * details. Its true for ISP4010 as per Version E - Not sure when it | |
531 | * was changed. Get the time2wait from the fw_dd_entry field : | |
532 | * default_time2wait which we call it as minTime2Wait DEV_DB_ENTRY | |
533 | * struct. | |
534 | */ | |
535 | if (conn_err_detail) | |
536 | *conn_err_detail = mbox_sts[5]; | |
537 | if (tcp_source_port_num) | |
538 | *tcp_source_port_num = (uint16_t) mbox_sts[6] >> 16; | |
539 | if (connection_id) | |
540 | *connection_id = (uint16_t) mbox_sts[6] & 0x00FF; | |
541 | status = QLA_SUCCESS; | |
542 | ||
543 | exit_get_fwddb: | |
544 | return status; | |
545 | } | |
546 | ||
547 | /** | |
548 | * qla4xxx_set_fwddb_entry - sets a ddb entry. | |
549 | * @ha: Pointer to host adapter structure. | |
550 | * @fw_ddb_index: Firmware's device database index | |
551 | * @fw_ddb_entry: Pointer to firmware's ddb entry structure, or NULL. | |
552 | * | |
553 | * This routine initializes or updates the adapter's device database | |
554 | * entry for the specified device. It also triggers a login for the | |
555 | * specified device. Therefore, it may also be used as a secondary | |
556 | * login routine when a NULL pointer is specified for the fw_ddb_entry. | |
557 | **/ | |
558 | int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index, | |
559 | dma_addr_t fw_ddb_entry_dma) | |
560 | { | |
561 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
562 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
563 | ||
564 | /* Do not wait for completion. The firmware will send us an | |
565 | * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status. | |
566 | */ | |
567 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
568 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | |
569 | ||
570 | mbox_cmd[0] = MBOX_CMD_SET_DATABASE_ENTRY; | |
571 | mbox_cmd[1] = (uint32_t) fw_ddb_index; | |
572 | mbox_cmd[2] = LSDW(fw_ddb_entry_dma); | |
573 | mbox_cmd[3] = MSDW(fw_ddb_entry_dma); | |
574 | return qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]); | |
575 | } | |
576 | ||
47975477 | 577 | #if 0 |
afaf5a2d DS |
578 | int qla4xxx_conn_open_session_login(struct scsi_qla_host * ha, |
579 | uint16_t fw_ddb_index) | |
580 | { | |
581 | int status = QLA_ERROR; | |
582 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
583 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
584 | ||
585 | /* Do not wait for completion. The firmware will send us an | |
586 | * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status. | |
587 | */ | |
588 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
589 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | |
590 | mbox_cmd[0] = MBOX_CMD_CONN_OPEN_SESS_LOGIN; | |
591 | mbox_cmd[1] = (uint32_t) fw_ddb_index; | |
592 | mbox_cmd[2] = 0; | |
593 | mbox_cmd[3] = 0; | |
594 | mbox_cmd[4] = 0; | |
595 | status = qla4xxx_mailbox_command(ha, 4, 0, &mbox_cmd[0], &mbox_sts[0]); | |
596 | DEBUG2(printk("%s fw_ddb_index=%d status=%d mbx0_1=0x%x :0x%x\n", | |
597 | __func__, fw_ddb_index, status, mbox_sts[0], | |
598 | mbox_sts[1]);) | |
599 | ||
600 | return status; | |
601 | } | |
47975477 | 602 | #endif /* 0 */ |
afaf5a2d DS |
603 | |
604 | /** | |
605 | * qla4xxx_get_crash_record - retrieves crash record. | |
606 | * @ha: Pointer to host adapter structure. | |
607 | * | |
608 | * This routine retrieves a crash record from the QLA4010 after an 8002h aen. | |
609 | **/ | |
610 | void qla4xxx_get_crash_record(struct scsi_qla_host * ha) | |
611 | { | |
612 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
613 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
614 | struct crash_record *crash_record = NULL; | |
615 | dma_addr_t crash_record_dma = 0; | |
616 | uint32_t crash_record_size = 0; | |
617 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
618 | memset(&mbox_sts, 0, sizeof(mbox_cmd)); | |
619 | ||
620 | /* Get size of crash record. */ | |
621 | mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD; | |
622 | if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) != | |
623 | QLA_SUCCESS) { | |
624 | DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n", | |
625 | ha->host_no, __func__)); | |
626 | goto exit_get_crash_record; | |
627 | } | |
628 | crash_record_size = mbox_sts[4]; | |
629 | if (crash_record_size == 0) { | |
630 | DEBUG2(printk("scsi%ld: %s: ERROR: Crash record size is 0!\n", | |
631 | ha->host_no, __func__)); | |
632 | goto exit_get_crash_record; | |
633 | } | |
634 | ||
635 | /* Alloc Memory for Crash Record. */ | |
636 | crash_record = dma_alloc_coherent(&ha->pdev->dev, crash_record_size, | |
637 | &crash_record_dma, GFP_KERNEL); | |
638 | if (crash_record == NULL) | |
639 | goto exit_get_crash_record; | |
640 | ||
641 | /* Get Crash Record. */ | |
642 | mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD; | |
643 | mbox_cmd[2] = LSDW(crash_record_dma); | |
644 | mbox_cmd[3] = MSDW(crash_record_dma); | |
645 | mbox_cmd[4] = crash_record_size; | |
646 | if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) != | |
647 | QLA_SUCCESS) | |
648 | goto exit_get_crash_record; | |
649 | ||
650 | /* Dump Crash Record. */ | |
651 | ||
652 | exit_get_crash_record: | |
653 | if (crash_record) | |
654 | dma_free_coherent(&ha->pdev->dev, crash_record_size, | |
655 | crash_record, crash_record_dma); | |
656 | } | |
657 | ||
47975477 | 658 | #if 0 |
afaf5a2d DS |
659 | /** |
660 | * qla4xxx_get_conn_event_log - retrieves connection event log | |
661 | * @ha: Pointer to host adapter structure. | |
662 | **/ | |
663 | void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha) | |
664 | { | |
665 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
666 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
667 | struct conn_event_log_entry *event_log = NULL; | |
668 | dma_addr_t event_log_dma = 0; | |
669 | uint32_t event_log_size = 0; | |
670 | uint32_t num_valid_entries; | |
671 | uint32_t oldest_entry = 0; | |
672 | uint32_t max_event_log_entries; | |
673 | uint8_t i; | |
674 | ||
675 | ||
676 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
677 | memset(&mbox_sts, 0, sizeof(mbox_cmd)); | |
678 | ||
679 | /* Get size of crash record. */ | |
680 | mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG; | |
681 | if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) != | |
682 | QLA_SUCCESS) | |
683 | goto exit_get_event_log; | |
684 | ||
685 | event_log_size = mbox_sts[4]; | |
686 | if (event_log_size == 0) | |
687 | goto exit_get_event_log; | |
688 | ||
689 | /* Alloc Memory for Crash Record. */ | |
690 | event_log = dma_alloc_coherent(&ha->pdev->dev, event_log_size, | |
691 | &event_log_dma, GFP_KERNEL); | |
692 | if (event_log == NULL) | |
693 | goto exit_get_event_log; | |
694 | ||
695 | /* Get Crash Record. */ | |
696 | mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG; | |
697 | mbox_cmd[2] = LSDW(event_log_dma); | |
698 | mbox_cmd[3] = MSDW(event_log_dma); | |
699 | if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) != | |
700 | QLA_SUCCESS) { | |
701 | DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event " | |
702 | "log!\n", ha->host_no, __func__)); | |
703 | goto exit_get_event_log; | |
704 | } | |
705 | ||
706 | /* Dump Event Log. */ | |
707 | num_valid_entries = mbox_sts[1]; | |
708 | ||
709 | max_event_log_entries = event_log_size / | |
710 | sizeof(struct conn_event_log_entry); | |
711 | ||
712 | if (num_valid_entries > max_event_log_entries) | |
713 | oldest_entry = num_valid_entries % max_event_log_entries; | |
714 | ||
715 | DEBUG3(printk("scsi%ld: Connection Event Log Dump (%d entries):\n", | |
716 | ha->host_no, num_valid_entries)); | |
717 | ||
11010fec | 718 | if (ql4xextended_error_logging == 3) { |
afaf5a2d DS |
719 | if (oldest_entry == 0) { |
720 | /* Circular Buffer has not wrapped around */ | |
721 | for (i=0; i < num_valid_entries; i++) { | |
722 | qla4xxx_dump_buffer((uint8_t *)event_log+ | |
723 | (i*sizeof(*event_log)), | |
724 | sizeof(*event_log)); | |
725 | } | |
726 | } | |
727 | else { | |
728 | /* Circular Buffer has wrapped around - | |
729 | * display accordingly*/ | |
730 | for (i=oldest_entry; i < max_event_log_entries; i++) { | |
731 | qla4xxx_dump_buffer((uint8_t *)event_log+ | |
732 | (i*sizeof(*event_log)), | |
733 | sizeof(*event_log)); | |
734 | } | |
735 | for (i=0; i < oldest_entry; i++) { | |
736 | qla4xxx_dump_buffer((uint8_t *)event_log+ | |
737 | (i*sizeof(*event_log)), | |
738 | sizeof(*event_log)); | |
739 | } | |
740 | } | |
741 | } | |
742 | ||
743 | exit_get_event_log: | |
744 | if (event_log) | |
745 | dma_free_coherent(&ha->pdev->dev, event_log_size, event_log, | |
746 | event_log_dma); | |
747 | } | |
47975477 | 748 | #endif /* 0 */ |
afaf5a2d DS |
749 | |
750 | /** | |
751 | * qla4xxx_reset_lun - issues LUN Reset | |
752 | * @ha: Pointer to host adapter structure. | |
753 | * @db_entry: Pointer to device database entry | |
754 | * @un_entry: Pointer to lun entry structure | |
755 | * | |
756 | * This routine performs a LUN RESET on the specified target/lun. | |
757 | * The caller must ensure that the ddb_entry and lun_entry pointers | |
758 | * are valid before calling this routine. | |
759 | **/ | |
760 | int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry, | |
761 | int lun) | |
762 | { | |
763 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
764 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
765 | int status = QLA_SUCCESS; | |
766 | ||
767 | DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no, | |
768 | ddb_entry->os_target_id, lun)); | |
769 | ||
770 | /* | |
771 | * Send lun reset command to ISP, so that the ISP will return all | |
772 | * outstanding requests with RESET status | |
773 | */ | |
774 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
775 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | |
776 | mbox_cmd[0] = MBOX_CMD_LUN_RESET; | |
777 | mbox_cmd[1] = ddb_entry->fw_ddb_index; | |
778 | mbox_cmd[2] = lun << 8; | |
779 | mbox_cmd[5] = 0x01; /* Immediate Command Enable */ | |
780 | qla4xxx_mailbox_command(ha, 6, 1, &mbox_cmd[0], &mbox_sts[0]); | |
781 | if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE && | |
782 | mbox_sts[0] != MBOX_STS_COMMAND_ERROR) | |
783 | status = QLA_ERROR; | |
784 | ||
785 | return status; | |
786 | } | |
787 | ||
788 | ||
789 | int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr, | |
790 | uint32_t offset, uint32_t len) | |
791 | { | |
792 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
793 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
794 | ||
795 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
796 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | |
797 | mbox_cmd[0] = MBOX_CMD_READ_FLASH; | |
798 | mbox_cmd[1] = LSDW(dma_addr); | |
799 | mbox_cmd[2] = MSDW(dma_addr); | |
800 | mbox_cmd[3] = offset; | |
801 | mbox_cmd[4] = len; | |
802 | if (qla4xxx_mailbox_command(ha, 5, 2, &mbox_cmd[0], &mbox_sts[0]) != | |
803 | QLA_SUCCESS) { | |
804 | DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ " | |
805 | "status %04X %04X, offset %08x, len %08x\n", ha->host_no, | |
806 | __func__, mbox_sts[0], mbox_sts[1], offset, len)); | |
807 | return QLA_ERROR; | |
808 | } | |
809 | return QLA_SUCCESS; | |
810 | } | |
811 | ||
812 | /** | |
813 | * qla4xxx_get_fw_version - gets firmware version | |
814 | * @ha: Pointer to host adapter structure. | |
815 | * | |
816 | * Retrieves the firmware version on HBA. In QLA4010, mailboxes 2 & 3 may | |
817 | * hold an address for data. Make sure that we write 0 to those mailboxes, | |
818 | * if unused. | |
819 | **/ | |
820 | int qla4xxx_get_fw_version(struct scsi_qla_host * ha) | |
821 | { | |
822 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
823 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
824 | ||
825 | /* Get firmware version. */ | |
826 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
827 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | |
828 | mbox_cmd[0] = MBOX_CMD_ABOUT_FW; | |
829 | if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) != | |
830 | QLA_SUCCESS) { | |
831 | DEBUG2(printk("scsi%ld: %s: MBOX_CMD_ABOUT_FW failed w/ " | |
832 | "status %04X\n", ha->host_no, __func__, mbox_sts[0])); | |
833 | return QLA_ERROR; | |
834 | } | |
835 | ||
836 | /* Save firmware version information. */ | |
837 | ha->firmware_version[0] = mbox_sts[1]; | |
838 | ha->firmware_version[1] = mbox_sts[2]; | |
839 | ha->patch_number = mbox_sts[3]; | |
840 | ha->build_number = mbox_sts[4]; | |
841 | ||
842 | return QLA_SUCCESS; | |
843 | } | |
844 | ||
47975477 AB |
845 | static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, |
846 | dma_addr_t dma_addr) | |
afaf5a2d DS |
847 | { |
848 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
849 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
850 | ||
851 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
852 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | |
853 | ||
854 | mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS; | |
855 | mbox_cmd[2] = LSDW(dma_addr); | |
856 | mbox_cmd[3] = MSDW(dma_addr); | |
857 | ||
858 | if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) != | |
859 | QLA_SUCCESS) { | |
860 | DEBUG2(printk("scsi%ld: %s: failed status %04X\n", | |
861 | ha->host_no, __func__, mbox_sts[0])); | |
862 | return QLA_ERROR; | |
863 | } | |
864 | return QLA_SUCCESS; | |
865 | } | |
866 | ||
47975477 | 867 | static int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index) |
afaf5a2d DS |
868 | { |
869 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | |
870 | uint32_t mbox_sts[MBOX_REG_COUNT]; | |
871 | ||
872 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | |
873 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | |
874 | ||
875 | mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY; | |
876 | mbox_cmd[1] = MAX_PRST_DEV_DB_ENTRIES; | |
877 | ||
878 | if (qla4xxx_mailbox_command(ha, 2, 3, &mbox_cmd[0], &mbox_sts[0]) != | |
879 | QLA_SUCCESS) { | |
880 | if (mbox_sts[0] == MBOX_STS_COMMAND_ERROR) { | |
881 | *ddb_index = mbox_sts[2]; | |
882 | } else { | |
883 | DEBUG2(printk("scsi%ld: %s: failed status %04X\n", | |
884 | ha->host_no, __func__, mbox_sts[0])); | |
885 | return QLA_ERROR; | |
886 | } | |
887 | } else { | |
888 | *ddb_index = MAX_PRST_DEV_DB_ENTRIES; | |
889 | } | |
890 | ||
891 | return QLA_SUCCESS; | |
892 | } | |
893 | ||
894 | ||
895 | int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port) | |
896 | { | |
897 | struct dev_db_entry *fw_ddb_entry; | |
898 | dma_addr_t fw_ddb_entry_dma; | |
899 | uint32_t ddb_index; | |
900 | int ret_val = QLA_SUCCESS; | |
901 | ||
902 | ||
903 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, | |
904 | sizeof(*fw_ddb_entry), | |
905 | &fw_ddb_entry_dma, GFP_KERNEL); | |
906 | if (!fw_ddb_entry) { | |
907 | DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n", | |
908 | ha->host_no, __func__)); | |
909 | ret_val = QLA_ERROR; | |
910 | goto qla4xxx_send_tgts_exit; | |
911 | } | |
912 | ||
913 | ret_val = qla4xxx_get_default_ddb(ha, fw_ddb_entry_dma); | |
914 | if (ret_val != QLA_SUCCESS) | |
915 | goto qla4xxx_send_tgts_exit; | |
916 | ||
917 | ret_val = qla4xxx_req_ddb_entry(ha, &ddb_index); | |
918 | if (ret_val != QLA_SUCCESS) | |
919 | goto qla4xxx_send_tgts_exit; | |
920 | ||
921 | memset((void *)fw_ddb_entry->iSCSIAlias, 0, | |
922 | sizeof(fw_ddb_entry->iSCSIAlias)); | |
923 | ||
924 | memset((void *)fw_ddb_entry->iscsiName, 0, | |
925 | sizeof(fw_ddb_entry->iscsiName)); | |
926 | ||
927 | memset((void *)fw_ddb_entry->ipAddr, 0, sizeof(fw_ddb_entry->ipAddr)); | |
928 | memset((void *)fw_ddb_entry->targetAddr, 0, | |
929 | sizeof(fw_ddb_entry->targetAddr)); | |
930 | ||
931 | fw_ddb_entry->options = (DDB_OPT_DISC_SESSION | DDB_OPT_TARGET); | |
932 | fw_ddb_entry->portNumber = cpu_to_le16(ntohs(port)); | |
933 | ||
934 | fw_ddb_entry->ipAddr[0] = *ip; | |
935 | fw_ddb_entry->ipAddr[1] = *(ip + 1); | |
936 | fw_ddb_entry->ipAddr[2] = *(ip + 2); | |
937 | fw_ddb_entry->ipAddr[3] = *(ip + 3); | |
938 | ||
939 | ret_val = qla4xxx_set_ddb_entry(ha, ddb_index, fw_ddb_entry_dma); | |
940 | ||
941 | qla4xxx_send_tgts_exit: | |
942 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | |
943 | fw_ddb_entry, fw_ddb_entry_dma); | |
944 | return ret_val; | |
945 | } | |
946 |