be_mgmt.c 11.2 KB
Newer Older
1
/**
2
 * Copyright (C) 2005 - 2010 ServerEngines
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.  The full GNU General
 * Public License is included in this distribution in the file called COPYING.
 *
 * Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
 *
 * Contact Information:
 * linux-drivers@serverengines.com
 *
 * ServerEngines
 * 209 N. Fair Oaks Ave
 * Sunnyvale, CA 94085
 *
 */

#include "be_mgmt.h"
#include "be_iscsi.h"

24
int mgmt_get_fw_config(struct be_ctrl_info *ctrl,
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
				struct beiscsi_hba *phba)
{
	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
	struct be_fw_cfg *req = embedded_payload(wrb);
	int status = 0;

	spin_lock(&ctrl->mbox_lock);
	memset(wrb, 0, sizeof(*wrb));

	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);

	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
			   OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req));
	status = be_mbox_notify(ctrl);
	if (!status) {
		struct be_fw_cfg *pfw_cfg;
		pfw_cfg = req;
		phba->fw_config.phys_port = pfw_cfg->phys_port;
		phba->fw_config.iscsi_icd_start =
					pfw_cfg->ulp[0].icd_base;
		phba->fw_config.iscsi_icd_count =
					pfw_cfg->ulp[0].icd_count;
		phba->fw_config.iscsi_cid_start =
					pfw_cfg->ulp[0].sq_base;
		phba->fw_config.iscsi_cid_count =
					pfw_cfg->ulp[0].sq_count;
51
		if (phba->fw_config.iscsi_cid_count > (BE2_MAX_SESSIONS / 2)) {
52 53 54 55 56 57
			SE_DEBUG(DBG_LVL_8,
				"FW reported MAX CXNS as %d \t"
				"Max Supported = %d.\n",
				phba->fw_config.iscsi_cid_count,
				BE2_MAX_SESSIONS);
			phba->fw_config.iscsi_cid_count = BE2_MAX_SESSIONS / 2;
58
		}
59 60
	} else {
		shost_printk(KERN_WARNING, phba->shost,
61
			     "Failed in mgmt_get_fw_config\n");
62 63 64 65 66 67
	}

	spin_unlock(&ctrl->mbox_lock);
	return status;
}

68
int mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
69
				      struct beiscsi_hba *phba)
70 71 72 73 74 75 76 77 78 79 80 81 82 83
{
	struct be_dma_mem nonemb_cmd;
	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
	struct be_mgmt_controller_attributes *req;
	struct be_sge *sge = nonembedded_sgl(wrb);
	int status = 0;

	nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev,
				sizeof(struct be_mgmt_controller_attributes),
				&nonemb_cmd.dma);
	if (nonemb_cmd.va == NULL) {
		SE_DEBUG(DBG_LVL_1,
			 "Failed to allocate memory for mgmt_check_supported_fw"
			 "\n");
84
		return -ENOMEM;
85 86 87
	}
	nonemb_cmd.size = sizeof(struct be_mgmt_controller_attributes);
	req = nonemb_cmd.va;
88
	memset(req, 0, sizeof(*req));
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
	spin_lock(&ctrl->mbox_lock);
	memset(wrb, 0, sizeof(*wrb));
	be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
			   OPCODE_COMMON_GET_CNTL_ATTRIBUTES, sizeof(*req));
	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma));
	sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF);
	sge->len = cpu_to_le32(nonemb_cmd.size);
	status = be_mbox_notify(ctrl);
	if (!status) {
		struct be_mgmt_controller_attributes_resp *resp = nonemb_cmd.va;
		SE_DEBUG(DBG_LVL_8, "Firmware version of CMD: %s\n",
			resp->params.hba_attribs.flashrom_version_string);
		SE_DEBUG(DBG_LVL_8, "Firmware version is : %s\n",
			resp->params.hba_attribs.firmware_version_string);
		SE_DEBUG(DBG_LVL_8,
			"Developer Build, not performing version check...\n");
106 107 108 109
		phba->fw_config.iscsi_features =
				resp->params.hba_attribs.iscsi_features;
		SE_DEBUG(DBG_LVL_8, " phba->fw_config.iscsi_features = %d\n",
				      phba->fw_config.iscsi_features);
110 111
	} else
		SE_DEBUG(DBG_LVL_1, " Failed in mgmt_check_supported_fw\n");
112
	spin_unlock(&ctrl->mbox_lock);
113 114 115 116 117 118 119
	if (nonemb_cmd.va)
		pci_free_consistent(ctrl->pdev, nonemb_cmd.size,
				    nonemb_cmd.va, nonemb_cmd.dma);

	return status;
}

120
int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute)
121 122
{
	struct be_ctrl_info *ctrl = &phba->ctrl;
123
	struct be_mcc_wrb *wrb = wrb_from_mccq(phba);
124 125 126 127 128 129 130 131 132 133 134 135 136 137
	struct iscsi_cleanup_req *req = embedded_payload(wrb);
	int status = 0;

	spin_lock(&ctrl->mbox_lock);
	memset(wrb, 0, sizeof(*wrb));

	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
			   OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req));

	req->chute = chute;
	req->hdr_ring_id = 0;
	req->data_ring_id = 0;

