]>
Commit | Line | Data |
---|---|---|
6733b39a | 1 | /** |
255fa9a3 | 2 | * Copyright (C) 2005 - 2011 Emulex |
6733b39a JK |
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 | * | |
255fa9a3 | 10 | * Written by: Jayamohan Kallickal (jayamohan.kallickal@emulex.com) |
6733b39a JK |
11 | * |
12 | * Contact Information: | |
255fa9a3 | 13 | * linux-drivers@emulex.com |
6733b39a | 14 | * |
255fa9a3 JK |
15 | * Emulex |
16 | * 3333 Susan Street | |
17 | * Costa Mesa, CA 92626 | |
6733b39a JK |
18 | */ |
19 | ||
ffce3e2e JK |
20 | #include <linux/bsg-lib.h> |
21 | #include <scsi/scsi_transport_iscsi.h> | |
22 | #include <scsi/scsi_bsg_iscsi.h> | |
6733b39a JK |
23 | #include "be_mgmt.h" |
24 | #include "be_iscsi.h" | |
c7acc5b8 | 25 | |
0e43895e | 26 | unsigned int mgmt_get_boot_target(struct beiscsi_hba *phba) |
c7acc5b8 JK |
27 | { |
28 | struct be_ctrl_info *ctrl = &phba->ctrl; | |
29 | struct be_mcc_wrb *wrb; | |
0e43895e | 30 | struct be_cmd_get_boot_target_req *req; |
c7acc5b8 JK |
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, | |
0e43895e | 47 | sizeof(struct be_cmd_get_boot_target_resp)); |
c7acc5b8 JK |
48 | |
49 | be_mcc_notify(phba); | |
50 | spin_unlock(&ctrl->mbox_lock); | |
51 | return tag; | |
52 | } | |
53 | ||
0e43895e MC |
54 | unsigned int mgmt_get_session_info(struct beiscsi_hba *phba, |
55 | u32 boot_session_handle, | |
56 | struct be_dma_mem *nonemb_cmd) | |
c7acc5b8 JK |
57 | { |
58 | struct be_ctrl_info *ctrl = &phba->ctrl; | |
59 | struct be_mcc_wrb *wrb; | |
60 | unsigned int tag = 0; | |
0e43895e MC |
61 | struct be_cmd_get_session_req *req; |
62 | struct be_cmd_get_session_resp *resp; | |
c7acc5b8 JK |
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 | } | |
6733b39a | 95 | |
03a12310 | 96 | int mgmt_get_fw_config(struct be_ctrl_info *ctrl, |
6733b39a JK |
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)); | |
6733b39a JK |
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; | |
7da50879 | 123 | if (phba->fw_config.iscsi_cid_count > (BE2_MAX_SESSIONS / 2)) { |
a3babda5 | 124 | SE_DEBUG(DBG_LVL_8, |
3cbb7a74 | 125 | "FW reported MAX CXNS as %d\t" |
a3babda5 JK |
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; | |
7da50879 | 130 | } |
6733b39a JK |
131 | } else { |
132 | shost_printk(KERN_WARNING, phba->shost, | |
457ff3b7 | 133 | "Failed in mgmt_get_fw_config\n"); |
6733b39a JK |
134 | } |
135 | ||
136 | spin_unlock(&ctrl->mbox_lock); | |
137 | return status; | |
138 | } | |
139 | ||
03a12310 | 140 | int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, |
bfead3b2 | 141 | struct beiscsi_hba *phba) |
6733b39a JK |
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"); | |
d3ad2bb3 | 156 | return -ENOMEM; |
6733b39a JK |
157 | } |
158 | nonemb_cmd.size = sizeof(struct be_mgmt_controller_attributes); | |
159 | req = nonemb_cmd.va; | |
f98c96b0 | 160 | memset(req, 0, sizeof(*req)); |
6733b39a JK |
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); | |
6733b39a JK |
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"); | |
bfead3b2 JK |
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); | |
6733b39a JK |
182 | } else |
183 | SE_DEBUG(DBG_LVL_1, " Failed in mgmt_check_supported_fw\n"); | |
bfead3b2 | 184 | spin_unlock(&ctrl->mbox_lock); |
6733b39a JK |
185 | if (nonemb_cmd.va) |
186 | pci_free_consistent(ctrl->pdev, nonemb_cmd.size, | |
187 | nonemb_cmd.va, nonemb_cmd.dma); | |
188 | ||
6733b39a JK |
189 | return status; |
190 | } | |
191 | ||
ffce3e2e JK |
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 | ||
03a12310 | 258 | int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) |
6733b39a JK |
259 | { |
260 | struct be_ctrl_info *ctrl = &phba->ctrl; | |
bfead3b2 | 261 | struct be_mcc_wrb *wrb = wrb_from_mccq(phba); |
6733b39a JK |
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; | |
069adc7b JK |
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)); | |
6733b39a | 275 | |
bfead3b2 | 276 | status = be_mcc_notify_wait(phba); |
6733b39a JK |
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 | ||
03a12310 | 284 | unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, |
4183122d | 285 | struct invalidate_command_table *inv_tbl, |
3cbb7a74 JK |
286 | unsigned int num_invalidate, unsigned int cid, |
287 | struct be_dma_mem *nonemb_cmd) | |
288 | ||
6733b39a | 289 | { |
6733b39a | 290 | struct be_ctrl_info *ctrl = &phba->ctrl; |
756d29c8 JK |
291 | struct be_mcc_wrb *wrb; |
292 | struct be_sge *sge; | |
6733b39a | 293 | struct invalidate_commands_params_in *req; |
4183122d | 294 | unsigned int i, tag = 0; |
756d29c8 JK |
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 | } | |
6733b39a | 302 | |
3cbb7a74 | 303 | req = nonemb_cmd->va; |
f98c96b0 | 304 | memset(req, 0, sizeof(*req)); |
756d29c8 JK |
305 | wrb = wrb_from_mccq(phba); |
306 | sge = nonembedded_sgl(wrb); | |
307 | wrb->tag0 |= tag; | |
6733b39a JK |
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; | |
4183122d JK |
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 | } | |
3cbb7a74 JK |
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); | |
6733b39a | 324 | |
756d29c8 | 325 | be_mcc_notify(phba); |
6733b39a | 326 | spin_unlock(&ctrl->mbox_lock); |
756d29c8 | 327 | return tag; |
6733b39a JK |
328 | } |
329 | ||
03a12310 | 330 | unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba, |
6733b39a JK |
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; | |
756d29c8 JK |
337 | struct be_mcc_wrb *wrb; |
338 | struct iscsi_invalidate_connection_params_in *req; | |
339 | unsigned int tag = 0; | |
6733b39a JK |
340 | |
341 | spin_lock(&ctrl->mbox_lock); | |
756d29c8 JK |
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); | |
6733b39a JK |
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; | |
756d29c8 | 362 | be_mcc_notify(phba); |
6733b39a | 363 | spin_unlock(&ctrl->mbox_lock); |
756d29c8 | 364 | return tag; |
6733b39a JK |
365 | } |
366 | ||
03a12310 | 367 | unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, |
6733b39a JK |
368 | unsigned short cid, unsigned int upload_flag) |
369 | { | |
370 | struct be_ctrl_info *ctrl = &phba->ctrl; | |
756d29c8 JK |
371 | struct be_mcc_wrb *wrb; |
372 | struct tcp_upload_params_in *req; | |
373 | unsigned int tag = 0; | |
6733b39a JK |
374 | |
375 | spin_lock(&ctrl->mbox_lock); | |
756d29c8 JK |
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; | |
6733b39a JK |
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; | |
756d29c8 | 390 | be_mcc_notify(phba); |
6733b39a | 391 | spin_unlock(&ctrl->mbox_lock); |
756d29c8 | 392 | return tag; |
6733b39a JK |
393 | } |
394 | ||
395 | int mgmt_open_connection(struct beiscsi_hba *phba, | |
396 | struct sockaddr *dst_addr, | |
3cbb7a74 JK |
397 | struct beiscsi_endpoint *beiscsi_ep, |
398 | struct be_dma_mem *nonemb_cmd) | |
6733b39a JK |
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; | |
756d29c8 JK |
405 | struct be_mcc_wrb *wrb; |
406 | struct tcp_connect_and_offload_in *req; | |
6733b39a JK |
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; | |
756d29c8 | 411 | unsigned int tag = 0; |
bfead3b2 | 412 | unsigned int i; |
6733b39a | 413 | unsigned short cid = beiscsi_ep->ep_cid; |
3cbb7a74 | 414 | struct be_sge *sge; |
6733b39a JK |
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); | |
756d29c8 JK |
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); | |
3cbb7a74 JK |
430 | memset(wrb, 0, sizeof(*wrb)); |
431 | sge = nonembedded_sgl(wrb); | |
432 | ||
433 | req = nonemb_cmd->va; | |
434 | memset(req, 0, sizeof(*req)); | |
756d29c8 | 435 | wrb->tag0 |= tag; |
6733b39a | 436 | |
b15d05b0 | 437 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); |
6733b39a JK |
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; | |
0e43895e MC |
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; | |
6733b39a JK |
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; | |
0e43895e | 454 | memcpy(&req->ip_address.addr, |
6733b39a JK |
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); | |
5db3f33d | 465 | free_mcc_tag(&phba->ctrl, tag); |
6733b39a JK |
466 | return -EINVAL; |
467 | ||
468 | } | |
469 | req->cid = cid; | |
bfead3b2 JK |
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; | |
457ff3b7 | 474 | SE_DEBUG(DBG_LVL_8, "i=%d cq_id=%d\n", i, req->cq_id); |
6733b39a JK |
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; | |
3cbb7a74 JK |
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); | |
756d29c8 | 484 | be_mcc_notify(phba); |
6733b39a | 485 | spin_unlock(&ctrl->mbox_lock); |
756d29c8 | 486 | return tag; |
6733b39a | 487 | } |
bfead3b2 | 488 | |
0e43895e | 489 | unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba) |
bfead3b2 JK |
490 | { |
491 | struct be_ctrl_info *ctrl = &phba->ctrl; | |
0e43895e MC |
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; | |
bfead3b2 | 527 | |
bfead3b2 | 528 | spin_lock(&ctrl->mbox_lock); |
756d29c8 JK |
529 | tag = alloc_mcc_tag(phba); |
530 | if (!tag) { | |
531 | spin_unlock(&ctrl->mbox_lock); | |
0e43895e MC |
532 | rc = -ENOMEM; |
533 | goto free_cmd; | |
756d29c8 | 534 | } |
0e43895e | 535 | memset(wrb, 0, sizeof(*wrb)); |
756d29c8 | 536 | wrb->tag0 |= tag; |
0e43895e MC |
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); | |
bfead3b2 | 543 | |
756d29c8 | 544 | be_mcc_notify(phba); |
bfead3b2 | 545 | spin_unlock(&ctrl->mbox_lock); |
0e43895e MC |
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 | { | |
b83d543f | 574 | cmd->va = pci_alloc_consistent(phba->ctrl.pdev, size, &cmd->dma); |
0e43895e MC |
575 | if (!cmd->va) { |
576 | SE_DEBUG(DBG_LVL_1, "Failed to allocate memory for if info\n"); | |
577 | return -ENOMEM; | |
578 | } | |
b83d543f | 579 | memset(cmd->va, 0, size); |
0e43895e MC |
580 | cmd->size = size; |
581 | be_cmd_hdr_prepare(cmd->va, CMD_SUBSYSTEM_ISCSI, iscsi_cmd, size); | |
582 | return 0; | |
bfead3b2 JK |
583 | } |
584 | ||
0e43895e MC |
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 | ||
2177199d JSJ |
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 | } | |
c62eef0d JSJ |
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 | } |