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