138
	status =  be_mcc_notify_wait(phba);
139 140 141 142 143 144 145
	if (status)
		shost_printk(KERN_WARNING, phba->shost,
			     " mgmt_epfw_cleanup , FAILED\n");
	spin_unlock(&ctrl->mbox_lock);
	return status;
}

146
unsigned int  mgmt_invalidate_icds(struct beiscsi_hba *phba,
147 148
				struct invalidate_command_table *inv_tbl,
				unsigned int num_invalidate, unsigned int cid)
149 150 151
{
	struct be_dma_mem nonemb_cmd;
	struct be_ctrl_info *ctrl = &phba->ctrl;
152 153
	struct be_mcc_wrb *wrb;
	struct be_sge *sge;
154
	struct invalidate_commands_params_in *req;
155
	unsigned int i, tag = 0;
156 157 158 159 160 161 162

	spin_lock(&ctrl->mbox_lock);
	tag = alloc_mcc_tag(phba);
	if (!tag) {
		spin_unlock(&ctrl->mbox_lock);
		return tag;
	}
163 164 165 166 167 168

	nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev,
				sizeof(struct invalidate_commands_params_in),
				&nonemb_cmd.dma);
	if (nonemb_cmd.va == NULL) {
		SE_DEBUG(DBG_LVL_1,
169
			 "Failed to alloc memory for mgmt_invalidate_icds\n");
J
Jiri Slaby 已提交
170
		spin_unlock(&ctrl->mbox_lock);
171
		return 0;
172 173 174
	}
	nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
	req = nonemb_cmd.va;
175
	memset(req, 0, sizeof(*req));
176 177 178
	wrb = wrb_from_mccq(phba);
	sge = nonembedded_sgl(wrb);
	wrb->tag0 |= tag;
179 180 181 182 183 184 185

	be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
			OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS,
			sizeof(*req));
	req->ref_handle = 0;
	req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE;
186 187 188 189 190 191
	for (i = 0; i < num_invalidate; i++) {
		req->table[i].icd = inv_tbl->icd;
		req->table[i].cid = inv_tbl->cid;
		req->icd_count++;
		inv_tbl++;
	}
192 193 194 195
	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma));
	sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF);
	sge->len = cpu_to_le32(nonemb_cmd.size);

196
	be_mcc_notify(phba);
197 198 199 200
	spin_unlock(&ctrl->mbox_lock);
	if (nonemb_cmd.va)
		pci_free_consistent(ctrl->pdev, nonemb_cmd.size,
				    nonemb_cmd.va, nonemb_cmd.dma);
201
	return tag;
202 203
}

204
unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba,
205 206 207 208 209 210
					 struct beiscsi_endpoint *beiscsi_ep,
					 unsigned short cid,
					 unsigned short issue_reset,
					 unsigned short savecfg_flag)
{
	struct be_ctrl_info *ctrl = &phba->ctrl;
211 212 213
	struct be_mcc_wrb *wrb;
	struct iscsi_invalidate_connection_params_in *req;
	unsigned int tag = 0;
214 215

	spin_lock(&ctrl->mbox_lock);
216 217 218 219 220 221 222 223
	tag = alloc_mcc_tag(phba);
	if (!tag) {
		spin_unlock(&ctrl->mbox_lock);
		return tag;
	}
	wrb = wrb_from_mccq(phba);
	wrb->tag0 |= tag;
	req = embedded_payload(wrb);
224 225 226 227 228 229 230 231 232 233 234 235

	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
			   OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION,
			   sizeof(*req));
	req->session_handle = beiscsi_ep->fw_handle;
	req->cid = cid;
	if (issue_reset)
		req->cleanup_type = CMD_ISCSI_CONNECTION_ISSUE_TCP_RST;
	else
		req->cleanup_type = CMD_ISCSI_CONNECTION_INVALIDATE;
	req->save_cfg = savecfg_flag;
236
	be_mcc_notify(phba);
237
	spin_unlock(&ctrl->mbox_lock);
238
	return tag;
239 240
}

241
unsigned int mgmt_upload_connection(struct beiscsi_hba *phba,
242 243 244
				unsigned short cid, unsigned int upload_flag)
{
	struct be_ctrl_info *ctrl = &phba->ctrl;
245 246 247
	struct be_mcc_wrb *wrb;
	struct tcp_upload_params_in *req;
	unsigned int tag = 0;
248 249

	spin_lock(&ctrl->mbox_lock);
250 251 252 253 254 255 256 257
	tag = alloc_mcc_tag(phba);
	if (!tag) {
		spin_unlock(&ctrl->mbox_lock);
		return tag;
	}
	wrb = wrb_from_mccq(phba);
	req = embedded_payload(wrb);
	wrb->tag0 |= tag;
258 259 260 261 262 263

	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
	be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD,
			   OPCODE_COMMON_TCP_UPLOAD, sizeof(*req));
	req->id = (unsigned short)cid;
	req->upload_type = (unsigned char)upload_flag;
