]>
Commit | Line | Data |
---|---|---|
6733b39a | 1 | /** |
60f36e04 | 2 | * Copyright (C) 2005 - 2016 Broadcom |
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 | * | |
60f36e04 | 10 | * Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com) |
6733b39a JK |
11 | * |
12 | * Contact Information: | |
60f36e04 | 13 | * linux-drivers@broadcom.com |
6733b39a | 14 | * |
c4f39bda | 15 | * Emulex |
255fa9a3 JK |
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" | |
7a158003 JSJ |
25 | #include "be_main.h" |
26 | ||
10bcd47d JB |
27 | int beiscsi_modify_eq_delay(struct beiscsi_hba *phba, |
28 | struct be_set_eqd *set_eqd, | |
29 | int num) | |
73af08e1 JK |
30 | { |
31 | struct be_ctrl_info *ctrl = &phba->ctrl; | |
32 | struct be_mcc_wrb *wrb; | |
33 | struct be_cmd_req_modify_eq_delay *req; | |
090e2184 | 34 | unsigned int tag; |
73af08e1 JK |
35 | int i; |
36 | ||
c03a50f7 | 37 | mutex_lock(&ctrl->mbox_lock); |
090e2184 JB |
38 | wrb = alloc_mcc_wrb(phba, &tag); |
39 | if (!wrb) { | |
c03a50f7 | 40 | mutex_unlock(&ctrl->mbox_lock); |
090e2184 | 41 | return 0; |
73af08e1 JK |
42 | } |
43 | ||
73af08e1 | 44 | req = embedded_payload(wrb); |
73af08e1 JK |
45 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
46 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | |
10bcd47d | 47 | OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req)); |
73af08e1 JK |
48 | |
49 | req->num_eq = cpu_to_le32(num); | |
50 | for (i = 0; i < num; i++) { | |
51 | req->delay[i].eq_id = cpu_to_le32(set_eqd[i].eq_id); | |
52 | req->delay[i].phase = 0; | |
53 | req->delay[i].delay_multiplier = | |
54 | cpu_to_le32(set_eqd[i].delay_multiplier); | |
55 | } | |
56 | ||
10bcd47d JB |
57 | /* ignore the completion of this mbox command */ |
58 | set_bit(MCC_TAG_STATE_IGNORE, &ctrl->ptag_state[tag].tag_state); | |
cdde6682 | 59 | be_mcc_notify(phba, tag); |
c03a50f7 | 60 | mutex_unlock(&ctrl->mbox_lock); |
73af08e1 JK |
61 | return tag; |
62 | } | |
63 | ||
ffce3e2e JK |
64 | unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, |
65 | struct beiscsi_hba *phba, | |
66 | struct bsg_job *job, | |
67 | struct be_dma_mem *nonemb_cmd) | |
68 | { | |
daa8dc08 JK |
69 | struct be_mcc_wrb *wrb; |
70 | struct be_sge *mcc_sge; | |
ffce3e2e JK |
71 | unsigned int tag = 0; |
72 | struct iscsi_bsg_request *bsg_req = job->request; | |
73 | struct be_bsg_vendor_cmd *req = nonemb_cmd->va; | |
74 | unsigned short region, sector_size, sector, offset; | |
75 | ||
76 | nonemb_cmd->size = job->request_payload.payload_len; | |
77 | memset(nonemb_cmd->va, 0, nonemb_cmd->size); | |
ffce3e2e JK |
78 | region = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; |
79 | sector_size = bsg_req->rqst_data.h_vendor.vendor_cmd[2]; | |
80 | sector = bsg_req->rqst_data.h_vendor.vendor_cmd[3]; | |
81 | offset = bsg_req->rqst_data.h_vendor.vendor_cmd[4]; | |
82 | req->region = region; | |
83 | req->sector = sector; | |
84 | req->offset = offset; | |
ffce3e2e | 85 | |
c03a50f7 JB |
86 | if (mutex_lock_interruptible(&ctrl->mbox_lock)) |
87 | return 0; | |
ffce3e2e JK |
88 | switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) { |
89 | case BEISCSI_WRITE_FLASH: | |
90 | offset = sector * sector_size + offset; | |
91 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | |
92 | OPCODE_COMMON_WRITE_FLASH, sizeof(*req)); | |
93 | sg_copy_to_buffer(job->request_payload.sg_list, | |
94 | job->request_payload.sg_cnt, | |
95 | nonemb_cmd->va + offset, job->request_len); | |
96 | break; | |
97 | case BEISCSI_READ_FLASH: | |
98 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | |
99 | OPCODE_COMMON_READ_FLASH, sizeof(*req)); | |
100 | break; | |
101 | default: | |
99bc5d55 JSJ |
102 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, |
103 | "BG_%d : Unsupported cmd = 0x%x\n\n", | |
104 | bsg_req->rqst_data.h_vendor.vendor_cmd[0]); | |
105 | ||
c03a50f7 | 106 | mutex_unlock(&ctrl->mbox_lock); |
c5bf8889 | 107 | return -EPERM; |
ffce3e2e JK |
108 | } |
109 | ||
090e2184 JB |
110 | wrb = alloc_mcc_wrb(phba, &tag); |
111 | if (!wrb) { | |
c03a50f7 | 112 | mutex_unlock(&ctrl->mbox_lock); |
090e2184 | 113 | return 0; |
ffce3e2e JK |
114 | } |
115 | ||
daa8dc08 | 116 | mcc_sge = nonembedded_sgl(wrb); |
ffce3e2e JK |
117 | be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, |
118 | job->request_payload.sg_cnt); | |
119 | mcc_sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); | |
120 | mcc_sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); | |
121 | mcc_sge->len = cpu_to_le32(nonemb_cmd->size); | |
ffce3e2e | 122 | |
cdde6682 | 123 | be_mcc_notify(phba, tag); |
ffce3e2e | 124 | |
c03a50f7 | 125 | mutex_unlock(&ctrl->mbox_lock); |
ffce3e2e JK |
126 | return tag; |
127 | } | |
128 | ||
03a12310 | 129 | unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba, |
6733b39a JK |
130 | struct beiscsi_endpoint *beiscsi_ep, |
131 | unsigned short cid, | |
132 | unsigned short issue_reset, | |
133 | unsigned short savecfg_flag) | |
134 | { | |
135 | struct be_ctrl_info *ctrl = &phba->ctrl; | |
756d29c8 JK |
136 | struct be_mcc_wrb *wrb; |
137 | struct iscsi_invalidate_connection_params_in *req; | |
138 | unsigned int tag = 0; | |
6733b39a | 139 | |
c03a50f7 | 140 | mutex_lock(&ctrl->mbox_lock); |
090e2184 JB |
141 | wrb = alloc_mcc_wrb(phba, &tag); |
142 | if (!wrb) { | |
c03a50f7 | 143 | mutex_unlock(&ctrl->mbox_lock); |
090e2184 | 144 | return 0; |
756d29c8 | 145 | } |
6733b39a | 146 | |
090e2184 | 147 | req = embedded_payload(wrb); |
6733b39a JK |
148 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
149 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | |
150 | OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION, | |
151 | sizeof(*req)); | |
152 | req->session_handle = beiscsi_ep->fw_handle; | |
153 | req->cid = cid; | |
154 | if (issue_reset) | |
155 | req->cleanup_type = CMD_ISCSI_CONNECTION_ISSUE_TCP_RST; | |
156 | else | |
157 | req->cleanup_type = CMD_ISCSI_CONNECTION_INVALIDATE; | |
158 | req->save_cfg = savecfg_flag; | |
cdde6682 | 159 | be_mcc_notify(phba, tag); |
c03a50f7 | 160 | mutex_unlock(&ctrl->mbox_lock); |
756d29c8 | 161 | return tag; |
6733b39a JK |
162 | } |
163 | ||
03a12310 | 164 | unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, |
6733b39a JK |
165 | unsigned short cid, unsigned int upload_flag) |
166 | { | |
167 | struct be_ctrl_info *ctrl = &phba->ctrl; | |
756d29c8 JK |
168 | struct be_mcc_wrb *wrb; |
169 | struct tcp_upload_params_in *req; | |
090e2184 | 170 | unsigned int tag; |
6733b39a | 171 | |
c03a50f7 | 172 | mutex_lock(&ctrl->mbox_lock); |
090e2184 JB |
173 | wrb = alloc_mcc_wrb(phba, &tag); |
174 | if (!wrb) { | |
c03a50f7 | 175 | mutex_unlock(&ctrl->mbox_lock); |
090e2184 | 176 | return 0; |
756d29c8 | 177 | } |
6733b39a | 178 | |
090e2184 | 179 | req = embedded_payload(wrb); |
6733b39a JK |
180 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
181 | be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD, | |
182 | OPCODE_COMMON_TCP_UPLOAD, sizeof(*req)); | |
183 | req->id = (unsigned short)cid; | |
184 | req->upload_type = (unsigned char)upload_flag; | |
cdde6682 | 185 | be_mcc_notify(phba, tag); |
c03a50f7 | 186 | mutex_unlock(&ctrl->mbox_lock); |
756d29c8 | 187 | return tag; |
6733b39a JK |
188 | } |
189 | ||
1e4be6ff JK |
190 | /** |
191 | * mgmt_open_connection()- Establish a TCP CXN | |
192 | * @dst_addr: Destination Address | |
193 | * @beiscsi_ep: ptr to device endpoint struct | |
194 | * @nonemb_cmd: ptr to memory allocated for command | |
195 | * | |
196 | * return | |
197 | * Success: Tag number of the MBX Command issued | |
198 | * Failure: Error code | |
199 | **/ | |
6733b39a JK |
200 | int mgmt_open_connection(struct beiscsi_hba *phba, |
201 | struct sockaddr *dst_addr, | |
3cbb7a74 JK |
202 | struct beiscsi_endpoint *beiscsi_ep, |
203 | struct be_dma_mem *nonemb_cmd) | |
6733b39a JK |
204 | { |
205 | struct hwi_controller *phwi_ctrlr; | |
206 | struct hwi_context_memory *phwi_context; | |
207 | struct sockaddr_in *daddr_in = (struct sockaddr_in *)dst_addr; | |
208 | struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)dst_addr; | |
209 | struct be_ctrl_info *ctrl = &phba->ctrl; | |
756d29c8 | 210 | struct be_mcc_wrb *wrb; |
b3c202dc | 211 | struct tcp_connect_and_offload_in_v1 *req; |
6733b39a JK |
212 | unsigned short def_hdr_id; |
213 | unsigned short def_data_id; | |
214 | struct phys_addr template_address = { 0, 0 }; | |
215 | struct phys_addr *ptemplate_address; | |
756d29c8 | 216 | unsigned int tag = 0; |
1e4be6ff | 217 | unsigned int i, ulp_num; |
6733b39a | 218 | unsigned short cid = beiscsi_ep->ep_cid; |
3cbb7a74 | 219 | struct be_sge *sge; |
6733b39a | 220 | |
291fef26 JB |
221 | if (dst_addr->sa_family != PF_INET && dst_addr->sa_family != PF_INET6) { |
222 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | |
223 | "BG_%d : unknown addr family %d\n", | |
224 | dst_addr->sa_family); | |
225 | return -EINVAL; | |
226 | } | |
227 | ||
6733b39a JK |
228 | phwi_ctrlr = phba->phwi_ctrlr; |
229 | phwi_context = phwi_ctrlr->phwi_ctxt; | |
1e4be6ff JK |
230 | |
231 | ulp_num = phwi_ctrlr->wrb_context[BE_GET_CRI_FROM_CID(cid)].ulp_num; | |
232 | ||
233 | def_hdr_id = (unsigned short)HWI_GET_DEF_HDRQ_ID(phba, ulp_num); | |
234 | def_data_id = (unsigned short)HWI_GET_DEF_BUFQ_ID(phba, ulp_num); | |
6733b39a JK |
235 | |
236 | ptemplate_address = &template_address; | |
237 | ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address); | |
c03a50f7 JB |
238 | if (mutex_lock_interruptible(&ctrl->mbox_lock)) |
239 | return 0; | |
090e2184 JB |
240 | wrb = alloc_mcc_wrb(phba, &tag); |
241 | if (!wrb) { | |
c03a50f7 | 242 | mutex_unlock(&ctrl->mbox_lock); |
090e2184 | 243 | return 0; |
756d29c8 | 244 | } |
3cbb7a74 | 245 | |
090e2184 | 246 | sge = nonembedded_sgl(wrb); |
3cbb7a74 JK |
247 | req = nonemb_cmd->va; |
248 | memset(req, 0, sizeof(*req)); | |
6733b39a | 249 | |
b3c202dc | 250 | be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1); |
6733b39a JK |
251 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, |
252 | OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD, | |
b3c202dc | 253 | nonemb_cmd->size); |
6733b39a JK |
254 | if (dst_addr->sa_family == PF_INET) { |
255 | __be32 s_addr = daddr_in->sin_addr.s_addr; | |
290aa376 | 256 | req->ip_address.ip_type = BEISCSI_IP_TYPE_V4; |
0e43895e MC |
257 | req->ip_address.addr[0] = s_addr & 0x000000ff; |
258 | req->ip_address.addr[1] = (s_addr & 0x0000ff00) >> 8; | |
259 | req->ip_address.addr[2] = (s_addr & 0x00ff0000) >> 16; | |
260 | req->ip_address.addr[3] = (s_addr & 0xff000000) >> 24; | |
6733b39a JK |
261 | req->tcp_port = ntohs(daddr_in->sin_port); |
262 | beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr; | |
263 | beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port); | |
290aa376 | 264 | beiscsi_ep->ip_type = BEISCSI_IP_TYPE_V4; |
291fef26 JB |
265 | } else { |
266 | /* else its PF_INET6 family */ | |
290aa376 | 267 | req->ip_address.ip_type = BEISCSI_IP_TYPE_V6; |
0e43895e | 268 | memcpy(&req->ip_address.addr, |
6733b39a JK |
269 | &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); |
270 | req->tcp_port = ntohs(daddr_in6->sin6_port); | |
271 | beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port); | |
272 | memcpy(&beiscsi_ep->dst6_addr, | |
273 | &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); | |
290aa376 | 274 | beiscsi_ep->ip_type = BEISCSI_IP_TYPE_V6; |
6733b39a JK |
275 | } |
276 | req->cid = cid; | |
bfead3b2 JK |
277 | i = phba->nxt_cqid++; |
278 | if (phba->nxt_cqid == phba->num_cpus) | |
279 | phba->nxt_cqid = 0; | |
280 | req->cq_id = phwi_context->be_cq[i].id; | |
99bc5d55 JSJ |
281 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, |
282 | "BG_%d : i=%d cq_id=%d\n", i, req->cq_id); | |
6733b39a JK |
283 | req->defq_id = def_hdr_id; |
284 | req->hdr_ring_id = def_hdr_id; | |
285 | req->data_ring_id = def_data_id; | |
286 | req->do_offload = 1; | |
287 | req->dataout_template_pa.lo = ptemplate_address->lo; | |
288 | req->dataout_template_pa.hi = ptemplate_address->hi; | |
3cbb7a74 JK |
289 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); |
290 | sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); | |
291 | sge->len = cpu_to_le32(nonemb_cmd->size); | |
b3c202dc JK |
292 | |
293 | if (!is_chip_be2_be3r(phba)) { | |
294 | req->hdr.version = MBX_CMD_VER1; | |
1b7a7ddc | 295 | req->tcp_window_size = 0x8000; |
b3c202dc JK |
296 | req->tcp_window_scale_count = 2; |
297 | } | |
298 | ||
cdde6682 | 299 | be_mcc_notify(phba, tag); |
c03a50f7 | 300 | mutex_unlock(&ctrl->mbox_lock); |
756d29c8 | 301 | return tag; |
6733b39a | 302 | } |
bfead3b2 | 303 | |
e175defe JSJ |
304 | /* |
305 | * mgmt_exec_nonemb_cmd()- Execute Non Embedded MBX Cmd | |
306 | * @phba: Driver priv structure | |
307 | * @nonemb_cmd: Address of the MBX command issued | |
308 | * @resp_buf: Buffer to copy the MBX cmd response | |
309 | * @resp_buf_len: respone lenght to be copied | |
310 | * | |
311 | **/ | |
0e43895e MC |
312 | static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba, |
313 | struct be_dma_mem *nonemb_cmd, void *resp_buf, | |
314 | int resp_buf_len) | |
315 | { | |
316 | struct be_ctrl_info *ctrl = &phba->ctrl; | |
daa8dc08 | 317 | struct be_mcc_wrb *wrb; |
0e43895e MC |
318 | struct be_sge *sge; |
319 | unsigned int tag; | |
320 | int rc = 0; | |
bfead3b2 | 321 | |
c03a50f7 | 322 | mutex_lock(&ctrl->mbox_lock); |
090e2184 JB |
323 | wrb = alloc_mcc_wrb(phba, &tag); |
324 | if (!wrb) { | |
c03a50f7 | 325 | mutex_unlock(&ctrl->mbox_lock); |
0e43895e MC |
326 | rc = -ENOMEM; |
327 | goto free_cmd; | |
756d29c8 | 328 | } |
daa8dc08 | 329 | |
0e43895e | 330 | sge = nonembedded_sgl(wrb); |
0e43895e MC |
331 | be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1); |
332 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); | |
e175defe | 333 | sge->pa_lo = cpu_to_le32(lower_32_bits(nonemb_cmd->dma)); |
0e43895e | 334 | sge->len = cpu_to_le32(nonemb_cmd->size); |
bfead3b2 | 335 | |
cdde6682 | 336 | be_mcc_notify(phba, tag); |
c03a50f7 | 337 | mutex_unlock(&ctrl->mbox_lock); |
0e43895e | 338 | |
88840332 | 339 | rc = beiscsi_mccq_compl_wait(phba, tag, NULL, nonemb_cmd); |
1957aa7f JK |
340 | |
341 | if (resp_buf) | |
342 | memcpy(resp_buf, nonemb_cmd->va, resp_buf_len); | |
343 | ||
e175defe | 344 | if (rc) { |
1957aa7f | 345 | /* Check if the MBX Cmd needs to be re-issued */ |
1f536d49 JK |
346 | if (rc == -EAGAIN) |
347 | return rc; | |
348 | ||
1957aa7f | 349 | beiscsi_log(phba, KERN_WARNING, |
99bc5d55 | 350 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, |
e175defe JSJ |
351 | "BG_%d : mgmt_exec_nonemb_cmd Failed status\n"); |
352 | ||
1957aa7f JK |
353 | if (rc != -EBUSY) |
354 | goto free_cmd; | |
355 | else | |
356 | return rc; | |
0e43895e | 357 | } |
0e43895e MC |
358 | free_cmd: |
359 | pci_free_consistent(ctrl->pdev, nonemb_cmd->size, | |
360 | nonemb_cmd->va, nonemb_cmd->dma); | |
361 | return rc; | |
362 | } | |
363 | ||
364 | static int mgmt_alloc_cmd_data(struct beiscsi_hba *phba, struct be_dma_mem *cmd, | |
365 | int iscsi_cmd, int size) | |
366 | { | |
7c845eb5 | 367 | cmd->va = pci_zalloc_consistent(phba->ctrl.pdev, size, &cmd->dma); |
0e43895e | 368 | if (!cmd->va) { |
99bc5d55 JSJ |
369 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, |
370 | "BG_%d : Failed to allocate memory for if info\n"); | |
0e43895e MC |
371 | return -ENOMEM; |
372 | } | |
0e43895e MC |
373 | cmd->size = size; |
374 | be_cmd_hdr_prepare(cmd->va, CMD_SUBSYSTEM_ISCSI, iscsi_cmd, size); | |
db02aea9 JB |
375 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, |
376 | "BG_%d : subsystem iSCSI cmd %d size %d\n", | |
377 | iscsi_cmd, size); | |
0e43895e | 378 | return 0; |
bfead3b2 JK |
379 | } |
380 | ||
c5bf8889 JB |
381 | unsigned int beiscsi_if_get_handle(struct beiscsi_hba *phba) |
382 | { | |
383 | struct be_ctrl_info *ctrl = &phba->ctrl; | |
384 | struct be_mcc_wrb *wrb; | |
385 | struct be_cmd_get_all_if_id_req *req; | |
386 | struct be_cmd_get_all_if_id_req *pbe_allid; | |
387 | unsigned int tag; | |
388 | int status = 0; | |
389 | ||
390 | if (mutex_lock_interruptible(&ctrl->mbox_lock)) | |
391 | return -EINTR; | |
392 | wrb = alloc_mcc_wrb(phba, &tag); | |
393 | if (!wrb) { | |
394 | mutex_unlock(&ctrl->mbox_lock); | |
395 | return -ENOMEM; | |
396 | } | |
397 | ||
398 | req = embedded_payload(wrb); | |
399 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | |
400 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | |
401 | OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID, | |
402 | sizeof(*req)); | |
403 | be_mcc_notify(phba, tag); | |
404 | mutex_unlock(&ctrl->mbox_lock); | |
405 | ||
406 | status = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL); | |
407 | if (status) { | |
408 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | |
409 | "BG_%d : %s failed: %d\n", __func__, status); | |
410 | return -EBUSY; | |
411 | } | |
412 | ||
413 | pbe_allid = embedded_payload(wrb); | |
414 | /* we now support only one interface per function */ | |
415 | phba->interface_handle = pbe_allid->if_hndl_list[0]; | |
416 | ||
417 | return status; | |
418 | } | |
419 | ||
290aa376 JB |
420 | static inline bool beiscsi_if_zero_ip(u8 *ip, u32 ip_type) |
421 | { | |
422 | u32 len; | |
423 | ||
424 | len = (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN; | |
425 | while (len && !ip[len - 1]) | |
426 | len--; | |
427 | return (len == 0); | |
428 | } | |
429 | ||
37f21648 JB |
430 | static int beiscsi_if_mod_gw(struct beiscsi_hba *phba, |
431 | u32 action, u32 ip_type, u8 *gw) | |
0e43895e MC |
432 | { |
433 | struct be_cmd_set_def_gateway_req *req; | |
434 | struct be_dma_mem nonemb_cmd; | |
435 | int rt_val; | |
436 | ||
0e43895e MC |
437 | rt_val = mgmt_alloc_cmd_data(phba, &nonemb_cmd, |
438 | OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY, | |
439 | sizeof(*req)); | |
440 | if (rt_val) | |
441 | return rt_val; | |
442 | ||
443 | req = nonemb_cmd.va; | |
37f21648 JB |
444 | req->action = action; |
445 | req->ip_addr.ip_type = ip_type; | |
446 | memcpy(req->ip_addr.addr, gw, | |
290aa376 | 447 | (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN); |
37f21648 JB |
448 | return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); |
449 | } | |
0e43895e | 450 | |
37f21648 JB |
451 | int beiscsi_if_set_gw(struct beiscsi_hba *phba, u32 ip_type, u8 *gw) |
452 | { | |
453 | struct be_cmd_get_def_gateway_resp gw_resp; | |
454 | int rt_val; | |
0e43895e | 455 | |
37f21648 JB |
456 | memset(&gw_resp, 0, sizeof(gw_resp)); |
457 | rt_val = beiscsi_if_get_gw(phba, ip_type, &gw_resp); | |
458 | if (rt_val) { | |
459 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | |
460 | "BG_%d : Failed to Get Gateway Addr\n"); | |
461 | return rt_val; | |
462 | } | |
463 | ||
290aa376 JB |
464 | if (!beiscsi_if_zero_ip(gw_resp.ip_addr.addr, ip_type)) { |
465 | rt_val = beiscsi_if_mod_gw(phba, IP_ACTION_DEL, ip_type, | |
466 | gw_resp.ip_addr.addr); | |
467 | if (rt_val) { | |
468 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | |
469 | "BG_%d : Failed to clear Gateway Addr Set\n"); | |
470 | return rt_val; | |
471 | } | |
37f21648 JB |
472 | } |
473 | ||
474 | rt_val = beiscsi_if_mod_gw(phba, IP_ACTION_ADD, ip_type, gw); | |
475 | if (rt_val) | |
476 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | |
477 | "BG_%d : Failed to Set Gateway Addr\n"); | |
478 | ||
479 | return rt_val; | |
480 | } | |
481 | ||
482 | int beiscsi_if_get_gw(struct beiscsi_hba *phba, u32 ip_type, | |
483 | struct be_cmd_get_def_gateway_resp *resp) | |
484 | { | |
485 | struct be_cmd_get_def_gateway_req *req; | |
486 | struct be_dma_mem nonemb_cmd; | |
487 | int rc; | |
488 | ||
489 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | |
490 | OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY, | |
491 | sizeof(*resp)); | |
492 | if (rc) | |
493 | return rc; | |
494 | ||
495 | req = nonemb_cmd.va; | |
496 | req->ip_type = ip_type; | |
497 | ||
498 | return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, resp, | |
499 | sizeof(*resp)); | |
0e43895e MC |
500 | } |
501 | ||
0152a7e9 JB |
502 | static int |
503 | beiscsi_if_clr_ip(struct beiscsi_hba *phba, | |
504 | struct be_cmd_get_if_info_resp *if_info) | |
0e43895e | 505 | { |
0152a7e9 | 506 | struct be_cmd_set_ip_addr_req *req; |
0e43895e | 507 | struct be_dma_mem nonemb_cmd; |
0e43895e MC |
508 | int rc; |
509 | ||
0152a7e9 JB |
510 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, |
511 | OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR, | |
512 | sizeof(*req)); | |
3c9d903b JB |
513 | if (rc) |
514 | return rc; | |
0e43895e | 515 | |
0152a7e9 JB |
516 | req = nonemb_cmd.va; |
517 | req->ip_params.record_entry_count = 1; | |
518 | req->ip_params.ip_record.action = IP_ACTION_DEL; | |
519 | req->ip_params.ip_record.interface_hndl = | |
520 | phba->interface_handle; | |
521 | req->ip_params.ip_record.ip_addr.size_of_structure = | |
522 | sizeof(struct be_ip_addr_subnet_format); | |
523 | req->ip_params.ip_record.ip_addr.ip_type = if_info->ip_addr.ip_type; | |
524 | memcpy(req->ip_params.ip_record.ip_addr.addr, | |
525 | if_info->ip_addr.addr, | |
526 | sizeof(if_info->ip_addr.addr)); | |
527 | memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, | |
528 | if_info->ip_addr.subnet_mask, | |
529 | sizeof(if_info->ip_addr.subnet_mask)); | |
530 | rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); | |
531 | if (rc < 0 || req->ip_params.ip_record.status) { | |
532 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | |
533 | "BG_%d : failed to clear IP: rc %d status %d\n", | |
534 | rc, req->ip_params.ip_record.status); | |
535 | } | |
536 | return rc; | |
537 | } | |
0e43895e | 538 | |
0152a7e9 JB |
539 | static int |
540 | beiscsi_if_set_ip(struct beiscsi_hba *phba, u8 *ip, | |
541 | u8 *subnet, u32 ip_type) | |
542 | { | |
543 | struct be_cmd_set_ip_addr_req *req; | |
544 | struct be_dma_mem nonemb_cmd; | |
545 | uint32_t ip_len; | |
546 | int rc; | |
547 | ||
548 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | |
549 | OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR, | |
550 | sizeof(*req)); | |
beff6549 | 551 | if (rc) |
0e43895e MC |
552 | return rc; |
553 | ||
0152a7e9 JB |
554 | req = nonemb_cmd.va; |
555 | req->ip_params.record_entry_count = 1; | |
556 | req->ip_params.ip_record.action = IP_ACTION_ADD; | |
557 | req->ip_params.ip_record.interface_hndl = | |
558 | phba->interface_handle; | |
559 | req->ip_params.ip_record.ip_addr.size_of_structure = | |
560 | sizeof(struct be_ip_addr_subnet_format); | |
561 | req->ip_params.ip_record.ip_addr.ip_type = ip_type; | |
290aa376 | 562 | ip_len = (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN; |
0152a7e9 JB |
563 | memcpy(req->ip_params.ip_record.ip_addr.addr, ip, ip_len); |
564 | if (subnet) | |
565 | memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, | |
566 | subnet, ip_len); | |
0e43895e | 567 | |
0152a7e9 JB |
568 | rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); |
569 | /** | |
570 | * In some cases, host needs to look into individual record status | |
571 | * even though FW reported success for that IOCTL. | |
572 | */ | |
573 | if (rc < 0 || req->ip_params.ip_record.status) { | |
574 | __beiscsi_log(phba, KERN_ERR, | |
575 | "BG_%d : failed to set IP: rc %d status %d\n", | |
576 | rc, req->ip_params.ip_record.status); | |
577 | if (req->ip_params.ip_record.status) | |
578 | rc = -EINVAL; | |
579 | } | |
580 | return rc; | |
581 | } | |
0e43895e | 582 | |
0152a7e9 JB |
583 | int beiscsi_if_en_static(struct beiscsi_hba *phba, u32 ip_type, |
584 | u8 *ip, u8 *subnet) | |
585 | { | |
586 | struct be_cmd_get_if_info_resp *if_info; | |
587 | struct be_cmd_rel_dhcp_req *reldhcp; | |
588 | struct be_dma_mem nonemb_cmd; | |
589 | int rc; | |
0e43895e | 590 | |
96b48b92 | 591 | rc = beiscsi_if_get_info(phba, ip_type, &if_info); |
0152a7e9 JB |
592 | if (rc) |
593 | return rc; | |
0e43895e | 594 | |
0152a7e9 JB |
595 | if (if_info->dhcp_state) { |
596 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | |
597 | OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR, | |
598 | sizeof(*reldhcp)); | |
0e43895e | 599 | if (rc) |
6d67726b | 600 | goto exit; |
0e43895e | 601 | |
0152a7e9 JB |
602 | reldhcp = nonemb_cmd.va; |
603 | reldhcp->interface_hndl = phba->interface_handle; | |
604 | reldhcp->ip_type = ip_type; | |
605 | rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); | |
606 | if (rc < 0) { | |
99bc5d55 | 607 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, |
0152a7e9 JB |
608 | "BG_%d : failed to release existing DHCP: %d\n", |
609 | rc); | |
6d67726b | 610 | goto exit; |
0e43895e | 611 | } |
0152a7e9 | 612 | } |
0e43895e | 613 | |
290aa376 JB |
614 | /* first delete any IP set */ |
615 | if (!beiscsi_if_zero_ip(if_info->ip_addr.addr, ip_type)) { | |
616 | rc = beiscsi_if_clr_ip(phba, if_info); | |
617 | if (rc) | |
618 | goto exit; | |
619 | } | |
0e43895e | 620 | |
0152a7e9 JB |
621 | /* if ip == NULL then this is called just to release DHCP IP */ |
622 | if (ip) | |
623 | rc = beiscsi_if_set_ip(phba, ip, subnet, ip_type); | |
624 | exit: | |
625 | kfree(if_info); | |
626 | return rc; | |
627 | } | |
628 | ||
629 | int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type) | |
630 | { | |
631 | struct be_cmd_get_def_gateway_resp gw_resp; | |
632 | struct be_cmd_get_if_info_resp *if_info; | |
633 | struct be_cmd_set_dhcp_req *dhcpreq; | |
634 | struct be_dma_mem nonemb_cmd; | |
635 | u8 *gw; | |
636 | int rc; | |
637 | ||
96b48b92 | 638 | rc = beiscsi_if_get_info(phba, ip_type, &if_info); |
0152a7e9 JB |
639 | if (rc) |
640 | return rc; | |
641 | ||
642 | if (if_info->dhcp_state) { | |
643 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | |
644 | "BG_%d : DHCP Already Enabled\n"); | |
645 | goto exit; | |
0e43895e MC |
646 | } |
647 | ||
290aa376 JB |
648 | /* first delete any IP set */ |
649 | if (!beiscsi_if_zero_ip(if_info->ip_addr.addr, ip_type)) { | |
650 | rc = beiscsi_if_clr_ip(phba, if_info); | |
651 | if (rc) | |
652 | goto exit; | |
653 | } | |
0152a7e9 JB |
654 | |
655 | /* delete gateway settings if mode change is to DHCP */ | |
656 | memset(&gw_resp, 0, sizeof(gw_resp)); | |
657 | /* use ip_type provided in if_info */ | |
658 | rc = beiscsi_if_get_gw(phba, if_info->ip_addr.ip_type, &gw_resp); | |
659 | if (rc) { | |
660 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | |
661 | "BG_%d : Failed to Get Gateway Addr\n"); | |
662 | goto exit; | |
663 | } | |
664 | gw = (u8 *)&gw_resp.ip_addr.addr; | |
290aa376 JB |
665 | if (!beiscsi_if_zero_ip(gw, if_info->ip_addr.ip_type)) { |
666 | rc = beiscsi_if_mod_gw(phba, IP_ACTION_DEL, | |
667 | if_info->ip_addr.ip_type, gw); | |
668 | if (rc) { | |
669 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | |
670 | "BG_%d : Failed to clear Gateway Addr Set\n"); | |
671 | goto exit; | |
672 | } | |
0152a7e9 JB |
673 | } |
674 | ||
675 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | |
0e43895e MC |
676 | OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR, |
677 | sizeof(*dhcpreq)); | |
0152a7e9 JB |
678 | if (rc) |
679 | goto exit; | |
0e43895e | 680 | |
0152a7e9 | 681 | dhcpreq = nonemb_cmd.va; |
290aa376 | 682 | dhcpreq->flags = 1; /* 1 - blocking; 0 - non-blocking */ |
0152a7e9 JB |
683 | dhcpreq->retry_count = 1; |
684 | dhcpreq->interface_hndl = phba->interface_handle; | |
685 | dhcpreq->ip_type = ip_type; | |
686 | rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); | |
0e43895e | 687 | |
6d67726b ML |
688 | exit: |
689 | kfree(if_info); | |
0e43895e MC |
690 | return rc; |
691 | } | |
692 | ||
db02aea9 JB |
693 | /** |
694 | * beiscsi_if_set_vlan()- Issue and wait for CMD completion | |
695 | * @phba: device private structure instance | |
696 | * @vlan_tag: VLAN tag | |
697 | * | |
698 | * Issue the MBX Cmd and wait for the completion of the | |
699 | * command. | |
700 | * | |
701 | * returns | |
702 | * Success: 0 | |
703 | * Failure: Non-Xero Value | |
704 | **/ | |
705 | int beiscsi_if_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag) | |
706 | { | |
707 | int rc; | |
708 | unsigned int tag; | |
709 | ||
710 | tag = be_cmd_set_vlan(phba, vlan_tag); | |
711 | if (!tag) { | |
712 | beiscsi_log(phba, KERN_ERR, | |
713 | (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX), | |
714 | "BG_%d : VLAN Setting Failed\n"); | |
715 | return -EBUSY; | |
716 | } | |
717 | ||
718 | rc = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL); | |
719 | if (rc) { | |
720 | beiscsi_log(phba, KERN_ERR, | |
721 | (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX), | |
722 | "BS_%d : VLAN MBX Cmd Failed\n"); | |
723 | return rc; | |
724 | } | |
725 | return rc; | |
726 | } | |
727 | ||
728 | ||
96b48b92 JB |
729 | int beiscsi_if_get_info(struct beiscsi_hba *phba, int ip_type, |
730 | struct be_cmd_get_if_info_resp **if_info) | |
0e43895e MC |
731 | { |
732 | struct be_cmd_get_if_info_req *req; | |
733 | struct be_dma_mem nonemb_cmd; | |
1f536d49 | 734 | uint32_t ioctl_size = sizeof(struct be_cmd_get_if_info_resp); |
0e43895e MC |
735 | int rc; |
736 | ||
c5bf8889 | 737 | rc = beiscsi_if_get_handle(phba); |
3c9d903b JB |
738 | if (rc) |
739 | return rc; | |
0e43895e | 740 | |
1f536d49 JK |
741 | do { |
742 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | |
743 | OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO, | |
744 | ioctl_size); | |
745 | if (rc) | |
746 | return rc; | |
0e43895e | 747 | |
1f536d49 JK |
748 | req = nonemb_cmd.va; |
749 | req->interface_hndl = phba->interface_handle; | |
750 | req->ip_type = ip_type; | |
751 | ||
752 | /* Allocate memory for if_info */ | |
753 | *if_info = kzalloc(ioctl_size, GFP_KERNEL); | |
754 | if (!*if_info) { | |
755 | beiscsi_log(phba, KERN_ERR, | |
756 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | |
757 | "BG_%d : Memory Allocation Failure\n"); | |
758 | ||
759 | /* Free the DMA memory for the IOCTL issuing */ | |
760 | pci_free_consistent(phba->ctrl.pdev, | |
761 | nonemb_cmd.size, | |
762 | nonemb_cmd.va, | |
763 | nonemb_cmd.dma); | |
764 | return -ENOMEM; | |
765 | } | |
766 | ||
767 | rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, *if_info, | |
768 | ioctl_size); | |
0e43895e | 769 | |
1f536d49 JK |
770 | /* Check if the error is because of Insufficent_Buffer */ |
771 | if (rc == -EAGAIN) { | |
772 | ||
773 | /* Get the new memory size */ | |
774 | ioctl_size = ((struct be_cmd_resp_hdr *) | |
775 | nonemb_cmd.va)->actual_resp_len; | |
776 | ioctl_size += sizeof(struct be_cmd_req_hdr); | |
777 | ||
778 | /* Free the previous allocated DMA memory */ | |
779 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | |
780 | nonemb_cmd.va, | |
781 | nonemb_cmd.dma); | |
782 | ||
783 | /* Free the virtual memory */ | |
784 | kfree(*if_info); | |
785 | } else | |
786 | break; | |
787 | } while (true); | |
788 | return rc; | |
0e43895e MC |
789 | } |
790 | ||
791 | int mgmt_get_nic_conf(struct beiscsi_hba *phba, | |
792 | struct be_cmd_get_nic_conf_resp *nic) | |
793 | { | |
794 | struct be_dma_mem nonemb_cmd; | |
795 | int rc; | |
796 | ||
797 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | |
798 | OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG, | |
799 | sizeof(*nic)); | |
800 | if (rc) | |
801 | return rc; | |
802 | ||
803 | return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, nic, sizeof(*nic)); | |
804 | } | |
805 | ||
806 | ||
807 | ||
2177199d JSJ |
808 | unsigned int be_cmd_get_initname(struct beiscsi_hba *phba) |
809 | { | |
090e2184 | 810 | unsigned int tag; |
2177199d JSJ |
811 | struct be_mcc_wrb *wrb; |
812 | struct be_cmd_hba_name *req; | |
813 | struct be_ctrl_info *ctrl = &phba->ctrl; | |
814 | ||
c03a50f7 JB |
815 | if (mutex_lock_interruptible(&ctrl->mbox_lock)) |
816 | return 0; | |
090e2184 JB |
817 | wrb = alloc_mcc_wrb(phba, &tag); |
818 | if (!wrb) { | |
c03a50f7 | 819 | mutex_unlock(&ctrl->mbox_lock); |
090e2184 | 820 | return 0; |
2177199d JSJ |
821 | } |
822 | ||
2177199d | 823 | req = embedded_payload(wrb); |
2177199d JSJ |
824 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
825 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | |
826 | OPCODE_ISCSI_INI_CFG_GET_HBA_NAME, | |
827 | sizeof(*req)); | |
828 | ||
cdde6682 | 829 | be_mcc_notify(phba, tag); |
c03a50f7 | 830 | mutex_unlock(&ctrl->mbox_lock); |
2177199d JSJ |
831 | return tag; |
832 | } | |
c62eef0d | 833 | |
50a4b824 JB |
834 | static void beiscsi_boot_process_compl(struct beiscsi_hba *phba, |
835 | unsigned int tag) | |
836 | { | |
837 | struct be_cmd_get_boot_target_resp *boot_resp; | |
838 | struct be_cmd_resp_logout_fw_sess *logo_resp; | |
839 | struct be_cmd_get_session_resp *sess_resp; | |
840 | struct be_mcc_wrb *wrb; | |
841 | struct boot_struct *bs; | |
842 | int boot_work, status; | |
843 | ||
844 | if (!test_bit(BEISCSI_HBA_BOOT_WORK, &phba->state)) { | |
845 | __beiscsi_log(phba, KERN_ERR, | |
846 | "BG_%d : %s no boot work %lx\n", | |
847 | __func__, phba->state); | |
848 | return; | |
849 | } | |
850 | ||
851 | if (phba->boot_struct.tag != tag) { | |
852 | __beiscsi_log(phba, KERN_ERR, | |
853 | "BG_%d : %s tag mismatch %d:%d\n", | |
854 | __func__, tag, phba->boot_struct.tag); | |
855 | return; | |
856 | } | |
857 | bs = &phba->boot_struct; | |
858 | boot_work = 1; | |
859 | status = 0; | |
860 | switch (bs->action) { | |
861 | case BEISCSI_BOOT_REOPEN_SESS: | |
862 | status = __beiscsi_mcc_compl_status(phba, tag, NULL, NULL); | |
863 | if (!status) | |
864 | bs->action = BEISCSI_BOOT_GET_SHANDLE; | |
865 | else | |
866 | bs->retry--; | |
867 | break; | |
868 | case BEISCSI_BOOT_GET_SHANDLE: | |
869 | status = __beiscsi_mcc_compl_status(phba, tag, &wrb, NULL); | |
870 | if (!status) { | |
871 | boot_resp = embedded_payload(wrb); | |
872 | bs->s_handle = boot_resp->boot_session_handle; | |
873 | } | |
874 | if (bs->s_handle == BE_BOOT_INVALID_SHANDLE) { | |
875 | bs->action = BEISCSI_BOOT_REOPEN_SESS; | |
876 | bs->retry--; | |
877 | } else { | |
878 | bs->action = BEISCSI_BOOT_GET_SINFO; | |
879 | } | |
880 | break; | |
881 | case BEISCSI_BOOT_GET_SINFO: | |
882 | status = __beiscsi_mcc_compl_status(phba, tag, NULL, | |
883 | &bs->nonemb_cmd); | |
884 | if (!status) { | |
885 | sess_resp = bs->nonemb_cmd.va; | |
886 | memcpy(&bs->boot_sess, &sess_resp->session_info, | |
887 | sizeof(struct mgmt_session_info)); | |
888 | bs->action = BEISCSI_BOOT_LOGOUT_SESS; | |
889 | } else { | |
890 | __beiscsi_log(phba, KERN_ERR, | |
891 | "BG_%d : get boot session info error : 0x%x\n", | |
892 | status); | |
893 | boot_work = 0; | |
894 | } | |
895 | pci_free_consistent(phba->ctrl.pdev, bs->nonemb_cmd.size, | |
896 | bs->nonemb_cmd.va, bs->nonemb_cmd.dma); | |
897 | bs->nonemb_cmd.va = NULL; | |
898 | break; | |
899 | case BEISCSI_BOOT_LOGOUT_SESS: | |
900 | status = __beiscsi_mcc_compl_status(phba, tag, &wrb, NULL); | |
901 | if (!status) { | |
902 | logo_resp = embedded_payload(wrb); | |
903 | if (logo_resp->session_status != BE_SESS_STATUS_CLOSE) { | |
904 | __beiscsi_log(phba, KERN_ERR, | |
905 | "BG_%d : FW boot session logout error : 0x%x\n", | |
906 | logo_resp->session_status); | |
907 | } | |
908 | } | |
909 | /* continue to create boot_kset even if logout failed? */ | |
910 | bs->action = BEISCSI_BOOT_CREATE_KSET; | |
911 | break; | |
912 | default: | |
913 | break; | |
914 | } | |
915 | ||
916 | /* clear the tag so no other completion matches this tag */ | |
917 | bs->tag = 0; | |
918 | if (!bs->retry) { | |
919 | boot_work = 0; | |
920 | __beiscsi_log(phba, KERN_ERR, | |
921 | "BG_%d : failed to setup boot target: status %d action %d\n", | |
922 | status, bs->action); | |
923 | } | |
924 | if (!boot_work) { | |
925 | /* wait for next event to start boot_work */ | |
926 | clear_bit(BEISCSI_HBA_BOOT_WORK, &phba->state); | |
927 | return; | |
928 | } | |
929 | schedule_work(&phba->boot_work); | |
930 | } | |
931 | ||
9aef4200 | 932 | /** |
50a4b824 JB |
933 | * beiscsi_boot_logout_sess()- Logout from boot FW session |
934 | * @phba: Device priv structure instance | |
935 | * | |
936 | * return | |
937 | * the TAG used for MBOX Command | |
9aef4200 | 938 | * |
50a4b824 JB |
939 | */ |
940 | unsigned int beiscsi_boot_logout_sess(struct beiscsi_hba *phba) | |
941 | { | |
942 | struct be_ctrl_info *ctrl = &phba->ctrl; | |
943 | struct be_mcc_wrb *wrb; | |
944 | struct be_cmd_req_logout_fw_sess *req; | |
945 | unsigned int tag; | |
946 | ||
947 | mutex_lock(&ctrl->mbox_lock); | |
948 | wrb = alloc_mcc_wrb(phba, &tag); | |
949 | if (!wrb) { | |
950 | mutex_unlock(&ctrl->mbox_lock); | |
951 | return 0; | |
952 | } | |
953 | ||
954 | req = embedded_payload(wrb); | |
955 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | |
956 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | |
957 | OPCODE_ISCSI_INI_SESSION_LOGOUT_TARGET, | |
958 | sizeof(struct be_cmd_req_logout_fw_sess)); | |
959 | /* Use the session handle copied into boot_sess */ | |
960 | req->session_handle = phba->boot_struct.boot_sess.session_handle; | |
961 | ||
962 | phba->boot_struct.tag = tag; | |
963 | set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state); | |
964 | ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl; | |
965 | ||
966 | be_mcc_notify(phba, tag); | |
967 | mutex_unlock(&ctrl->mbox_lock); | |
968 | ||
969 | return tag; | |
970 | } | |
971 | /** | |
972 | * beiscsi_boot_reopen_sess()- Reopen boot session | |
973 | * @phba: Device priv structure instance | |
9aef4200 JSJ |
974 | * |
975 | * return | |
50a4b824 | 976 | * the TAG used for MBOX Command |
9aef4200 JSJ |
977 | * |
978 | **/ | |
50a4b824 | 979 | unsigned int beiscsi_boot_reopen_sess(struct beiscsi_hba *phba) |
9aef4200 | 980 | { |
50a4b824 | 981 | struct be_ctrl_info *ctrl = &phba->ctrl; |
9aef4200 | 982 | struct be_mcc_wrb *wrb; |
50a4b824 | 983 | struct be_cmd_reopen_session_req *req; |
e175defe | 984 | unsigned int tag; |
9aef4200 | 985 | |
50a4b824 JB |
986 | mutex_lock(&ctrl->mbox_lock); |
987 | wrb = alloc_mcc_wrb(phba, &tag); | |
988 | if (!wrb) { | |
989 | mutex_unlock(&ctrl->mbox_lock); | |
990 | return 0; | |
991 | } | |
e175defe | 992 | |
50a4b824 JB |
993 | req = embedded_payload(wrb); |
994 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | |
995 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | |
996 | OPCODE_ISCSI_INI_DRIVER_REOPEN_ALL_SESSIONS, | |
997 | sizeof(struct be_cmd_reopen_session_resp)); | |
998 | req->reopen_type = BE_REOPEN_BOOT_SESSIONS; | |
999 | req->session_handle = BE_BOOT_INVALID_SHANDLE; | |
e175defe | 1000 | |
50a4b824 JB |
1001 | phba->boot_struct.tag = tag; |
1002 | set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state); | |
1003 | ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl; | |
9aef4200 | 1004 | |
50a4b824 JB |
1005 | be_mcc_notify(phba, tag); |
1006 | mutex_unlock(&ctrl->mbox_lock); | |
1007 | return tag; | |
1008 | } | |
9aef4200 | 1009 | |
9aef4200 | 1010 | |
50a4b824 JB |
1011 | /** |
1012 | * beiscsi_boot_get_sinfo()- Get boot session info | |
1013 | * @phba: device priv structure instance | |
1014 | * | |
1015 | * Fetches the boot_struct.s_handle info from FW. | |
1016 | * return | |
1017 | * the TAG used for MBOX Command | |
1018 | * | |
1019 | **/ | |
1020 | unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba) | |
1021 | { | |
1022 | struct be_ctrl_info *ctrl = &phba->ctrl; | |
50a4b824 JB |
1023 | struct be_cmd_get_session_req *req; |
1024 | struct be_dma_mem *nonemb_cmd; | |
1025 | struct be_mcc_wrb *wrb; | |
1026 | struct be_sge *sge; | |
1027 | unsigned int tag; | |
e175defe | 1028 | |
50a4b824 JB |
1029 | mutex_lock(&ctrl->mbox_lock); |
1030 | wrb = alloc_mcc_wrb(phba, &tag); | |
1031 | if (!wrb) { | |
1032 | mutex_unlock(&ctrl->mbox_lock); | |
1033 | return 0; | |
1034 | } | |
9aef4200 | 1035 | |
50a4b824 | 1036 | nonemb_cmd = &phba->boot_struct.nonemb_cmd; |
fa1261c4 | 1037 | nonemb_cmd->size = sizeof(struct be_cmd_get_session_resp); |
50a4b824 | 1038 | nonemb_cmd->va = pci_alloc_consistent(phba->ctrl.pdev, |
23b98e4b | 1039 | nonemb_cmd->size, |
50a4b824 | 1040 | &nonemb_cmd->dma); |
658f18d1 JB |
1041 | if (!nonemb_cmd->va) { |
1042 | mutex_unlock(&ctrl->mbox_lock); | |
50a4b824 | 1043 | return 0; |
658f18d1 | 1044 | } |
50a4b824 JB |
1045 | |
1046 | req = nonemb_cmd->va; | |
1047 | memset(req, 0, sizeof(*req)); | |
1048 | sge = nonembedded_sgl(wrb); | |
1049 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); | |
1050 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | |
1051 | OPCODE_ISCSI_INI_SESSION_GET_A_SESSION, | |
fa1261c4 | 1052 | sizeof(struct be_cmd_get_session_resp)); |
50a4b824 JB |
1053 | req->session_handle = phba->boot_struct.s_handle; |
1054 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); | |
1055 | sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); | |
1056 | sge->len = cpu_to_le32(nonemb_cmd->size); | |
1057 | ||
1058 | phba->boot_struct.tag = tag; | |
1059 | set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state); | |
1060 | ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl; | |
1061 | ||
1062 | be_mcc_notify(phba, tag); | |
1063 | mutex_unlock(&ctrl->mbox_lock); | |
1064 | return tag; | |
1065 | } | |
1066 | ||
1067 | unsigned int __beiscsi_boot_get_shandle(struct beiscsi_hba *phba, int async) | |
1068 | { | |
1069 | struct be_ctrl_info *ctrl = &phba->ctrl; | |
1070 | struct be_mcc_wrb *wrb; | |
1071 | struct be_cmd_get_boot_target_req *req; | |
1072 | unsigned int tag; | |
1073 | ||
1074 | mutex_lock(&ctrl->mbox_lock); | |
1075 | wrb = alloc_mcc_wrb(phba, &tag); | |
1076 | if (!wrb) { | |
1077 | mutex_unlock(&ctrl->mbox_lock); | |
1078 | return 0; | |
1079 | } | |
1080 | ||
1081 | req = embedded_payload(wrb); | |
1082 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | |
1083 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | |
1084 | OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET, | |
1085 | sizeof(struct be_cmd_get_boot_target_resp)); | |
1086 | ||
1087 | if (async) { | |
1088 | phba->boot_struct.tag = tag; | |
1089 | set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state); | |
1090 | ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl; | |
1091 | } | |
1092 | ||
1093 | be_mcc_notify(phba, tag); | |
1094 | mutex_unlock(&ctrl->mbox_lock); | |
1095 | return tag; | |
1096 | } | |
1097 | ||
1098 | /** | |
1099 | * beiscsi_boot_get_shandle()- Get boot session handle | |
1100 | * @phba: device priv structure instance | |
1101 | * @s_handle: session handle returned for boot session. | |
1102 | * | |
1103 | * return | |
1104 | * Success: 1 | |
1105 | * Failure: negative | |
1106 | * | |
1107 | **/ | |
1108 | int beiscsi_boot_get_shandle(struct beiscsi_hba *phba, unsigned int *s_handle) | |
1109 | { | |
1110 | struct be_cmd_get_boot_target_resp *boot_resp; | |
1111 | struct be_mcc_wrb *wrb; | |
1112 | unsigned int tag; | |
1113 | int rc; | |
1114 | ||
1115 | *s_handle = BE_BOOT_INVALID_SHANDLE; | |
1116 | /* get configured boot session count and handle */ | |
1117 | tag = __beiscsi_boot_get_shandle(phba, 0); | |
1118 | if (!tag) { | |
1119 | beiscsi_log(phba, KERN_ERR, | |
1120 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, | |
1121 | "BG_%d : Getting Boot Target Info Failed\n"); | |
1122 | return -EAGAIN; | |
1123 | } | |
1124 | ||
1125 | rc = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL); | |
1126 | if (rc) { | |
1127 | beiscsi_log(phba, KERN_ERR, | |
1128 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | |
1129 | "BG_%d : MBX CMD get_boot_target Failed\n"); | |
1130 | return -EBUSY; | |
1131 | } | |
1132 | ||
1133 | boot_resp = embedded_payload(wrb); | |
1134 | /* check if there are any boot targets configured */ | |
1135 | if (!boot_resp->boot_session_count) { | |
1136 | __beiscsi_log(phba, KERN_INFO, | |
1137 | "BG_%d : No boot targets configured\n"); | |
1138 | return -ENXIO; | |
1139 | } | |
1140 | ||
1141 | /* only if FW has logged in to the boot target, s_handle is valid */ | |
1142 | *s_handle = boot_resp->boot_session_handle; | |
1143 | return 1; | |
9aef4200 | 1144 | } |
6f72238e | 1145 | |
5cac7596 JSJ |
1146 | /** |
1147 | * beiscsi_drvr_ver_disp()- Display the driver Name and Version | |
1148 | * @dev: ptr to device not used. | |
1149 | * @attr: device attribute, not used. | |
1150 | * @buf: contains formatted text driver name and version | |
1151 | * | |
1152 | * return | |
1153 | * size of the formatted string | |
1154 | **/ | |
1155 | ssize_t | |
1156 | beiscsi_drvr_ver_disp(struct device *dev, struct device_attribute *attr, | |
1157 | char *buf) | |
1158 | { | |
1159 | return snprintf(buf, PAGE_SIZE, BE_NAME "\n"); | |
1160 | } | |
acb9693c | 1161 | |
22661e25 JK |
1162 | /** |
1163 | * beiscsi_fw_ver_disp()- Display Firmware Version | |
1164 | * @dev: ptr to device not used. | |
1165 | * @attr: device attribute, not used. | |
1166 | * @buf: contains formatted text Firmware version | |
1167 | * | |
1168 | * return | |
1169 | * size of the formatted string | |
1170 | **/ | |
1171 | ssize_t | |
1172 | beiscsi_fw_ver_disp(struct device *dev, struct device_attribute *attr, | |
1173 | char *buf) | |
1174 | { | |
1175 | struct Scsi_Host *shost = class_to_shost(dev); | |
1176 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | |
1177 | ||
1178 | return snprintf(buf, PAGE_SIZE, "%s\n", phba->fw_ver_str); | |
1179 | } | |
1180 | ||
7ad4dfe1 | 1181 | /** |
6103c1f7 | 1182 | * beiscsi_active_session_disp()- Display Sessions Active |
7ad4dfe1 JK |
1183 | * @dev: ptr to device not used. |
1184 | * @attr: device attribute, not used. | |
1185 | * @buf: contains formatted text Session Count | |
1186 | * | |
1187 | * return | |
1188 | * size of the formatted string | |
1189 | **/ | |
1190 | ssize_t | |
6103c1f7 | 1191 | beiscsi_active_session_disp(struct device *dev, struct device_attribute *attr, |
7ad4dfe1 JK |
1192 | char *buf) |
1193 | { | |
1194 | struct Scsi_Host *shost = class_to_shost(dev); | |
1195 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | |
0a3db7c0 JK |
1196 | uint16_t avlbl_cids = 0, ulp_num, len = 0, total_cids = 0; |
1197 | ||
1198 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | |
1199 | if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { | |
1200 | avlbl_cids = BEISCSI_ULP_AVLBL_CID(phba, ulp_num); | |
1201 | total_cids = BEISCSI_GET_CID_COUNT(phba, ulp_num); | |
1202 | len += snprintf(buf+len, PAGE_SIZE - len, | |
1203 | "ULP%d : %d\n", ulp_num, | |
1204 | (total_cids - avlbl_cids)); | |
1205 | } else | |
1206 | len += snprintf(buf+len, PAGE_SIZE - len, | |
1207 | "ULP%d : %d\n", ulp_num, 0); | |
1208 | } | |
7ad4dfe1 | 1209 | |
0a3db7c0 | 1210 | return len; |
7ad4dfe1 JK |
1211 | } |
1212 | ||
6103c1f7 JK |
1213 | /** |
1214 | * beiscsi_free_session_disp()- Display Avaliable Session | |
1215 | * @dev: ptr to device not used. | |
1216 | * @attr: device attribute, not used. | |
1217 | * @buf: contains formatted text Session Count | |
1218 | * | |
1219 | * return | |
1220 | * size of the formatted string | |
1221 | **/ | |
1222 | ssize_t | |
1223 | beiscsi_free_session_disp(struct device *dev, struct device_attribute *attr, | |
1224 | char *buf) | |
1225 | { | |
1226 | struct Scsi_Host *shost = class_to_shost(dev); | |
1227 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | |
1228 | uint16_t ulp_num, len = 0; | |
1229 | ||
1230 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | |
1231 | if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) | |
1232 | len += snprintf(buf+len, PAGE_SIZE - len, | |
1233 | "ULP%d : %d\n", ulp_num, | |
1234 | BEISCSI_ULP_AVLBL_CID(phba, ulp_num)); | |
1235 | else | |
1236 | len += snprintf(buf+len, PAGE_SIZE - len, | |
1237 | "ULP%d : %d\n", ulp_num, 0); | |
1238 | } | |
1239 | ||
1240 | return len; | |
1241 | } | |
1242 | ||
26000db7 JSJ |
1243 | /** |
1244 | * beiscsi_adap_family_disp()- Display adapter family. | |
1245 | * @dev: ptr to device to get priv structure | |
1246 | * @attr: device attribute, not used. | |
1247 | * @buf: contains formatted text driver name and version | |
1248 | * | |
1249 | * return | |
1250 | * size of the formatted string | |
1251 | **/ | |
1252 | ssize_t | |
1253 | beiscsi_adap_family_disp(struct device *dev, struct device_attribute *attr, | |
1254 | char *buf) | |
1255 | { | |
1256 | uint16_t dev_id = 0; | |
1257 | struct Scsi_Host *shost = class_to_shost(dev); | |
1258 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | |
1259 | ||
1260 | dev_id = phba->pcidev->device; | |
1261 | switch (dev_id) { | |
1262 | case BE_DEVICE_ID1: | |
1263 | case OC_DEVICE_ID1: | |
1264 | case OC_DEVICE_ID2: | |
5fa7db21 KM |
1265 | return snprintf(buf, PAGE_SIZE, |
1266 | "Obsolete/Unsupported BE2 Adapter Family\n"); | |
26000db7 JSJ |
1267 | break; |
1268 | case BE_DEVICE_ID2: | |
1269 | case OC_DEVICE_ID3: | |
1270 | return snprintf(buf, PAGE_SIZE, "BE3-R Adapter Family\n"); | |
1271 | break; | |
1272 | case OC_SKH_ID1: | |
1273 | return snprintf(buf, PAGE_SIZE, "Skyhawk-R Adapter Family\n"); | |
1274 | break; | |
1275 | default: | |
1276 | return snprintf(buf, PAGE_SIZE, | |
b23f7a09 | 1277 | "Unknown Adapter Family: 0x%x\n", dev_id); |
26000db7 JSJ |
1278 | break; |
1279 | } | |
1280 | } | |
1281 | ||
d3fea9af JK |
1282 | /** |
1283 | * beiscsi_phys_port()- Display Physical Port Identifier | |
1284 | * @dev: ptr to device not used. | |
1285 | * @attr: device attribute, not used. | |
1286 | * @buf: contains formatted text port identifier | |
1287 | * | |
1288 | * return | |
1289 | * size of the formatted string | |
1290 | **/ | |
1291 | ssize_t | |
1292 | beiscsi_phys_port_disp(struct device *dev, struct device_attribute *attr, | |
1293 | char *buf) | |
1294 | { | |
1295 | struct Scsi_Host *shost = class_to_shost(dev); | |
1296 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | |
1297 | ||
fa1261c4 | 1298 | return snprintf(buf, PAGE_SIZE, "Port Identifier : %u\n", |
d3fea9af JK |
1299 | phba->fw_config.phys_port); |
1300 | } | |
26000db7 | 1301 | |
acb9693c JSJ |
1302 | void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, |
1303 | struct wrb_handle *pwrb_handle, | |
340c99e9 JSJ |
1304 | struct be_mem_descriptor *mem_descr, |
1305 | struct hwi_wrb_context *pwrb_context) | |
acb9693c JSJ |
1306 | { |
1307 | struct iscsi_wrb *pwrb = pwrb_handle->pwrb; | |
1308 | ||
acb9693c JSJ |
1309 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, |
1310 | max_send_data_segment_length, pwrb, | |
1311 | params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1312 | max_send_data_segment_length) / 32]); | |
1313 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, type, pwrb, | |
1314 | BE_TGT_CTX_UPDT_CMD); | |
1315 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, | |
1316 | first_burst_length, | |
1317 | pwrb, | |
1318 | params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1319 | first_burst_length) / 32]); | |
1320 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, erl, pwrb, | |
1321 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1322 | erl) / 32] & OFFLD_PARAMS_ERL)); | |
1323 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, dde, pwrb, | |
1324 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1325 | dde) / 32] & OFFLD_PARAMS_DDE) >> 2); | |
1326 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, hde, pwrb, | |
1327 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1328 | hde) / 32] & OFFLD_PARAMS_HDE) >> 3); | |
1329 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ir2t, pwrb, | |
1330 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1331 | ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4); | |
1332 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, imd, pwrb, | |
1333 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1334 | imd) / 32] & OFFLD_PARAMS_IMD) >> 5); | |
1335 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, stat_sn, | |
1336 | pwrb, | |
1337 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1338 | exp_statsn) / 32] + 1)); | |
1339 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, wrb_idx, | |
1340 | pwrb, pwrb_handle->wrb_index); | |
1341 | ||
1342 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, | |
1343 | max_burst_length, pwrb, params->dw[offsetof | |
1344 | (struct amap_beiscsi_offload_params, | |
1345 | max_burst_length) / 32]); | |
1346 | ||
1347 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb, | |
340c99e9 JSJ |
1348 | pwrb, pwrb_handle->wrb_index); |
1349 | if (pwrb_context->plast_wrb) | |
1350 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, | |
1351 | ptr2nextwrb, | |
1352 | pwrb_context->plast_wrb, | |
1353 | pwrb_handle->wrb_index); | |
1354 | pwrb_context->plast_wrb = pwrb; | |
1355 | ||
acb9693c JSJ |
1356 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, |
1357 | session_state, pwrb, 0); | |
1358 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack, | |
1359 | pwrb, 1); | |
1360 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, notpredblq, | |
1361 | pwrb, 0); | |
1362 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, mode, pwrb, | |
1363 | 0); | |
1364 | ||
1365 | mem_descr += ISCSI_MEM_GLOBAL_HEADER; | |
1366 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, | |
1367 | pad_buffer_addr_hi, pwrb, | |
1368 | mem_descr->mem_array[0].bus_address.u.a32.address_hi); | |
1369 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, | |
1370 | pad_buffer_addr_lo, pwrb, | |
1371 | mem_descr->mem_array[0].bus_address.u.a32.address_lo); | |
1372 | } | |
1373 | ||
1374 | void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, | |
340c99e9 JSJ |
1375 | struct wrb_handle *pwrb_handle, |
1376 | struct hwi_wrb_context *pwrb_context) | |
acb9693c JSJ |
1377 | { |
1378 | struct iscsi_wrb *pwrb = pwrb_handle->pwrb; | |
1379 | ||
acb9693c JSJ |
1380 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, |
1381 | max_burst_length, pwrb, params->dw[offsetof | |
1382 | (struct amap_beiscsi_offload_params, | |
1383 | max_burst_length) / 32]); | |
1384 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, | |
1385 | type, pwrb, | |
1386 | BE_TGT_CTX_UPDT_CMD); | |
1387 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, | |
1388 | ptr2nextwrb, | |
340c99e9 JSJ |
1389 | pwrb, pwrb_handle->wrb_index); |
1390 | if (pwrb_context->plast_wrb) | |
1391 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, | |
1392 | ptr2nextwrb, | |
1393 | pwrb_context->plast_wrb, | |
1394 | pwrb_handle->wrb_index); | |
1395 | pwrb_context->plast_wrb = pwrb; | |
1396 | ||
acb9693c JSJ |
1397 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, wrb_idx, |
1398 | pwrb, pwrb_handle->wrb_index); | |
1399 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, | |
1400 | max_send_data_segment_length, pwrb, | |
1401 | params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1402 | max_send_data_segment_length) / 32]); | |
1403 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, | |
1404 | first_burst_length, pwrb, | |
1405 | params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1406 | first_burst_length) / 32]); | |
1407 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, | |
7331613e JK |
1408 | max_recv_dataseg_len, pwrb, |
1409 | params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1410 | max_recv_data_segment_length) / 32]); | |
acb9693c JSJ |
1411 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, |
1412 | max_cxns, pwrb, BEISCSI_MAX_CXNS); | |
1413 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, erl, pwrb, | |
1414 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1415 | erl) / 32] & OFFLD_PARAMS_ERL)); | |
1416 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, dde, pwrb, | |
1417 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1418 | dde) / 32] & OFFLD_PARAMS_DDE) >> 2); | |
1419 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, hde, pwrb, | |
1420 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1421 | hde) / 32] & OFFLD_PARAMS_HDE) >> 3); | |
1422 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, | |
1423 | ir2t, pwrb, | |
1424 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1425 | ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4); | |
1426 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, imd, pwrb, | |
1427 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1428 | imd) / 32] & OFFLD_PARAMS_IMD) >> 5); | |
1429 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, | |
1430 | data_seq_inorder, | |
1431 | pwrb, | |
1432 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1433 | data_seq_inorder) / 32] & | |
1434 | OFFLD_PARAMS_DATA_SEQ_INORDER) >> 6); | |
1435 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, | |
1436 | pdu_seq_inorder, | |
1437 | pwrb, | |
1438 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1439 | pdu_seq_inorder) / 32] & | |
1440 | OFFLD_PARAMS_PDU_SEQ_INORDER) >> 7); | |
1441 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, max_r2t, | |
1442 | pwrb, | |
1443 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1444 | max_r2t) / 32] & | |
1445 | OFFLD_PARAMS_MAX_R2T) >> 8); | |
1446 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, stat_sn, | |
1447 | pwrb, | |
1448 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | |
1449 | exp_statsn) / 32] + 1)); | |
1450 | } | |
98713216 JB |
1451 | |
1452 | int beiscsi_mgmt_invalidate_icds(struct beiscsi_hba *phba, | |
1453 | struct invldt_cmd_tbl *inv_tbl, | |
1454 | unsigned int nents) | |
1455 | { | |
1456 | struct be_ctrl_info *ctrl = &phba->ctrl; | |
1457 | struct invldt_cmds_params_in *req; | |
1458 | struct be_dma_mem nonemb_cmd; | |
1459 | struct be_mcc_wrb *wrb; | |
1460 | unsigned int i, tag; | |
1461 | struct be_sge *sge; | |
1462 | int rc; | |
1463 | ||
1464 | if (!nents || nents > BE_INVLDT_CMD_TBL_SZ) | |
1465 | return -EINVAL; | |
1466 | ||
1467 | nonemb_cmd.size = sizeof(union be_invldt_cmds_params); | |
1468 | nonemb_cmd.va = pci_zalloc_consistent(phba->ctrl.pdev, | |
1469 | nonemb_cmd.size, | |
1470 | &nonemb_cmd.dma); | |
1471 | if (!nonemb_cmd.va) { | |
1472 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH, | |
1473 | "BM_%d : invldt_cmds_params alloc failed\n"); | |
1474 | return -ENOMEM; | |
1475 | } | |
1476 | ||
1477 | mutex_lock(&ctrl->mbox_lock); | |
1478 | wrb = alloc_mcc_wrb(phba, &tag); | |
1479 | if (!wrb) { | |
1480 | mutex_unlock(&ctrl->mbox_lock); | |
1481 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | |
1482 | nonemb_cmd.va, nonemb_cmd.dma); | |
1483 | return -ENOMEM; | |
1484 | } | |
1485 | ||
1486 | req = nonemb_cmd.va; | |
1487 | be_wrb_hdr_prepare(wrb, nonemb_cmd.size, false, 1); | |
1488 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | |
1489 | OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS, | |
1490 | sizeof(*req)); | |
1491 | req->ref_handle = 0; | |
1492 | req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE; | |
1493 | for (i = 0; i < nents; i++) { | |
1494 | req->table[i].icd = inv_tbl[i].icd; | |
1495 | req->table[i].cid = inv_tbl[i].cid; | |
1496 | req->icd_count++; | |
1497 | } | |
1498 | sge = nonembedded_sgl(wrb); | |
1499 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); | |
1500 | sge->pa_lo = cpu_to_le32(lower_32_bits(nonemb_cmd.dma)); | |
1501 | sge->len = cpu_to_le32(nonemb_cmd.size); | |
1502 | ||
1503 | be_mcc_notify(phba, tag); | |
1504 | mutex_unlock(&ctrl->mbox_lock); | |
1505 | ||
1506 | rc = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd); | |
1507 | if (rc != -EBUSY) | |
1508 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | |
1509 | nonemb_cmd.va, nonemb_cmd.dma); | |
1510 | return rc; | |
1511 | } |