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 <linux/bsg-lib.h> 21 #include <scsi/scsi_transport_iscsi.h> 22 #include <scsi/scsi_bsg_iscsi.h> 23 #include "be_mgmt.h" 24 #include "be_iscsi.h" 25 26 unsigned int mgmt_get_boot_target(struct beiscsi_hba *phba) 27 { 28 struct be_ctrl_info *ctrl = &phba->ctrl; 29 struct be_mcc_wrb *wrb; 30 struct be_cmd_get_boot_target_req *req; 31 unsigned int tag = 0; 32 33 SE_DEBUG(DBG_LVL_8, "In bescsi_get_boot_target\n"); 34 spin_lock(&ctrl->mbox_lock); 35 tag = alloc_mcc_tag(phba); 36 if (!tag) { 37 spin_unlock(&ctrl->mbox_lock); 38 return tag; 39 } 40 41 wrb = wrb_from_mccq(phba); 42 req = embedded_payload(wrb); 43 wrb->tag0 |= tag; 44 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 45 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, 46 OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET, 47 sizeof(struct be_cmd_get_boot_target_resp)); 48 49 be_mcc_notify(phba); 50 spin_unlock(&ctrl->mbox_lock); 51 return tag; 52 } 53 54 unsigned int mgmt_get_session_info(struct beiscsi_hba *phba, 55 u32 boot_session_handle, 56 struct be_dma_mem *nonemb_cmd) 57 { 58 struct be_ctrl_info *ctrl = &phba->ctrl; 59 struct be_mcc_wrb *wrb; 60 unsigned int tag = 0; 61 struct be_cmd_get_session_req *req; 62 struct be_cmd_get_session_resp *resp; 63 struct be_sge *sge; 64 65 SE_DEBUG(DBG_LVL_8, "In beiscsi_get_session_info\n"); 66 spin_lock(&ctrl->mbox_lock); 67 tag = alloc_mcc_tag(phba); 68 if (!tag) { 69 spin_unlock(&ctrl->mbox_lock); 70 return tag; 71 } 72 73 nonemb_cmd->size = sizeof(*resp); 74 req = nonemb_cmd->va; 75 memset(req, 0, sizeof(*req)); 76 wrb = wrb_from_mccq(phba); 77 sge = nonembedded_sgl(wrb); 78 wrb->tag0 |= tag; 79 80 81 wrb->tag0 |= tag; 82 be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); 83 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, 84 OPCODE_ISCSI_INI_SESSION_GET_A_SESSION, 85 sizeof(*resp)); 86 req->session_handle = boot_session_handle; 87 sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); 88 sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); 89 sge->len = cpu_to_le32(nonemb_cmd->size); 90 91 be_mcc_notify(phba); 92 spin_unlock(&ctrl->mbox_lock); 93 return tag; 94 } 95 96 int mgmt_get_fw_config(struct be_ctrl_info *ctrl, 97 struct beiscsi_hba *phba) 98 { 99 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 100 struct be_fw_cfg *req = embedded_payload(wrb); 101 int status = 0; 102 103 spin_lock(&ctrl->mbox_lock); 104 memset(wrb, 0, sizeof(*wrb)); 105 106 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 107 108 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 109 OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req)); 110 status = be_mbox_notify(ctrl); 111 if (!status) { 112 struct be_fw_cfg *pfw_cfg; 113 pfw_cfg = req; 114 phba->fw_config.phys_port = pfw_cfg->phys_port; 115 phba->fw_config.iscsi_icd_start = 116 pfw_cfg->ulp[0].icd_base; 117 phba->fw_config.iscsi_icd_count = 118 pfw_cfg->ulp[0].icd_count; 119 phba->fw_config.iscsi_cid_start = 120 pfw_cfg->ulp[0].sq_base; 121 phba->fw_config.iscsi_cid_count = 122 pfw_cfg->ulp[0].sq_count; 123 if (phba->fw_config.iscsi_cid_count > (BE2_MAX_SESSIONS / 2)) { 124 SE_DEBUG(DBG_LVL_8, 125 "FW reported MAX CXNS as %d\t" 126 "Max Supported = %d.\n", 127 phba->fw_config.iscsi_cid_count, 128 BE2_MAX_SESSIONS); 129 phba->fw_config.iscsi_cid_count = BE2_MAX_SESSIONS / 2; 130 } 131 } else { 132 shost_printk(KERN_WARNING, phba->shost, 133 "Failed in mgmt_get_fw_config\n"); 134 } 135 136 spin_unlock(&ctrl->mbox_lock); 137 return status; 138 } 139 140 int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, 141 struct beiscsi_hba *phba) 142 { 143 struct be_dma_mem nonemb_cmd; 144 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 145 struct be_mgmt_controller_attributes *req; 146 struct be_sge *sge = nonembedded_sgl(wrb); 147 int status = 0; 148 149 nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev, 150 sizeof(struct be_mgmt_controller_attributes), 151 &nonemb_cmd.dma); 152 if (nonemb_cmd.va == NULL) { 153 SE_DEBUG(DBG_LVL_1, 154 "Failed to allocate memory for mgmt_check_supported_fw" 155 "\n"); 156 return -ENOMEM; 157 } 158 nonemb_cmd.size = sizeof(struct be_mgmt_controller_attributes); 159 req = nonemb_cmd.va; 160 memset(req, 0, sizeof(*req)); 161 spin_lock(&ctrl->mbox_lock); 162 memset(wrb, 0, sizeof(*wrb)); 163 be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); 164 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 165 OPCODE_COMMON_GET_CNTL_ATTRIBUTES, sizeof(*req)); 166 sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); 167 sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); 168 sge->len = cpu_to_le32(nonemb_cmd.size); 169 status = be_mbox_notify(ctrl); 170 if (!status) { 171 struct be_mgmt_controller_attributes_resp *resp = nonemb_cmd.va; 172 SE_DEBUG(DBG_LVL_8, "Firmware version of CMD: %s\n", 173 resp->params.hba_attribs.flashrom_version_string); 174 SE_DEBUG(DBG_LVL_8, "Firmware version is : %s\n", 175 resp->params.hba_attribs.firmware_version_string); 176 SE_DEBUG(DBG_LVL_8, 177 "Developer Build, not performing version check...\n"); 178 phba->fw_config.iscsi_features = 179 resp->params.hba_attribs.iscsi_features; 180 SE_DEBUG(DBG_LVL_8, " phba->fw_config.iscsi_features = %d\n", 181 phba->fw_config.iscsi_features); 182 } else 183 SE_DEBUG(DBG_LVL_1, " Failed in mgmt_check_supported_fw\n"); 184 spin_unlock(&ctrl->mbox_lock); 185 if (nonemb_cmd.va) 186 pci_free_consistent(ctrl->pdev, nonemb_cmd.size, 187 nonemb_cmd.va, nonemb_cmd.dma); 188 189 return status; 190 } 191 192 unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, 193 struct beiscsi_hba *phba, 194 struct bsg_job *job, 195 struct be_dma_mem *nonemb_cmd) 196 { 197 struct be_cmd_resp_hdr *resp; 198 struct be_mcc_wrb *wrb = wrb_from_mccq(phba); 199 struct be_sge *mcc_sge = nonembedded_sgl(wrb); 200 unsigned int tag = 0; 201 struct iscsi_bsg_request *bsg_req = job->request; 202 struct be_bsg_vendor_cmd *req = nonemb_cmd->va; 203 unsigned short region, sector_size, sector, offset; 204 205 nonemb_cmd->size = job->request_payload.payload_len; 206 memset(nonemb_cmd->va, 0, nonemb_cmd->size); 207 resp = nonemb_cmd->va; 208 region = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; 209 sector_size = bsg_req->rqst_data.h_vendor.vendor_cmd[2]; 210 sector = bsg_req->rqst_data.h_vendor.vendor_cmd[3]; 211 offset = bsg_req->rqst_data.h_vendor.vendor_cmd[4]; 212 req->region = region; 213 req->sector = sector; 214 req->offset = offset; 215 spin_lock(&ctrl->mbox_lock); 216 memset(wrb, 0, sizeof(*wrb)); 217 218 switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) { 219 case BEISCSI_WRITE_FLASH: 220 offset = sector * sector_size + offset; 221 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 222 OPCODE_COMMON_WRITE_FLASH, sizeof(*req)); 223 sg_copy_to_buffer(job->request_payload.sg_list, 224 job->request_payload.sg_cnt, 225 nonemb_cmd->va + offset, job->request_len); 226 break; 227 case BEISCSI_READ_FLASH: 228 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 229 OPCODE_COMMON_READ_FLASH, sizeof(*req)); 230 break; 231 default: 232 shost_printk(KERN_WARNING, phba->shost, 233 "Unsupported cmd = 0x%x\n\n", bsg_req->rqst_data. 234 h_vendor.vendor_cmd[0]); 235 spin_unlock(&ctrl->mbox_lock); 236 return -ENOSYS; 237 } 238 239 tag = alloc_mcc_tag(phba); 240 if (!tag) { 241 spin_unlock(&ctrl->mbox_lock); 242 return tag; 243 } 244 245 be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 246 job->request_payload.sg_cnt); 247 mcc_sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); 248 mcc_sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); 249 mcc_sge->len = cpu_to_le32(nonemb_cmd->size); 250 wrb->tag0 |= tag; 251 252 be_mcc_notify(phba); 253 254 spin_unlock(&ctrl->mbox_lock); 255 return tag; 256 } 257 258 int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) 259 { 260 struct be_ctrl_info *ctrl = &phba->ctrl; 261 struct be_mcc_wrb *wrb = wrb_from_mccq(phba); 262 struct iscsi_cleanup_req *req = embedded_payload(wrb); 263 int status = 0; 264 265 spin_lock(&ctrl->mbox_lock); 266 memset(wrb, 0, sizeof(*wrb)); 267 268 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 269 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 270 OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req)); 271 272 req->chute = chute; 273 req->hdr_ring_id = cpu_to_le16(HWI_GET_DEF_HDRQ_ID(phba)); 274 req->data_ring_id = cpu_to_le16(HWI_GET_DEF_BUFQ_ID(phba)); 275 276 status = be_mcc_notify_wait(phba); 277 if (status) 278 shost_printk(KERN_WARNING, phba->shost, 279 " mgmt_epfw_cleanup , FAILED\n"); 280 spin_unlock(&ctrl->mbox_lock); 281 return status; 282 } 283 284 unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, 285 struct invalidate_command_table *inv_tbl, 286 unsigned int num_invalidate, unsigned int cid, 287 struct be_dma_mem *nonemb_cmd) 288 289 { 290 struct be_ctrl_info *ctrl = &phba->ctrl; 291 struct be_mcc_wrb *wrb; 292 struct be_sge *sge; 293 struct invalidate_commands_params_in *req; 294 unsigned int i, tag = 0; 295 296 spin_lock(&ctrl->mbox_lock); 297 tag = alloc_mcc_tag(phba); 298 if (!tag) { 299 spin_unlock(&ctrl->mbox_lock); 300 return tag; 301 } 302 303 req = nonemb_cmd->va; 304 memset(req, 0, sizeof(*req)); 305 wrb = wrb_from_mccq(phba); 306 sge = nonembedded_sgl(wrb); 307 wrb->tag0 |= tag; 308 309 be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); 310 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 311 OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS, 312 sizeof(*req)); 313 req->ref_handle = 0; 314 req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE; 315 for (i = 0; i < num_invalidate; i++) { 316 req->table[i].icd = inv_tbl->icd; 317 req->table[i].cid = inv_tbl->cid; 318 req->icd_count++; 319 inv_tbl++; 320 } 321 sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); 322 sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); 323 sge->len = cpu_to_le32(nonemb_cmd->size); 324 325 be_mcc_notify(phba); 326 spin_unlock(&ctrl->mbox_lock); 327 return tag; 328 } 329 330 unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba, 331 struct beiscsi_endpoint *beiscsi_ep, 332 unsigned short cid, 333 unsigned short issue_reset, 334 unsigned short savecfg_flag) 335 { 336 struct be_ctrl_info *ctrl = &phba->ctrl; 337 struct be_mcc_wrb *wrb; 338 struct iscsi_invalidate_connection_params_in *req; 339 unsigned int tag = 0; 340 341 spin_lock(&ctrl->mbox_lock); 342 tag = alloc_mcc_tag(phba); 343 if (!tag) { 344 spin_unlock(&ctrl->mbox_lock); 345 return tag; 346 } 347 wrb = wrb_from_mccq(phba); 348 wrb->tag0 |= tag; 349 req = embedded_payload(wrb); 350 351 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 352 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, 353 OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION, 354 sizeof(*req)); 355 req->session_handle = beiscsi_ep->fw_handle; 356 req->cid = cid; 357 if (issue_reset) 358 req->cleanup_type = CMD_ISCSI_CONNECTION_ISSUE_TCP_RST; 359 else 360 req->cleanup_type = CMD_ISCSI_CONNECTION_INVALIDATE; 361 req->save_cfg = savecfg_flag; 362 be_mcc_notify(phba); 363 spin_unlock(&ctrl->mbox_lock); 364 return tag; 365 } 366 367 unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, 368 unsigned short cid, unsigned int upload_flag) 369 { 370 struct be_ctrl_info *ctrl = &phba->ctrl; 371 struct be_mcc_wrb *wrb; 372 struct tcp_upload_params_in *req; 373 unsigned int tag = 0; 374 375 spin_lock(&ctrl->mbox_lock); 376 tag = alloc_mcc_tag(phba); 377 if (!tag) { 378 spin_unlock(&ctrl->mbox_lock); 379 return tag; 380 } 381 wrb = wrb_from_mccq(phba); 382 req = embedded_payload(wrb); 383 wrb->tag0 |= tag; 384 385 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 386 be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD, 387 OPCODE_COMMON_TCP_UPLOAD, sizeof(*req)); 388 req->id = (unsigned short)cid; 389 req->upload_type = (unsigned char)upload_flag; 390 be_mcc_notify(phba); 391 spin_unlock(&ctrl->mbox_lock); 392 return tag; 393 } 394 395 int mgmt_open_connection(struct beiscsi_hba *phba, 396 struct sockaddr *dst_addr, 397 struct beiscsi_endpoint *beiscsi_ep, 398 struct be_dma_mem *nonemb_cmd) 399 { 400 struct hwi_controller *phwi_ctrlr; 401 struct hwi_context_memory *phwi_context; 402 struct sockaddr_in *daddr_in = (struct sockaddr_in *)dst_addr; 403 struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)dst_addr; 404 struct be_ctrl_info *ctrl = &phba->ctrl; 405 struct be_mcc_wrb *wrb; 406 struct tcp_connect_and_offload_in *req; 407 unsigned short def_hdr_id; 408 unsigned short def_data_id; 409 struct phys_addr template_address = { 0, 0 }; 410 struct phys_addr *ptemplate_address; 411 unsigned int tag = 0; 412 unsigned int i; 413 unsigned short cid = beiscsi_ep->ep_cid; 414 struct be_sge *sge; 415 416 phwi_ctrlr = phba->phwi_ctrlr; 417 phwi_context = phwi_ctrlr->phwi_ctxt; 418 def_hdr_id = (unsigned short)HWI_GET_DEF_HDRQ_ID(phba); 419 def_data_id = (unsigned short)HWI_GET_DEF_BUFQ_ID(phba); 420 421 ptemplate_address = &template_address; 422 ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address); 423 spin_lock(&ctrl->mbox_lock); 424 tag = alloc_mcc_tag(phba); 425 if (!tag) { 426 spin_unlock(&ctrl->mbox_lock); 427 return tag; 428 } 429 wrb = wrb_from_mccq(phba); 430 memset(wrb, 0, sizeof(*wrb)); 431 sge = nonembedded_sgl(wrb); 432 433 req = nonemb_cmd->va; 434 memset(req, 0, sizeof(*req)); 435 wrb->tag0 |= tag; 436 437 be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); 438 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 439 OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD, 440 sizeof(*req)); 441 if (dst_addr->sa_family == PF_INET) { 442 __be32 s_addr = daddr_in->sin_addr.s_addr; 443 req->ip_address.ip_type = BE2_IPV4; 444 req->ip_address.addr[0] = s_addr & 0x000000ff; 445 req->ip_address.addr[1] = (s_addr & 0x0000ff00) >> 8; 446 req->ip_address.addr[2] = (s_addr & 0x00ff0000) >> 16; 447 req->ip_address.addr[3] = (s_addr & 0xff000000) >> 24; 448 req->tcp_port = ntohs(daddr_in->sin_port); 449 beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr; 450 beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port); 451 beiscsi_ep->ip_type = BE2_IPV4; 452 } else if (dst_addr->sa_family == PF_INET6) { 453 req->ip_address.ip_type = BE2_IPV6; 454 memcpy(&req->ip_address.addr, 455 &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); 456 req->tcp_port = ntohs(daddr_in6->sin6_port); 457 beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port); 458 memcpy(&beiscsi_ep->dst6_addr, 459 &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); 460 beiscsi_ep->ip_type = BE2_IPV6; 461 } else{ 462 shost_printk(KERN_ERR, phba->shost, "unknown addr family %d\n", 463 dst_addr->sa_family); 464 spin_unlock(&ctrl->mbox_lock); 465 free_mcc_tag(&phba->ctrl, tag); 466 return -EINVAL; 467 468 } 469 req->cid = cid; 470 i = phba->nxt_cqid++; 471 if (phba->nxt_cqid == phba->num_cpus) 472 phba->nxt_cqid = 0; 473 req->cq_id = phwi_context->be_cq[i].id; 474 SE_DEBUG(DBG_LVL_8, "i=%d cq_id=%d\n", i, req->cq_id); 475 req->defq_id = def_hdr_id; 476 req->hdr_ring_id = def_hdr_id; 477 req->data_ring_id = def_data_id; 478 req->do_offload = 1; 479 req->dataout_template_pa.lo = ptemplate_address->lo; 480 req->dataout_template_pa.hi = ptemplate_address->hi; 481 sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); 482 sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); 483 sge->len = cpu_to_le32(nonemb_cmd->size); 484 be_mcc_notify(phba); 485 spin_unlock(&ctrl->mbox_lock); 486 return tag; 487 } 488 489 unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba) 490 { 491 struct be_ctrl_info *ctrl = &phba->ctrl; 492 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 493 struct be_cmd_get_all_if_id_req *req = embedded_payload(wrb); 494 struct be_cmd_get_all_if_id_req *pbe_allid = req; 495 int status = 0; 496 497 memset(wrb, 0, sizeof(*wrb)); 498 499 spin_lock(&ctrl->mbox_lock); 500 501 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 502 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 503 OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID, 504 sizeof(*req)); 505 status = be_mbox_notify(ctrl); 506 if (!status) 507 phba->interface_handle = pbe_allid->if_hndl_list[0]; 508 else { 509 shost_printk(KERN_WARNING, phba->shost, 510 "Failed in mgmt_get_all_if_id\n"); 511 } 512 spin_unlock(&ctrl->mbox_lock); 513 514 return status; 515 } 516 517 static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba, 518 struct be_dma_mem *nonemb_cmd, void *resp_buf, 519 int resp_buf_len) 520 { 521 struct be_ctrl_info *ctrl = &phba->ctrl; 522 struct be_mcc_wrb *wrb = wrb_from_mccq(phba); 523 unsigned short status, extd_status; 524 struct be_sge *sge; 525 unsigned int tag; 526 int rc = 0; 527 528 spin_lock(&ctrl->mbox_lock); 529 tag = alloc_mcc_tag(phba); 530 if (!tag) { 531 spin_unlock(&ctrl->mbox_lock); 532 rc = -ENOMEM; 533 goto free_cmd; 534 } 535 memset(wrb, 0, sizeof(*wrb)); 536 wrb->tag0 |= tag; 537 sge = nonembedded_sgl(wrb); 538 539 be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1); 540 sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); 541 sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); 542 sge->len = cpu_to_le32(nonemb_cmd->size); 543 544 be_mcc_notify(phba); 545 spin_unlock(&ctrl->mbox_lock); 546 547 wait_event_interruptible(phba->ctrl.mcc_wait[tag], 548 phba->ctrl.mcc_numtag[tag]); 549 550 extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; 551 status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; 552 if (status || extd_status) { 553 SE_DEBUG(DBG_LVL_1, 554 "mgmt_exec_nonemb_cmd Failed status = %d" 555 "extd_status = %d\n", status, extd_status); 556 rc = -EIO; 557 goto free_tag; 558 } 559 560 if (resp_buf) 561 memcpy(resp_buf, nonemb_cmd->va, resp_buf_len); 562 563 free_tag: 564 free_mcc_tag(&phba->ctrl, tag); 565 free_cmd: 566 pci_free_consistent(ctrl->pdev, nonemb_cmd->size, 567 nonemb_cmd->va, nonemb_cmd->dma); 568 return rc; 569 } 570 571 static int mgmt_alloc_cmd_data(struct beiscsi_hba *phba, struct be_dma_mem *cmd, 572 int iscsi_cmd, int size) 573 { 574 cmd->va = pci_alloc_consistent(phba->ctrl.pdev, size, &cmd->dma); 575 if (!cmd->va) { 576 SE_DEBUG(DBG_LVL_1, "Failed to allocate memory for if info\n"); 577 return -ENOMEM; 578 } 579 memset(cmd->va, 0, size); 580 cmd->size = size; 581 be_cmd_hdr_prepare(cmd->va, CMD_SUBSYSTEM_ISCSI, iscsi_cmd, size); 582 return 0; 583 } 584 585 static int 586 mgmt_static_ip_modify(struct beiscsi_hba *phba, 587 struct be_cmd_get_if_info_resp *if_info, 588 struct iscsi_iface_param_info *ip_param, 589 struct iscsi_iface_param_info *subnet_param, 590 uint32_t ip_action) 591 { 592 struct be_cmd_set_ip_addr_req *req; 593 struct be_dma_mem nonemb_cmd; 594 uint32_t ip_type; 595 int rc; 596 597 rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, 598 OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR, 599 sizeof(*req)); 600 if (rc) 601 return rc; 602 603 ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? 604 BE2_IPV6 : BE2_IPV4 ; 605 606 req = nonemb_cmd.va; 607 req->ip_params.record_entry_count = 1; 608 req->ip_params.ip_record.action = ip_action; 609 req->ip_params.ip_record.interface_hndl = 610 phba->interface_handle; 611 req->ip_params.ip_record.ip_addr.size_of_structure = 612 sizeof(struct be_ip_addr_subnet_format); 613 req->ip_params.ip_record.ip_addr.ip_type = ip_type; 614 615 if (ip_action == IP_ACTION_ADD) { 616 memcpy(req->ip_params.ip_record.ip_addr.addr, ip_param->value, 617 ip_param->len); 618 619 if (subnet_param) 620 memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, 621 subnet_param->value, subnet_param->len); 622 } else { 623 memcpy(req->ip_params.ip_record.ip_addr.addr, 624 if_info->ip_addr.addr, ip_param->len); 625 626 memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, 627 if_info->ip_addr.subnet_mask, ip_param->len); 628 } 629 630 rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); 631 if (rc < 0) 632 shost_printk(KERN_WARNING, phba->shost, 633 "Failed to Modify existing IP Address\n"); 634 return rc; 635 } 636 637 static int mgmt_modify_gateway(struct beiscsi_hba *phba, uint8_t *gt_addr, 638 uint32_t gtway_action, uint32_t param_len) 639 { 640 struct be_cmd_set_def_gateway_req *req; 641 struct be_dma_mem nonemb_cmd; 642 int rt_val; 643 644 645 rt_val = mgmt_alloc_cmd_data(phba, &nonemb_cmd, 646 OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY, 647 sizeof(*req)); 648 if (rt_val) 649 return rt_val; 650 651 req = nonemb_cmd.va; 652 req->action = gtway_action; 653 req->ip_addr.ip_type = BE2_IPV4; 654 655 memcpy(req->ip_addr.addr, gt_addr, param_len); 656 657 return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); 658 } 659 660 int mgmt_set_ip(struct beiscsi_hba *phba, 661 struct iscsi_iface_param_info *ip_param, 662 struct iscsi_iface_param_info *subnet_param, 663 uint32_t boot_proto) 664 { 665 struct be_cmd_get_def_gateway_resp gtway_addr_set; 666 struct be_cmd_get_if_info_resp if_info; 667 struct be_cmd_set_dhcp_req *dhcpreq; 668 struct be_cmd_rel_dhcp_req *reldhcp; 669 struct be_dma_mem nonemb_cmd; 670 uint8_t *gtway_addr; 671 uint32_t ip_type; 672 int rc; 673 674 if (mgmt_get_all_if_id(phba)) 675 return -EIO; 676 677 memset(&if_info, 0, sizeof(if_info)); 678 ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? 679 BE2_IPV6 : BE2_IPV4 ; 680 681 rc = mgmt_get_if_info(phba, ip_type, &if_info); 682 if (rc) 683 return rc; 684 685 if (boot_proto == ISCSI_BOOTPROTO_DHCP) { 686 if (if_info.dhcp_state) { 687 shost_printk(KERN_WARNING, phba->shost, 688 "DHCP Already Enabled\n"); 689 return 0; 690 } 691 /* The ip_param->len is 1 in DHCP case. Setting 692 proper IP len as this it is used while 693 freeing the Static IP. 694 */ 695 ip_param->len = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? 696 IP_V6_LEN : IP_V4_LEN; 697 698 } else { 699 if (if_info.dhcp_state) { 700 701 memset(&if_info, 0, sizeof(if_info)); 702 rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, 703 OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR, 704 sizeof(*reldhcp)); 705 706 if (rc) 707 return rc; 708 709 reldhcp = nonemb_cmd.va; 710 reldhcp->interface_hndl = phba->interface_handle; 711 reldhcp->ip_type = ip_type; 712 713 rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); 714 if (rc < 0) { 715 shost_printk(KERN_WARNING, phba->shost, 716 "Failed to Delete existing dhcp\n"); 717 return rc; 718 } 719 } 720 } 721 722 /* Delete the Static IP Set */ 723 if (if_info.ip_addr.addr[0]) { 724 rc = mgmt_static_ip_modify(phba, &if_info, ip_param, NULL, 725 IP_ACTION_DEL); 726 if (rc) 727 return rc; 728 } 729 730 /* Delete the Gateway settings if mode change is to DHCP */ 731 if (boot_proto == ISCSI_BOOTPROTO_DHCP) { 732 memset(>way_addr_set, 0, sizeof(gtway_addr_set)); 733 rc = mgmt_get_gateway(phba, BE2_IPV4, >way_addr_set); 734 if (rc) { 735 shost_printk(KERN_WARNING, phba->shost, 736 "Failed to Get Gateway Addr\n"); 737 return rc; 738 } 739 740 if (gtway_addr_set.ip_addr.addr[0]) { 741 gtway_addr = (uint8_t *)>way_addr_set.ip_addr.addr; 742 rc = mgmt_modify_gateway(phba, gtway_addr, 743 IP_ACTION_DEL, IP_V4_LEN); 744 745 if (rc) { 746 shost_printk(KERN_WARNING, phba->shost, 747 "Failed to clear Gateway Addr Set\n"); 748 return rc; 749 } 750 } 751 } 752 753 /* Set Adapter to DHCP/Static Mode */ 754 if (boot_proto == ISCSI_BOOTPROTO_DHCP) { 755 rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, 756 OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR, 757 sizeof(*dhcpreq)); 758 if (rc) 759 return rc; 760 761 dhcpreq = nonemb_cmd.va; 762 dhcpreq->flags = BLOCKING; 763 dhcpreq->retry_count = 1; 764 dhcpreq->interface_hndl = phba->interface_handle; 765 dhcpreq->ip_type = BE2_DHCP_V4; 766 767 return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); 768 } else { 769 return mgmt_static_ip_modify(phba, &if_info, ip_param, 770 subnet_param, IP_ACTION_ADD); 771 } 772 773 return rc; 774 } 775 776 int mgmt_set_gateway(struct beiscsi_hba *phba, 777 struct iscsi_iface_param_info *gateway_param) 778 { 779 struct be_cmd_get_def_gateway_resp gtway_addr_set; 780 uint8_t *gtway_addr; 781 int rt_val; 782 783 memset(>way_addr_set, 0, sizeof(gtway_addr_set)); 784 rt_val = mgmt_get_gateway(phba, BE2_IPV4, >way_addr_set); 785 if (rt_val) { 786 shost_printk(KERN_WARNING, phba->shost, 787 "Failed to Get Gateway Addr\n"); 788 return rt_val; 789 } 790 791 if (gtway_addr_set.ip_addr.addr[0]) { 792 gtway_addr = (uint8_t *)>way_addr_set.ip_addr.addr; 793 rt_val = mgmt_modify_gateway(phba, gtway_addr, IP_ACTION_DEL, 794 gateway_param->len); 795 if (rt_val) { 796 shost_printk(KERN_WARNING, phba->shost, 797 "Failed to clear Gateway Addr Set\n"); 798 return rt_val; 799 } 800 } 801 802 gtway_addr = (uint8_t *)&gateway_param->value; 803 rt_val = mgmt_modify_gateway(phba, gtway_addr, IP_ACTION_ADD, 804 gateway_param->len); 805 806 if (rt_val) 807 shost_printk(KERN_WARNING, phba->shost, 808 "Failed to Set Gateway Addr\n"); 809 810 return rt_val; 811 } 812 813 int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type, 814 struct be_cmd_get_def_gateway_resp *gateway) 815 { 816 struct be_cmd_get_def_gateway_req *req; 817 struct be_dma_mem nonemb_cmd; 818 int rc; 819 820 rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, 821 OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY, 822 sizeof(*gateway)); 823 if (rc) 824 return rc; 825 826 req = nonemb_cmd.va; 827 req->ip_type = ip_type; 828 829 return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, gateway, 830 sizeof(*gateway)); 831 } 832 833 int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, 834 struct be_cmd_get_if_info_resp *if_info) 835 { 836 struct be_cmd_get_if_info_req *req; 837 struct be_dma_mem nonemb_cmd; 838 int rc; 839 840 if (mgmt_get_all_if_id(phba)) 841 return -EIO; 842 843 rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, 844 OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO, 845 sizeof(*if_info)); 846 if (rc) 847 return rc; 848 849 req = nonemb_cmd.va; 850 req->interface_hndl = phba->interface_handle; 851 req->ip_type = ip_type; 852 853 return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, if_info, 854 sizeof(*if_info)); 855 } 856 857 int mgmt_get_nic_conf(struct beiscsi_hba *phba, 858 struct be_cmd_get_nic_conf_resp *nic) 859 { 860 struct be_dma_mem nonemb_cmd; 861 int rc; 862 863 rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, 864 OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG, 865 sizeof(*nic)); 866 if (rc) 867 return rc; 868 869 return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, nic, sizeof(*nic)); 870 } 871 872 873 874 unsigned int be_cmd_get_initname(struct beiscsi_hba *phba) 875 { 876 unsigned int tag = 0; 877 struct be_mcc_wrb *wrb; 878 struct be_cmd_hba_name *req; 879 struct be_ctrl_info *ctrl = &phba->ctrl; 880 881 spin_lock(&ctrl->mbox_lock); 882 tag = alloc_mcc_tag(phba); 883 if (!tag) { 884 spin_unlock(&ctrl->mbox_lock); 885 return tag; 886 } 887 888 wrb = wrb_from_mccq(phba); 889 req = embedded_payload(wrb); 890 wrb->tag0 |= tag; 891 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 892 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, 893 OPCODE_ISCSI_INI_CFG_GET_HBA_NAME, 894 sizeof(*req)); 895 896 be_mcc_notify(phba); 897 spin_unlock(&ctrl->mbox_lock); 898 return tag; 899 } 900 901 unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba) 902 { 903 unsigned int tag = 0; 904 struct be_mcc_wrb *wrb; 905 struct be_cmd_ntwk_link_status_req *req; 906 struct be_ctrl_info *ctrl = &phba->ctrl; 907 908 spin_lock(&ctrl->mbox_lock); 909 tag = alloc_mcc_tag(phba); 910 if (!tag) { 911 spin_unlock(&ctrl->mbox_lock); 912 return tag; 913 } 914 915 wrb = wrb_from_mccq(phba); 916 req = embedded_payload(wrb); 917 wrb->tag0 |= tag; 918 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 919 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 920 OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, 921 sizeof(*req)); 922 923 be_mcc_notify(phba); 924 spin_unlock(&ctrl->mbox_lock); 925 return tag; 926 } 927