1 /** 2 * Copyright (C) 2005 - 2009 ServerEngines 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 (jayamohank@serverengines.com) 11 * 12 * Contact Information: 13 * linux-drivers@serverengines.com 14 * 15 * ServerEngines 16 * 209 N. Fair Oaks Ave 17 * Sunnyvale, CA 94085 18 * 19 */ 20 21 #include "be_mgmt.h" 22 #include "be_iscsi.h" 23 24 unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl, 25 struct beiscsi_hba *phba) 26 { 27 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 28 struct be_fw_cfg *req = embedded_payload(wrb); 29 int status = 0; 30 31 spin_lock(&ctrl->mbox_lock); 32 memset(wrb, 0, sizeof(*wrb)); 33 34 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 35 36 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 37 OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req)); 38 status = be_mbox_notify(ctrl); 39 if (!status) { 40 struct be_fw_cfg *pfw_cfg; 41 pfw_cfg = req; 42 phba->fw_config.phys_port = pfw_cfg->phys_port; 43 phba->fw_config.iscsi_icd_start = 44 pfw_cfg->ulp[0].icd_base; 45 phba->fw_config.iscsi_icd_count = 46 pfw_cfg->ulp[0].icd_count; 47 phba->fw_config.iscsi_cid_start = 48 pfw_cfg->ulp[0].sq_base; 49 phba->fw_config.iscsi_cid_count = 50 pfw_cfg->ulp[0].sq_count; 51 } else { 52 shost_printk(KERN_WARNING, phba->shost, 53 "Failed in mgmt_get_fw_config \n"); 54 } 55 56 spin_unlock(&ctrl->mbox_lock); 57 return status; 58 } 59 60 unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl, 61 struct beiscsi_hba *phba) 62 { 63 struct be_dma_mem nonemb_cmd; 64 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 65 struct be_mgmt_controller_attributes *req; 66 struct be_sge *sge = nonembedded_sgl(wrb); 67 int status = 0; 68 69 nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev, 70 sizeof(struct be_mgmt_controller_attributes), 71 &nonemb_cmd.dma); 72 if (nonemb_cmd.va == NULL) { 73 SE_DEBUG(DBG_LVL_1, 74 "Failed to allocate memory for mgmt_check_supported_fw" 75 "\n"); 76 return -1; 77 } 78 nonemb_cmd.size = sizeof(struct be_mgmt_controller_attributes); 79 req = nonemb_cmd.va; 80 spin_lock(&ctrl->mbox_lock); 81 memset(wrb, 0, sizeof(*wrb)); 82 be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); 83 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 84 OPCODE_COMMON_GET_CNTL_ATTRIBUTES, sizeof(*req)); 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 status = be_mbox_notify(ctrl); 89 if (!status) { 90 struct be_mgmt_controller_attributes_resp *resp = nonemb_cmd.va; 91 SE_DEBUG(DBG_LVL_8, "Firmware version of CMD: %s\n", 92 resp->params.hba_attribs.flashrom_version_string); 93 SE_DEBUG(DBG_LVL_8, "Firmware version is : %s\n", 94 resp->params.hba_attribs.firmware_version_string); 95 SE_DEBUG(DBG_LVL_8, 96 "Developer Build, not performing version check...\n"); 97 phba->fw_config.iscsi_features = 98 resp->params.hba_attribs.iscsi_features; 99 SE_DEBUG(DBG_LVL_8, " phba->fw_config.iscsi_features = %d\n", 100 phba->fw_config.iscsi_features); 101 } else 102 SE_DEBUG(DBG_LVL_1, " Failed in mgmt_check_supported_fw\n"); 103 spin_unlock(&ctrl->mbox_lock); 104 if (nonemb_cmd.va) 105 pci_free_consistent(ctrl->pdev, nonemb_cmd.size, 106 nonemb_cmd.va, nonemb_cmd.dma); 107 108 return status; 109 } 110 111 112 unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) 113 { 114 struct be_ctrl_info *ctrl = &phba->ctrl; 115 struct be_mcc_wrb *wrb = wrb_from_mccq(phba); 116 struct iscsi_cleanup_req *req = embedded_payload(wrb); 117 int status = 0; 118 119 spin_lock(&ctrl->mbox_lock); 120 memset(wrb, 0, sizeof(*wrb)); 121 122 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 123 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 124 OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req)); 125 126 req->chute = chute; 127 req->hdr_ring_id = 0; 128 req->data_ring_id = 0; 129 130 status = be_mcc_notify_wait(phba); 131 if (status) 132 shost_printk(KERN_WARNING, phba->shost, 133 " mgmt_epfw_cleanup , FAILED\n"); 134 spin_unlock(&ctrl->mbox_lock); 135 return status; 136 } 137 138 unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, 139 unsigned int icd, unsigned int cid) 140 { 141 struct be_dma_mem nonemb_cmd; 142 struct be_ctrl_info *ctrl = &phba->ctrl; 143 struct be_mcc_wrb *wrb = wrb_from_mccq(phba); 144 struct be_sge *sge = nonembedded_sgl(wrb); 145 struct invalidate_commands_params_in *req; 146 int status = 0; 147 148 nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev, 149 sizeof(struct invalidate_commands_params_in), 150 &nonemb_cmd.dma); 151 if (nonemb_cmd.va == NULL) { 152 SE_DEBUG(DBG_LVL_1, 153 "Failed to allocate memory for" 154 "mgmt_invalidate_icds \n"); 155 return -1; 156 } 157 nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); 158 req = nonemb_cmd.va; 159 spin_lock(&ctrl->mbox_lock); 160 memset(wrb, 0, sizeof(*wrb)); 161 162 be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); 163 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 164 OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS, 165 sizeof(*req)); 166 req->ref_handle = 0; 167 req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE; 168 req->icd_count = 0; 169 req->table[req->icd_count].icd = icd; 170 req->table[req->icd_count].cid = cid; 171 sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); 172 sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); 173 sge->len = cpu_to_le32(nonemb_cmd.size); 174 175 status = be_mcc_notify_wait(phba); 176 if (status) 177 SE_DEBUG(DBG_LVL_1, "ICDS Invalidation Failed\n"); 178 spin_unlock(&ctrl->mbox_lock); 179 if (nonemb_cmd.va) 180 pci_free_consistent(ctrl->pdev, nonemb_cmd.size, 181 nonemb_cmd.va, nonemb_cmd.dma); 182 return status; 183 } 184 185 unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba, 186 struct beiscsi_endpoint *beiscsi_ep, 187 unsigned short cid, 188 unsigned short issue_reset, 189 unsigned short savecfg_flag) 190 { 191 struct be_ctrl_info *ctrl = &phba->ctrl; 192 struct be_mcc_wrb *wrb = wrb_from_mccq(phba); 193 struct iscsi_invalidate_connection_params_in *req = 194 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_INI, 202 OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION, 203 sizeof(*req)); 204 req->session_handle = beiscsi_ep->fw_handle; 205 req->cid = cid; 206 if (issue_reset) 207 req->cleanup_type = CMD_ISCSI_CONNECTION_ISSUE_TCP_RST; 208 else 209 req->cleanup_type = CMD_ISCSI_CONNECTION_INVALIDATE; 210 req->save_cfg = savecfg_flag; 211 status = be_mcc_notify_wait(phba); 212 if (status) 213 SE_DEBUG(DBG_LVL_1, "Invalidation Failed\n"); 214 215 spin_unlock(&ctrl->mbox_lock); 216 return status; 217 } 218 219 unsigned char mgmt_upload_connection(struct beiscsi_hba *phba, 220 unsigned short cid, unsigned int upload_flag) 221 { 222 struct be_ctrl_info *ctrl = &phba->ctrl; 223 struct be_mcc_wrb *wrb = wrb_from_mccq(phba); 224 struct tcp_upload_params_in *req = embedded_payload(wrb); 225 int status = 0; 226 227 spin_lock(&ctrl->mbox_lock); 228 memset(wrb, 0, sizeof(*wrb)); 229 230 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 231 be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD, 232 OPCODE_COMMON_TCP_UPLOAD, sizeof(*req)); 233 req->id = (unsigned short)cid; 234 req->upload_type = (unsigned char)upload_flag; 235 status = be_mcc_notify_wait(phba); 236 if (status) 237 SE_DEBUG(DBG_LVL_1, "mgmt_upload_connection Failed\n"); 238 spin_unlock(&ctrl->mbox_lock); 239 return status; 240 } 241 242 int mgmt_open_connection(struct beiscsi_hba *phba, 243 struct sockaddr *dst_addr, 244 struct beiscsi_endpoint *beiscsi_ep) 245 { 246 struct hwi_controller *phwi_ctrlr; 247 struct hwi_context_memory *phwi_context; 248 struct sockaddr_in *daddr_in = (struct sockaddr_in *)dst_addr; 249 struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)dst_addr; 250 struct be_ctrl_info *ctrl = &phba->ctrl; 251 struct be_mcc_wrb *wrb = wrb_from_mccq(phba); 252 struct tcp_connect_and_offload_in *req = embedded_payload(wrb); 253 unsigned short def_hdr_id; 254 unsigned short def_data_id; 255 struct phys_addr template_address = { 0, 0 }; 256 struct phys_addr *ptemplate_address; 257 int status = 0; 258 unsigned int i; 259 unsigned short cid = beiscsi_ep->ep_cid; 260 261 phwi_ctrlr = phba->phwi_ctrlr; 262 phwi_context = phwi_ctrlr->phwi_ctxt; 263 def_hdr_id = (unsigned short)HWI_GET_DEF_HDRQ_ID(phba); 264 def_data_id = (unsigned short)HWI_GET_DEF_BUFQ_ID(phba); 265 266 ptemplate_address = &template_address; 267 ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address); 268 spin_lock(&ctrl->mbox_lock); 269 memset(wrb, 0, sizeof(*wrb)); 270 271 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 272 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 273 OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD, 274 sizeof(*req)); 275 if (dst_addr->sa_family == PF_INET) { 276 __be32 s_addr = daddr_in->sin_addr.s_addr; 277 req->ip_address.ip_type = BE2_IPV4; 278 req->ip_address.ip_address[0] = s_addr & 0x000000ff; 279 req->ip_address.ip_address[1] = (s_addr & 0x0000ff00) >> 8; 280 req->ip_address.ip_address[2] = (s_addr & 0x00ff0000) >> 16; 281 req->ip_address.ip_address[3] = (s_addr & 0xff000000) >> 24; 282 req->tcp_port = ntohs(daddr_in->sin_port); 283 beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr; 284 beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port); 285 beiscsi_ep->ip_type = BE2_IPV4; 286 } else if (dst_addr->sa_family == PF_INET6) { 287 req->ip_address.ip_type = BE2_IPV6; 288 memcpy(&req->ip_address.ip_address, 289 &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); 290 req->tcp_port = ntohs(daddr_in6->sin6_port); 291 beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port); 292 memcpy(&beiscsi_ep->dst6_addr, 293 &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); 294 beiscsi_ep->ip_type = BE2_IPV6; 295 } else{ 296 shost_printk(KERN_ERR, phba->shost, "unknown addr family %d\n", 297 dst_addr->sa_family); 298 spin_unlock(&ctrl->mbox_lock); 299 return -EINVAL; 300 301 } 302 req->cid = cid; 303 i = phba->nxt_cqid++; 304 if (phba->nxt_cqid == phba->num_cpus) 305 phba->nxt_cqid = 0; 306 req->cq_id = phwi_context->be_cq[i].id; 307 SE_DEBUG(DBG_LVL_8, "i=%d cq_id=%d \n", i, req->cq_id); 308 req->defq_id = def_hdr_id; 309 req->hdr_ring_id = def_hdr_id; 310 req->data_ring_id = def_data_id; 311 req->do_offload = 1; 312 req->dataout_template_pa.lo = ptemplate_address->lo; 313 req->dataout_template_pa.hi = ptemplate_address->hi; 314 status = be_mcc_notify_wait(phba); 315 if (!status) { 316 struct iscsi_endpoint *ep; 317 struct tcp_connect_and_offload_out *ptcpcnct_out = 318 embedded_payload(wrb); 319 320 ep = phba->ep_array[ptcpcnct_out->cid]; 321 beiscsi_ep = ep->dd_data; 322 beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle; 323 beiscsi_ep->cid_vld = 1; 324 SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n"); 325 } else 326 SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed\n"); 327 spin_unlock(&ctrl->mbox_lock); 328 return status; 329 } 330 331 int be_cmd_get_mac_addr(struct beiscsi_hba *phba, u8 *mac_addr) 332 { 333 struct be_ctrl_info *ctrl = &phba->ctrl; 334 struct be_mcc_wrb *wrb = wrb_from_mccq(phba); 335 struct be_cmd_req_get_mac_addr *req = embedded_payload(wrb); 336 int status; 337 338 SE_DEBUG(DBG_LVL_8, "In be_cmd_get_mac_addr\n"); 339 spin_lock(&ctrl->mbox_lock); 340 memset(wrb, 0, sizeof(*wrb)); 341 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 342 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 343 OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG, 344 sizeof(*req)); 345 346 status = be_mcc_notify_wait(phba); 347 if (!status) { 348 struct be_cmd_resp_get_mac_addr *resp = embedded_payload(wrb); 349 350 memcpy(mac_addr, resp->mac_address, ETH_ALEN); 351 } 352 353 spin_unlock(&ctrl->mbox_lock); 354 return status; 355 } 356 357