1 /** 2 * Copyright (C) 2005 - 2011 Emulex 3 * All rights reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License version 2 7 * as published by the Free Software Foundation. The full GNU General 8 * Public License is included in this distribution in the file called COPYING. 9 * 10 * Written by: Jayamohan Kallickal (jayamohan.kallickal@emulex.com) 11 * 12 * Contact Information: 13 * linux-drivers@emulex.com 14 * 15 * Emulex 16 * 3333 Susan Street 17 * Costa Mesa, CA 92626 18 */ 19 20 #include "be_mgmt.h" 21 #include "be_iscsi.h" 22 #include <scsi/scsi_transport_iscsi.h> 23 24 unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba) 25 { 26 struct be_ctrl_info *ctrl = &phba->ctrl; 27 struct be_mcc_wrb *wrb; 28 struct be_cmd_req_get_mac_addr *req; 29 unsigned int tag = 0; 30 31 SE_DEBUG(DBG_LVL_8, "In bescsi_get_boot_target\n"); 32 spin_lock(&ctrl->mbox_lock); 33 tag = alloc_mcc_tag(phba); 34 if (!tag) { 35 spin_unlock(&ctrl->mbox_lock); 36 return tag; 37 } 38 39 wrb = wrb_from_mccq(phba); 40 req = embedded_payload(wrb); 41 wrb->tag0 |= tag; 42 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 43 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, 44 OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET, 45 sizeof(*req)); 46 47 be_mcc_notify(phba); 48 spin_unlock(&ctrl->mbox_lock); 49 return tag; 50 } 51 52 unsigned int beiscsi_get_session_info(struct beiscsi_hba *phba, 53 u32 boot_session_handle, 54 struct be_dma_mem *nonemb_cmd) 55 { 56 struct be_ctrl_info *ctrl = &phba->ctrl; 57 struct be_mcc_wrb *wrb; 58 unsigned int tag = 0; 59 struct be_cmd_req_get_session *req; 60 struct be_cmd_resp_get_session *resp; 61 struct be_sge *sge; 62 63 SE_DEBUG(DBG_LVL_8, "In beiscsi_get_session_info\n"); 64 spin_lock(&ctrl->mbox_lock); 65 tag = alloc_mcc_tag(phba); 66 if (!tag) { 67 spin_unlock(&ctrl->mbox_lock); 68 return tag; 69 } 70 71 nonemb_cmd->size = sizeof(*resp); 72 req = nonemb_cmd->va; 73 memset(req, 0, sizeof(*req)); 74 wrb = wrb_from_mccq(phba); 75 sge = nonembedded_sgl(wrb); 76 wrb->tag0 |= tag; 77 78 79 wrb->tag0 |= tag; 80 be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); 81 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, 82 OPCODE_ISCSI_INI_SESSION_GET_A_SESSION, 83 sizeof(*resp)); 84 req->session_handle = boot_session_handle; 85 sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); 86 sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); 87 sge->len = cpu_to_le32(nonemb_cmd->size); 88 89 be_mcc_notify(phba); 90 spin_unlock(&ctrl->mbox_lock); 91 return tag; 92 } 93 94 int mgmt_get_fw_config(struct be_ctrl_info *ctrl, 95 struct beiscsi_hba *phba) 96 { 97 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 98 struct be_fw_cfg *req = embedded_payload(wrb); 99 int status = 0; 100 101 spin_lock(&ctrl->mbox_lock); 102 memset(wrb, 0, sizeof(*wrb)); 103 104 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 105 106 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 107 OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req)); 108 status = be_mbox_notify(ctrl); 109 if (!status) { 110 struct be_fw_cfg *pfw_cfg; 111 pfw_cfg = req; 112 phba->fw_config.phys_port = pfw_cfg->phys_port; 113 phba->fw_config.iscsi_icd_start = 114 pfw_cfg->ulp[0].icd_base; 115 phba->fw_config.iscsi_icd_count = 116 pfw_cfg->ulp[0].icd_count; 117 phba->fw_config.iscsi_cid_start = 118 pfw_cfg->ulp[0].sq_base; 119 phba->fw_config.iscsi_cid_count = 120 pfw_cfg->ulp[0].sq_count; 121 if (phba->fw_config.iscsi_cid_count > (BE2_MAX_SESSIONS / 2)) { 122 SE_DEBUG(DBG_LVL_8, 123 "FW reported MAX CXNS as %d\t" 124 "Max Supported = %d.\n", 125 phba->fw_config.iscsi_cid_count, 126 BE2_MAX_SESSIONS); 127 phba->fw_config.iscsi_cid_count = BE2_MAX_SESSIONS / 2; 128 } 129 } else { 130 shost_printk(KERN_WARNING, phba->shost, 131 "Failed in mgmt_get_fw_config\n"); 132 } 133 134 spin_unlock(&ctrl->mbox_lock); 135 return status; 136 } 137 138 int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, 139 struct beiscsi_hba *phba) 140 { 141 struct be_dma_mem nonemb_cmd; 142 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 143 struct be_mgmt_controller_attributes *req; 144 struct be_sge *sge = nonembedded_sgl(wrb); 145 int status = 0; 146 147 nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev, 148 sizeof(struct be_mgmt_controller_attributes), 149 &nonemb_cmd.dma); 150 if (nonemb_cmd.va == NULL) { 151 SE_DEBUG(DBG_LVL_1, 152 "Failed to allocate memory for mgmt_check_supported_fw" 153 "\n"); 154 return -ENOMEM; 155 } 156 nonemb_cmd.size = sizeof(struct be_mgmt_controller_attributes); 157 req = nonemb_cmd.va; 158 memset(req, 0, sizeof(*req)); 159 spin_lock(&ctrl->mbox_lock); 160 memset(wrb, 0, sizeof(*wrb)); 161 be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); 162 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 163 OPCODE_COMMON_GET_CNTL_ATTRIBUTES, sizeof(*req)); 164 sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); 165 sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); 166 sge->len = cpu_to_le32(nonemb_cmd.size); 167 status = be_mbox_notify(ctrl); 168 if (!status) { 169 struct be_mgmt_controller_attributes_resp *resp = nonemb_cmd.va; 170 SE_DEBUG(DBG_LVL_8, "Firmware version of CMD: %s\n", 171 resp->params.hba_attribs.flashrom_version_string); 172 SE_DEBUG(DBG_LVL_8, "Firmware version is : %s\n", 173 resp->params.hba_attribs.firmware_version_string); 174 SE_DEBUG(DBG_LVL_8, 175 "Developer Build, not performing version check...\n"); 176 phba->fw_config.iscsi_features = 177 resp->params.hba_attribs.iscsi_features; 178 SE_DEBUG(DBG_LVL_8, " phba->fw_config.iscsi_features = %d\n", 179 phba->fw_config.iscsi_features); 180 } else 181 SE_DEBUG(DBG_LVL_1, " Failed in mgmt_check_supported_fw\n"); 182 spin_unlock(&ctrl->mbox_lock); 183 if (nonemb_cmd.va) 184 pci_free_consistent(ctrl->pdev, nonemb_cmd.size, 185 nonemb_cmd.va, nonemb_cmd.dma); 186 187 return status; 188 } 189 190 int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) 191 { 192 struct be_ctrl_info *ctrl = &phba->ctrl; 193 struct be_mcc_wrb *wrb = wrb_from_mccq(phba); 194 struct iscsi_cleanup_req *req = embedded_payload(wrb); 195 int status = 0; 196 197 spin_lock(&ctrl->mbox_lock); 198 memset(wrb, 0, sizeof(*wrb)); 199 200 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 201 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 202 OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req)); 203 204 req->chute = chute; 205 req->hdr_ring_id = cpu_to_le16(HWI_GET_DEF_HDRQ_ID(phba)); 206 req->data_ring_id = cpu_to_le16(HWI_GET_DEF_BUFQ_ID(phba)); 207 208 status = be_mcc_notify_wait(phba); 209 if (status) 210 shost_printk(KERN_WARNING, phba->shost, 211 " mgmt_epfw_cleanup , FAILED\n"); 212 spin_unlock(&ctrl->mbox_lock); 213 return status; 214 } 215 216 unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, 217 struct invalidate_command_table *inv_tbl, 218 unsigned int num_invalidate, unsigned int cid, 219 struct be_dma_mem *nonemb_cmd) 220 221 { 222 struct be_ctrl_info *ctrl = &phba->ctrl; 223 struct be_mcc_wrb *wrb; 224 struct be_sge *sge; 225 struct invalidate_commands_params_in *req; 226 unsigned int i, tag = 0; 227 228 spin_lock(&ctrl->mbox_lock); 229 tag = alloc_mcc_tag(phba); 230 if (!tag) { 231 spin_unlock(&ctrl->mbox_lock); 232 return tag; 233 } 234 235 req = nonemb_cmd->va; 236 memset(req, 0, sizeof(*req)); 237 wrb = wrb_from_mccq(phba); 238 sge = nonembedded_sgl(wrb); 239 wrb->tag0 |= tag; 240 241 be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); 242 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 243 OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS, 244 sizeof(*req)); 245 req->ref_handle = 0; 246 req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE; 247 for (i = 0; i < num_invalidate; i++) { 248 req->table[i].icd = inv_tbl->icd; 249 req->table[i].cid = inv_tbl->cid; 250 req->icd_count++; 251 inv_tbl++; 252 } 253 sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); 254 sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); 255 sge->len = cpu_to_le32(nonemb_cmd->size); 256 257 be_mcc_notify(phba); 258 spin_unlock(&ctrl->mbox_lock); 259 return tag; 260 } 261 262 unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba, 263 struct beiscsi_endpoint *beiscsi_ep, 264 unsigned short cid, 265 unsigned short issue_reset, 266 unsigned short savecfg_flag) 267 { 268 struct be_ctrl_info *ctrl = &phba->ctrl; 269 struct be_mcc_wrb *wrb; 270 struct iscsi_invalidate_connection_params_in *req; 271 unsigned int tag = 0; 272 273 spin_lock(&ctrl->mbox_lock); 274 tag = alloc_mcc_tag(phba); 275 if (!tag) { 276 spin_unlock(&ctrl->mbox_lock); 277 return tag; 278 } 279 wrb = wrb_from_mccq(phba); 280 wrb->tag0 |= tag; 281 req = embedded_payload(wrb); 282 283 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 284 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, 285 OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION, 286 sizeof(*req)); 287 req->session_handle = beiscsi_ep->fw_handle; 288 req->cid = cid; 289 if (issue_reset) 290 req->cleanup_type = CMD_ISCSI_CONNECTION_ISSUE_TCP_RST; 291 else 292 req->cleanup_type = CMD_ISCSI_CONNECTION_INVALIDATE; 293 req->save_cfg = savecfg_flag; 294 be_mcc_notify(phba); 295 spin_unlock(&ctrl->mbox_lock); 296 return tag; 297 } 298 299 unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, 300 unsigned short cid, unsigned int upload_flag) 301 { 302 struct be_ctrl_info *ctrl = &phba->ctrl; 303 struct be_mcc_wrb *wrb; 304 struct tcp_upload_params_in *req; 305 unsigned int tag = 0; 306 307 spin_lock(&ctrl->mbox_lock); 308 tag = alloc_mcc_tag(phba); 309 if (!tag) { 310 spin_unlock(&ctrl->mbox_lock); 311 return tag; 312 } 313 wrb = wrb_from_mccq(phba); 314 req = embedded_payload(wrb); 315 wrb->tag0 |= tag; 316 317 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 318 be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD, 319 OPCODE_COMMON_TCP_UPLOAD, sizeof(*req)); 320 req->id = (unsigned short)cid; 321 req->upload_type = (unsigned char)upload_flag; 322 be_mcc_notify(phba); 323 spin_unlock(&ctrl->mbox_lock); 324 return tag; 325 } 326 327 int mgmt_open_connection(struct beiscsi_hba *phba, 328 struct sockaddr *dst_addr, 329 struct beiscsi_endpoint *beiscsi_ep, 330 struct be_dma_mem *nonemb_cmd) 331 332 { 333 struct hwi_controller *phwi_ctrlr; 334 struct hwi_context_memory *phwi_context; 335 struct sockaddr_in *daddr_in = (struct sockaddr_in *)dst_addr; 336 struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)dst_addr; 337 struct be_ctrl_info *ctrl = &phba->ctrl; 338 struct be_mcc_wrb *wrb; 339 struct tcp_connect_and_offload_in *req; 340 unsigned short def_hdr_id; 341 unsigned short def_data_id; 342 struct phys_addr template_address = { 0, 0 }; 343 struct phys_addr *ptemplate_address; 344 unsigned int tag = 0; 345 unsigned int i; 346 unsigned short cid = beiscsi_ep->ep_cid; 347 struct be_sge *sge; 348 349 phwi_ctrlr = phba->phwi_ctrlr; 350 phwi_context = phwi_ctrlr->phwi_ctxt; 351 def_hdr_id = (unsigned short)HWI_GET_DEF_HDRQ_ID(phba); 352 def_data_id = (unsigned short)HWI_GET_DEF_BUFQ_ID(phba); 353 354 ptemplate_address = &template_address; 355 ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address); 356 spin_lock(&ctrl->mbox_lock); 357 tag = alloc_mcc_tag(phba); 358 if (!tag) { 359 spin_unlock(&ctrl->mbox_lock); 360 return tag; 361 } 362 wrb = wrb_from_mccq(phba); 363 memset(wrb, 0, sizeof(*wrb)); 364 sge = nonembedded_sgl(wrb); 365 366 req = nonemb_cmd->va; 367 memset(req, 0, sizeof(*req)); 368 wrb->tag0 |= tag; 369 370 be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); 371 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 372 OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD, 373 sizeof(*req)); 374 if (dst_addr->sa_family == PF_INET) { 375 __be32 s_addr = daddr_in->sin_addr.s_addr; 376 req->ip_address.ip_type = BE2_IPV4; 377 req->ip_address.ip_address[0] = s_addr & 0x000000ff; 378 req->ip_address.ip_address[1] = (s_addr & 0x0000ff00) >> 8; 379 req->ip_address.ip_address[2] = (s_addr & 0x00ff0000) >> 16; 380 req->ip_address.ip_address[3] = (s_addr & 0xff000000) >> 24; 381 req->tcp_port = ntohs(daddr_in->sin_port); 382 beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr; 383 beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port); 384 beiscsi_ep->ip_type = BE2_IPV4; 385 } else if (dst_addr->sa_family == PF_INET6) { 386 req->ip_address.ip_type = BE2_IPV6; 387 memcpy(&req->ip_address.ip_address, 388 &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); 389 req->tcp_port = ntohs(daddr_in6->sin6_port); 390 beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port); 391 memcpy(&beiscsi_ep->dst6_addr, 392 &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); 393 beiscsi_ep->ip_type = BE2_IPV6; 394 } else{ 395 shost_printk(KERN_ERR, phba->shost, "unknown addr family %d\n", 396 dst_addr->sa_family); 397 spin_unlock(&ctrl->mbox_lock); 398 free_mcc_tag(&phba->ctrl, tag); 399 return -EINVAL; 400 401 } 402 req->cid = cid; 403 i = phba->nxt_cqid++; 404 if (phba->nxt_cqid == phba->num_cpus) 405 phba->nxt_cqid = 0; 406 req->cq_id = phwi_context->be_cq[i].id; 407 SE_DEBUG(DBG_LVL_8, "i=%d cq_id=%d\n", i, req->cq_id); 408 req->defq_id = def_hdr_id; 409 req->hdr_ring_id = def_hdr_id; 410 req->data_ring_id = def_data_id; 411 req->do_offload = 1; 412 req->dataout_template_pa.lo = ptemplate_address->lo; 413 req->dataout_template_pa.hi = ptemplate_address->hi; 414 sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); 415 sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); 416 sge->len = cpu_to_le32(nonemb_cmd->size); 417 be_mcc_notify(phba); 418 spin_unlock(&ctrl->mbox_lock); 419 return tag; 420 } 421 422 unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba) 423 { 424 struct be_ctrl_info *ctrl = &phba->ctrl; 425 struct be_mcc_wrb *wrb; 426 struct be_cmd_req_get_mac_addr *req; 427 unsigned int tag = 0; 428 429 SE_DEBUG(DBG_LVL_8, "In be_cmd_get_mac_addr\n"); 430 spin_lock(&ctrl->mbox_lock); 431 tag = alloc_mcc_tag(phba); 432 if (!tag) { 433 spin_unlock(&ctrl->mbox_lock); 434 return tag; 435 } 436 437 wrb = wrb_from_mccq(phba); 438 req = embedded_payload(wrb); 439 wrb->tag0 |= tag; 440 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 441 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 442 OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG, 443 sizeof(*req)); 444 445 be_mcc_notify(phba); 446 spin_unlock(&ctrl->mbox_lock); 447 return tag; 448 } 449 450