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