264
	be_mcc_notify(phba);
265
	spin_unlock(&ctrl->mbox_lock);
266
	return tag;
267 268 269 270 271 272 273 274 275 276 277
}

int mgmt_open_connection(struct beiscsi_hba *phba,
			 struct sockaddr *dst_addr,
			 struct beiscsi_endpoint *beiscsi_ep)
{
	struct hwi_controller *phwi_ctrlr;
	struct hwi_context_memory *phwi_context;
	struct sockaddr_in *daddr_in = (struct sockaddr_in *)dst_addr;
	struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)dst_addr;
	struct be_ctrl_info *ctrl = &phba->ctrl;
278 279
	struct be_mcc_wrb *wrb;
	struct tcp_connect_and_offload_in *req;
280 281 282 283
	unsigned short def_hdr_id;
	unsigned short def_data_id;
	struct phys_addr template_address = { 0, 0 };
	struct phys_addr *ptemplate_address;
284
	unsigned int tag = 0;
285
	unsigned int i;
286 287 288 289 290 291 292 293 294 295
	unsigned short cid = beiscsi_ep->ep_cid;

	phwi_ctrlr = phba->phwi_ctrlr;
	phwi_context = phwi_ctrlr->phwi_ctxt;
	def_hdr_id = (unsigned short)HWI_GET_DEF_HDRQ_ID(phba);
	def_data_id = (unsigned short)HWI_GET_DEF_BUFQ_ID(phba);

	ptemplate_address = &template_address;
	ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address);
	spin_lock(&ctrl->mbox_lock);
296 297 298 299 300 301 302 303
	tag = alloc_mcc_tag(phba);
	if (!tag) {
		spin_unlock(&ctrl->mbox_lock);
		return tag;
	}
	wrb = wrb_from_mccq(phba);
	req = embedded_payload(wrb);
	wrb->tag0 |= tag;
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336

	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
			   OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD,
			   sizeof(*req));
	if (dst_addr->sa_family == PF_INET) {
		__be32 s_addr = daddr_in->sin_addr.s_addr;
		req->ip_address.ip_type = BE2_IPV4;
		req->ip_address.ip_address[0] = s_addr & 0x000000ff;
		req->ip_address.ip_address[1] = (s_addr & 0x0000ff00) >> 8;
		req->ip_address.ip_address[2] = (s_addr & 0x00ff0000) >> 16;
		req->ip_address.ip_address[3] = (s_addr & 0xff000000) >> 24;
		req->tcp_port = ntohs(daddr_in->sin_port);
		beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr;
		beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port);
		beiscsi_ep->ip_type = BE2_IPV4;
	} else if (dst_addr->sa_family == PF_INET6) {
		req->ip_address.ip_type = BE2_IPV6;
		memcpy(&req->ip_address.ip_address,
		       &daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
		req->tcp_port = ntohs(daddr_in6->sin6_port);
		beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port);
		memcpy(&beiscsi_ep->dst6_addr,
		       &daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
		beiscsi_ep->ip_type = BE2_IPV6;
	} else{
		shost_printk(KERN_ERR, phba->shost, "unknown addr family %d\n",
			     dst_addr->sa_family);
		spin_unlock(&ctrl->mbox_lock);
		return -EINVAL;

	}
	req->cid = cid;
337 338 339 340
	i = phba->nxt_cqid++;
	if (phba->nxt_cqid == phba->num_cpus)
		phba->nxt_cqid = 0;
	req->cq_id = phwi_context->be_cq[i].id;
341
	SE_DEBUG(DBG_LVL_8, "i=%d cq_id=%d\n", i, req->cq_id);
342 343 344 345 346 347
	req->defq_id = def_hdr_id;
	req->hdr_ring_id = def_hdr_id;
	req->data_ring_id = def_data_id;
	req->do_offload = 1;
	req->dataout_template_pa.lo = ptemplate_address->lo;
	req->dataout_template_pa.hi = ptemplate_address->hi;
348
	be_mcc_notify(phba);
349
	spin_unlock(&ctrl->mbox_lock);
350
	return tag;
351
}
352

353
unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba)
354 355
{
	struct be_ctrl_info *ctrl = &phba->ctrl;
356 357 358
	struct be_mcc_wrb *wrb;
	struct be_cmd_req_get_mac_addr *req;
	unsigned int tag = 0;
359 360 361

	SE_DEBUG(DBG_LVL_8, "In be_cmd_get_mac_addr\n");
	spin_lock(&ctrl->mbox_lock);
362 363 364 365 366 367 368 369 370
	tag = alloc_mcc_tag(phba);
	if (!tag) {
		spin_unlock(&ctrl->mbox_lock);
		return tag;
	}

	wrb = wrb_from_mccq(phba);
	req = embedded_payload(wrb);
	wrb->tag0 |= tag;
371 372 373 374 375
	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
			   OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG,
			   sizeof(*req));

376
	be_mcc_notify(phba);
377
	spin_unlock(&ctrl->mbox_lock);
378
	return tag;
379 380
}