diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_config.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_config.c | 1873 |
1 files changed, 1873 insertions, 0 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c new file mode 100644 index 000000000000..58cfb97846f7 --- /dev/null +++ b/drivers/scsi/mpt2sas/mpt2sas_config.c | |||
@@ -0,0 +1,1873 @@ | |||
1 | /* | ||
2 | * This module provides common API for accessing firmware configuration pages | ||
3 | * | ||
4 | * This code is based on drivers/scsi/mpt2sas/mpt2_base.c | ||
5 | * Copyright (C) 2007-2008 LSI Corporation | ||
6 | * (mailto:DL-MPTFusionLinux@lsi.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version 2 | ||
11 | * of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * NO WARRANTY | ||
19 | * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
20 | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | ||
21 | * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | ||
22 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | ||
23 | * solely responsible for determining the appropriateness of using and | ||
24 | * distributing the Program and assumes all risks associated with its | ||
25 | * exercise of rights under this Agreement, including but not limited to | ||
26 | * the risks and costs of program errors, damage to or loss of data, | ||
27 | * programs or equipment, and unavailability or interruption of operations. | ||
28 | |||
29 | * DISCLAIMER OF LIABILITY | ||
30 | * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
31 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
32 | * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
33 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
34 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
35 | * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
36 | * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
37 | |||
38 | * You should have received a copy of the GNU General Public License | ||
39 | * along with this program; if not, write to the Free Software | ||
40 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
41 | * USA. | ||
42 | */ | ||
43 | |||
44 | #include <linux/version.h> | ||
45 | #include <linux/module.h> | ||
46 | #include <linux/kernel.h> | ||
47 | #include <linux/init.h> | ||
48 | #include <linux/errno.h> | ||
49 | #include <linux/blkdev.h> | ||
50 | #include <linux/sched.h> | ||
51 | #include <linux/workqueue.h> | ||
52 | #include <linux/delay.h> | ||
53 | #include <linux/pci.h> | ||
54 | |||
55 | #include "mpt2sas_base.h" | ||
56 | |||
57 | /* local definitions */ | ||
58 | |||
59 | /* Timeout for config page request (in seconds) */ | ||
60 | #define MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT 15 | ||
61 | |||
62 | /* Common sgl flags for READING a config page. */ | ||
63 | #define MPT2_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \ | ||
64 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \ | ||
65 | | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT) | ||
66 | |||
67 | /* Common sgl flags for WRITING a config page. */ | ||
68 | #define MPT2_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \ | ||
69 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \ | ||
70 | | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \ | ||
71 | << MPI2_SGE_FLAGS_SHIFT) | ||
72 | |||
73 | /** | ||
74 | * struct config_request - obtain dma memory via routine | ||
75 | * @config_page_sz: size | ||
76 | * @config_page: virt pointer | ||
77 | * @config_page_dma: phys pointer | ||
78 | * | ||
79 | */ | ||
80 | struct config_request{ | ||
81 | u16 config_page_sz; | ||
82 | void *config_page; | ||
83 | dma_addr_t config_page_dma; | ||
84 | }; | ||
85 | |||
86 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
87 | /** | ||
88 | * _config_display_some_debug - debug routine | ||
89 | * @ioc: per adapter object | ||
90 | * @smid: system request message index | ||
91 | * @calling_function_name: string pass from calling function | ||
92 | * @mpi_reply: reply message frame | ||
93 | * Context: none. | ||
94 | * | ||
95 | * Function for displaying debug info helpfull when debugging issues | ||
96 | * in this module. | ||
97 | */ | ||
98 | static void | ||
99 | _config_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid, | ||
100 | char *calling_function_name, MPI2DefaultReply_t *mpi_reply) | ||
101 | { | ||
102 | Mpi2ConfigRequest_t *mpi_request; | ||
103 | char *desc = NULL; | ||
104 | |||
105 | if (!(ioc->logging_level & MPT_DEBUG_CONFIG)) | ||
106 | return; | ||
107 | |||
108 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
109 | switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) { | ||
110 | case MPI2_CONFIG_PAGETYPE_IO_UNIT: | ||
111 | desc = "io_unit"; | ||
112 | break; | ||
113 | case MPI2_CONFIG_PAGETYPE_IOC: | ||
114 | desc = "ioc"; | ||
115 | break; | ||
116 | case MPI2_CONFIG_PAGETYPE_BIOS: | ||
117 | desc = "bios"; | ||
118 | break; | ||
119 | case MPI2_CONFIG_PAGETYPE_RAID_VOLUME: | ||
120 | desc = "raid_volume"; | ||
121 | break; | ||
122 | case MPI2_CONFIG_PAGETYPE_MANUFACTURING: | ||
123 | desc = "manufaucturing"; | ||
124 | break; | ||
125 | case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK: | ||
126 | desc = "physdisk"; | ||
127 | break; | ||
128 | case MPI2_CONFIG_PAGETYPE_EXTENDED: | ||
129 | switch (mpi_request->ExtPageType) { | ||
130 | case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT: | ||
131 | desc = "sas_io_unit"; | ||
132 | break; | ||
133 | case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER: | ||
134 | desc = "sas_expander"; | ||
135 | break; | ||
136 | case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE: | ||
137 | desc = "sas_device"; | ||
138 | break; | ||
139 | case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY: | ||
140 | desc = "sas_phy"; | ||
141 | break; | ||
142 | case MPI2_CONFIG_EXTPAGETYPE_LOG: | ||
143 | desc = "log"; | ||
144 | break; | ||
145 | case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE: | ||
146 | desc = "enclosure"; | ||
147 | break; | ||
148 | case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG: | ||
149 | desc = "raid_config"; | ||
150 | break; | ||
151 | case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING: | ||
152 | desc = "driver_mappping"; | ||
153 | break; | ||
154 | } | ||
155 | break; | ||
156 | } | ||
157 | |||
158 | if (!desc) | ||
159 | return; | ||
160 | |||
161 | printk(MPT2SAS_DEBUG_FMT "%s: %s(%d), action(%d), form(0x%08x), " | ||
162 | "smid(%d)\n", ioc->name, calling_function_name, desc, | ||
163 | mpi_request->Header.PageNumber, mpi_request->Action, | ||
164 | le32_to_cpu(mpi_request->PageAddress), smid); | ||
165 | |||
166 | if (!mpi_reply) | ||
167 | return; | ||
168 | |||
169 | if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo) | ||
170 | printk(MPT2SAS_DEBUG_FMT | ||
171 | "\tiocstatus(0x%04x), loginfo(0x%08x)\n", | ||
172 | ioc->name, le16_to_cpu(mpi_reply->IOCStatus), | ||
173 | le32_to_cpu(mpi_reply->IOCLogInfo)); | ||
174 | } | ||
175 | #endif | ||
176 | |||
177 | /** | ||
178 | * mpt2sas_config_done - config page completion routine | ||
179 | * @ioc: per adapter object | ||
180 | * @smid: system request message index | ||
181 | * @VF_ID: virtual function id | ||
182 | * @reply: reply message frame(lower 32bit addr) | ||
183 | * Context: none. | ||
184 | * | ||
185 | * The callback handler when using _config_request. | ||
186 | * | ||
187 | * Return nothing. | ||
188 | */ | ||
189 | void | ||
190 | mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | ||
191 | { | ||
192 | MPI2DefaultReply_t *mpi_reply; | ||
193 | |||
194 | if (ioc->config_cmds.status == MPT2_CMD_NOT_USED) | ||
195 | return; | ||
196 | if (ioc->config_cmds.smid != smid) | ||
197 | return; | ||
198 | ioc->config_cmds.status |= MPT2_CMD_COMPLETE; | ||
199 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
200 | if (mpi_reply) { | ||
201 | ioc->config_cmds.status |= MPT2_CMD_REPLY_VALID; | ||
202 | memcpy(ioc->config_cmds.reply, mpi_reply, | ||
203 | mpi_reply->MsgLength*4); | ||
204 | } | ||
205 | ioc->config_cmds.status &= ~MPT2_CMD_PENDING; | ||
206 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
207 | _config_display_some_debug(ioc, smid, "config_done", mpi_reply); | ||
208 | #endif | ||
209 | complete(&ioc->config_cmds.done); | ||
210 | } | ||
211 | |||
212 | /** | ||
213 | * _config_request - main routine for sending config page requests | ||
214 | * @ioc: per adapter object | ||
215 | * @mpi_request: request message frame | ||
216 | * @mpi_reply: reply mf payload returned from firmware | ||
217 | * @timeout: timeout in seconds | ||
218 | * Context: sleep, the calling function needs to acquire the config_cmds.mutex | ||
219 | * | ||
220 | * A generic API for config page requests to firmware. | ||
221 | * | ||
222 | * The ioc->config_cmds.status flag should be MPT2_CMD_NOT_USED before calling | ||
223 | * this API. | ||
224 | * | ||
225 | * The callback index is set inside `ioc->config_cb_idx. | ||
226 | * | ||
227 | * Returns 0 for success, non-zero for failure. | ||
228 | */ | ||
229 | static int | ||
230 | _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t | ||
231 | *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout) | ||
232 | { | ||
233 | u16 smid; | ||
234 | u32 ioc_state; | ||
235 | unsigned long timeleft; | ||
236 | Mpi2ConfigRequest_t *config_request; | ||
237 | int r; | ||
238 | u8 retry_count; | ||
239 | u8 issue_reset; | ||
240 | u16 wait_state_count; | ||
241 | |||
242 | if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) { | ||
243 | printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n", | ||
244 | ioc->name, __func__); | ||
245 | return -EAGAIN; | ||
246 | } | ||
247 | retry_count = 0; | ||
248 | |||
249 | retry_config: | ||
250 | wait_state_count = 0; | ||
251 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
252 | while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | ||
253 | if (wait_state_count++ == MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT) { | ||
254 | printk(MPT2SAS_ERR_FMT | ||
255 | "%s: failed due to ioc not operational\n", | ||
256 | ioc->name, __func__); | ||
257 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; | ||
258 | return -EFAULT; | ||
259 | } | ||
260 | ssleep(1); | ||
261 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
262 | printk(MPT2SAS_INFO_FMT "%s: waiting for " | ||
263 | "operational state(count=%d)\n", ioc->name, | ||
264 | __func__, wait_state_count); | ||
265 | } | ||
266 | if (wait_state_count) | ||
267 | printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", | ||
268 | ioc->name, __func__); | ||
269 | |||
270 | smid = mpt2sas_base_get_smid(ioc, ioc->config_cb_idx); | ||
271 | if (!smid) { | ||
272 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
273 | ioc->name, __func__); | ||
274 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; | ||
275 | return -EAGAIN; | ||
276 | } | ||
277 | |||
278 | r = 0; | ||
279 | memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t)); | ||
280 | ioc->config_cmds.status = MPT2_CMD_PENDING; | ||
281 | config_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
282 | ioc->config_cmds.smid = smid; | ||
283 | memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t)); | ||
284 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | ||
285 | _config_display_some_debug(ioc, smid, "config_request", NULL); | ||
286 | #endif | ||
287 | mpt2sas_base_put_smid_default(ioc, smid, config_request->VF_ID); | ||
288 | timeleft = wait_for_completion_timeout(&ioc->config_cmds.done, | ||
289 | timeout*HZ); | ||
290 | if (!(ioc->config_cmds.status & MPT2_CMD_COMPLETE)) { | ||
291 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | ||
292 | ioc->name, __func__); | ||
293 | _debug_dump_mf(mpi_request, | ||
294 | sizeof(Mpi2ConfigRequest_t)/4); | ||
295 | if (!(ioc->config_cmds.status & MPT2_CMD_RESET)) | ||
296 | issue_reset = 1; | ||
297 | goto issue_host_reset; | ||
298 | } | ||
299 | if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID) | ||
300 | memcpy(mpi_reply, ioc->config_cmds.reply, | ||
301 | sizeof(Mpi2ConfigReply_t)); | ||
302 | if (retry_count) | ||
303 | printk(MPT2SAS_INFO_FMT "%s: retry completed!!\n", | ||
304 | ioc->name, __func__); | ||
305 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; | ||
306 | return r; | ||
307 | |||
308 | issue_host_reset: | ||
309 | if (issue_reset) | ||
310 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | ||
311 | FORCE_BIG_HAMMER); | ||
312 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; | ||
313 | if (!retry_count) { | ||
314 | printk(MPT2SAS_INFO_FMT "%s: attempting retry\n", | ||
315 | ioc->name, __func__); | ||
316 | retry_count++; | ||
317 | goto retry_config; | ||
318 | } | ||
319 | return -EFAULT; | ||
320 | } | ||
321 | |||
322 | /** | ||
323 | * _config_alloc_config_dma_memory - obtain physical memory | ||
324 | * @ioc: per adapter object | ||
325 | * @mem: struct config_request | ||
326 | * | ||
327 | * A wrapper for obtaining dma-able memory for config page request. | ||
328 | * | ||
329 | * Returns 0 for success, non-zero for failure. | ||
330 | */ | ||
331 | static int | ||
332 | _config_alloc_config_dma_memory(struct MPT2SAS_ADAPTER *ioc, | ||
333 | struct config_request *mem) | ||
334 | { | ||
335 | int r = 0; | ||
336 | |||
337 | mem->config_page = pci_alloc_consistent(ioc->pdev, mem->config_page_sz, | ||
338 | &mem->config_page_dma); | ||
339 | if (!mem->config_page) | ||
340 | r = -ENOMEM; | ||
341 | return r; | ||
342 | } | ||
343 | |||
344 | /** | ||
345 | * _config_free_config_dma_memory - wrapper to free the memory | ||
346 | * @ioc: per adapter object | ||
347 | * @mem: struct config_request | ||
348 | * | ||
349 | * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory. | ||
350 | * | ||
351 | * Returns 0 for success, non-zero for failure. | ||
352 | */ | ||
353 | static void | ||
354 | _config_free_config_dma_memory(struct MPT2SAS_ADAPTER *ioc, | ||
355 | struct config_request *mem) | ||
356 | { | ||
357 | pci_free_consistent(ioc->pdev, mem->config_page_sz, mem->config_page, | ||
358 | mem->config_page_dma); | ||
359 | } | ||
360 | |||
361 | /** | ||
362 | * mpt2sas_config_get_manufacturing_pg0 - obtain manufacturing page 0 | ||
363 | * @ioc: per adapter object | ||
364 | * @mpi_reply: reply mf payload returned from firmware | ||
365 | * @config_page: contents of the config page | ||
366 | * Context: sleep. | ||
367 | * | ||
368 | * Returns 0 for success, non-zero for failure. | ||
369 | */ | ||
370 | int | ||
371 | mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc, | ||
372 | Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page) | ||
373 | { | ||
374 | Mpi2ConfigRequest_t mpi_request; | ||
375 | int r; | ||
376 | struct config_request mem; | ||
377 | |||
378 | mutex_lock(&ioc->config_cmds.mutex); | ||
379 | memset(config_page, 0, sizeof(Mpi2ManufacturingPage0_t)); | ||
380 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
381 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
382 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
383 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; | ||
384 | mpi_request.Header.PageNumber = 0; | ||
385 | mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; | ||
386 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
387 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
388 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
389 | if (r) | ||
390 | goto out; | ||
391 | |||
392 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
393 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
394 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
395 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
396 | mpi_request.Header.PageLength = mpi_reply->Header.PageLength; | ||
397 | mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; | ||
398 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
399 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
400 | if (r) | ||
401 | goto out; | ||
402 | } else { | ||
403 | mem.config_page_dma = ioc->config_page_dma; | ||
404 | mem.config_page = ioc->config_page; | ||
405 | } | ||
406 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
407 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
408 | mem.config_page_dma); | ||
409 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
410 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
411 | if (!r) | ||
412 | memcpy(config_page, mem.config_page, | ||
413 | min_t(u16, mem.config_page_sz, | ||
414 | sizeof(Mpi2ManufacturingPage0_t))); | ||
415 | |||
416 | if (mem.config_page_sz > ioc->config_page_sz) | ||
417 | _config_free_config_dma_memory(ioc, &mem); | ||
418 | |||
419 | out: | ||
420 | mutex_unlock(&ioc->config_cmds.mutex); | ||
421 | return r; | ||
422 | } | ||
423 | |||
424 | /** | ||
425 | * mpt2sas_config_get_bios_pg2 - obtain bios page 2 | ||
426 | * @ioc: per adapter object | ||
427 | * @mpi_reply: reply mf payload returned from firmware | ||
428 | * @config_page: contents of the config page | ||
429 | * Context: sleep. | ||
430 | * | ||
431 | * Returns 0 for success, non-zero for failure. | ||
432 | */ | ||
433 | int | ||
434 | mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, | ||
435 | Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page) | ||
436 | { | ||
437 | Mpi2ConfigRequest_t mpi_request; | ||
438 | int r; | ||
439 | struct config_request mem; | ||
440 | |||
441 | mutex_lock(&ioc->config_cmds.mutex); | ||
442 | memset(config_page, 0, sizeof(Mpi2BiosPage2_t)); | ||
443 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
444 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
445 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
446 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; | ||
447 | mpi_request.Header.PageNumber = 2; | ||
448 | mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION; | ||
449 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
450 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
451 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
452 | if (r) | ||
453 | goto out; | ||
454 | |||
455 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
456 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
457 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
458 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
459 | mpi_request.Header.PageLength = mpi_reply->Header.PageLength; | ||
460 | mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; | ||
461 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
462 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
463 | if (r) | ||
464 | goto out; | ||
465 | } else { | ||
466 | mem.config_page_dma = ioc->config_page_dma; | ||
467 | mem.config_page = ioc->config_page; | ||
468 | } | ||
469 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
470 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
471 | mem.config_page_dma); | ||
472 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
473 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
474 | if (!r) | ||
475 | memcpy(config_page, mem.config_page, | ||
476 | min_t(u16, mem.config_page_sz, | ||
477 | sizeof(Mpi2BiosPage2_t))); | ||
478 | |||
479 | if (mem.config_page_sz > ioc->config_page_sz) | ||
480 | _config_free_config_dma_memory(ioc, &mem); | ||
481 | |||
482 | out: | ||
483 | mutex_unlock(&ioc->config_cmds.mutex); | ||
484 | return r; | ||
485 | } | ||
486 | |||
487 | /** | ||
488 | * mpt2sas_config_get_bios_pg3 - obtain bios page 3 | ||
489 | * @ioc: per adapter object | ||
490 | * @mpi_reply: reply mf payload returned from firmware | ||
491 | * @config_page: contents of the config page | ||
492 | * Context: sleep. | ||
493 | * | ||
494 | * Returns 0 for success, non-zero for failure. | ||
495 | */ | ||
496 | int | ||
497 | mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
498 | *mpi_reply, Mpi2BiosPage3_t *config_page) | ||
499 | { | ||
500 | Mpi2ConfigRequest_t mpi_request; | ||
501 | int r; | ||
502 | struct config_request mem; | ||
503 | |||
504 | mutex_lock(&ioc->config_cmds.mutex); | ||
505 | memset(config_page, 0, sizeof(Mpi2BiosPage3_t)); | ||
506 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
507 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
508 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
509 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; | ||
510 | mpi_request.Header.PageNumber = 3; | ||
511 | mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; | ||
512 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
513 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
514 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
515 | if (r) | ||
516 | goto out; | ||
517 | |||
518 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
519 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
520 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
521 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
522 | mpi_request.Header.PageLength = mpi_reply->Header.PageLength; | ||
523 | mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; | ||
524 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
525 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
526 | if (r) | ||
527 | goto out; | ||
528 | } else { | ||
529 | mem.config_page_dma = ioc->config_page_dma; | ||
530 | mem.config_page = ioc->config_page; | ||
531 | } | ||
532 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
533 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
534 | mem.config_page_dma); | ||
535 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
536 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
537 | if (!r) | ||
538 | memcpy(config_page, mem.config_page, | ||
539 | min_t(u16, mem.config_page_sz, | ||
540 | sizeof(Mpi2BiosPage3_t))); | ||
541 | |||
542 | if (mem.config_page_sz > ioc->config_page_sz) | ||
543 | _config_free_config_dma_memory(ioc, &mem); | ||
544 | |||
545 | out: | ||
546 | mutex_unlock(&ioc->config_cmds.mutex); | ||
547 | return r; | ||
548 | } | ||
549 | |||
550 | /** | ||
551 | * mpt2sas_config_get_iounit_pg0 - obtain iounit page 0 | ||
552 | * @ioc: per adapter object | ||
553 | * @mpi_reply: reply mf payload returned from firmware | ||
554 | * @config_page: contents of the config page | ||
555 | * Context: sleep. | ||
556 | * | ||
557 | * Returns 0 for success, non-zero for failure. | ||
558 | */ | ||
559 | int | ||
560 | mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, | ||
561 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page) | ||
562 | { | ||
563 | Mpi2ConfigRequest_t mpi_request; | ||
564 | int r; | ||
565 | struct config_request mem; | ||
566 | |||
567 | mutex_lock(&ioc->config_cmds.mutex); | ||
568 | memset(config_page, 0, sizeof(Mpi2IOUnitPage0_t)); | ||
569 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
570 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
571 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
572 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | ||
573 | mpi_request.Header.PageNumber = 0; | ||
574 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION; | ||
575 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
576 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
577 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
578 | if (r) | ||
579 | goto out; | ||
580 | |||
581 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
582 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
583 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
584 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
585 | mpi_request.Header.PageLength = mpi_reply->Header.PageLength; | ||
586 | mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; | ||
587 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
588 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
589 | if (r) | ||
590 | goto out; | ||
591 | } else { | ||
592 | mem.config_page_dma = ioc->config_page_dma; | ||
593 | mem.config_page = ioc->config_page; | ||
594 | } | ||
595 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
596 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
597 | mem.config_page_dma); | ||
598 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
599 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
600 | if (!r) | ||
601 | memcpy(config_page, mem.config_page, | ||
602 | min_t(u16, mem.config_page_sz, | ||
603 | sizeof(Mpi2IOUnitPage0_t))); | ||
604 | |||
605 | if (mem.config_page_sz > ioc->config_page_sz) | ||
606 | _config_free_config_dma_memory(ioc, &mem); | ||
607 | |||
608 | out: | ||
609 | mutex_unlock(&ioc->config_cmds.mutex); | ||
610 | return r; | ||
611 | } | ||
612 | |||
613 | /** | ||
614 | * mpt2sas_config_get_iounit_pg1 - obtain iounit page 1 | ||
615 | * @ioc: per adapter object | ||
616 | * @mpi_reply: reply mf payload returned from firmware | ||
617 | * @config_page: contents of the config page | ||
618 | * Context: sleep. | ||
619 | * | ||
620 | * Returns 0 for success, non-zero for failure. | ||
621 | */ | ||
622 | int | ||
623 | mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, | ||
624 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page) | ||
625 | { | ||
626 | Mpi2ConfigRequest_t mpi_request; | ||
627 | int r; | ||
628 | struct config_request mem; | ||
629 | |||
630 | mutex_lock(&ioc->config_cmds.mutex); | ||
631 | memset(config_page, 0, sizeof(Mpi2IOUnitPage1_t)); | ||
632 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
633 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
634 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
635 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | ||
636 | mpi_request.Header.PageNumber = 1; | ||
637 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION; | ||
638 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
639 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
640 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
641 | if (r) | ||
642 | goto out; | ||
643 | |||
644 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
645 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
646 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
647 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
648 | mpi_request.Header.PageLength = mpi_reply->Header.PageLength; | ||
649 | mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; | ||
650 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
651 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
652 | if (r) | ||
653 | goto out; | ||
654 | } else { | ||
655 | mem.config_page_dma = ioc->config_page_dma; | ||
656 | mem.config_page = ioc->config_page; | ||
657 | } | ||
658 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
659 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
660 | mem.config_page_dma); | ||
661 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
662 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
663 | if (!r) | ||
664 | memcpy(config_page, mem.config_page, | ||
665 | min_t(u16, mem.config_page_sz, | ||
666 | sizeof(Mpi2IOUnitPage1_t))); | ||
667 | |||
668 | if (mem.config_page_sz > ioc->config_page_sz) | ||
669 | _config_free_config_dma_memory(ioc, &mem); | ||
670 | |||
671 | out: | ||
672 | mutex_unlock(&ioc->config_cmds.mutex); | ||
673 | return r; | ||
674 | } | ||
675 | |||
676 | /** | ||
677 | * mpt2sas_config_set_iounit_pg1 - set iounit page 1 | ||
678 | * @ioc: per adapter object | ||
679 | * @mpi_reply: reply mf payload returned from firmware | ||
680 | * @config_page: contents of the config page | ||
681 | * Context: sleep. | ||
682 | * | ||
683 | * Returns 0 for success, non-zero for failure. | ||
684 | */ | ||
685 | int | ||
686 | mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, | ||
687 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t config_page) | ||
688 | { | ||
689 | Mpi2ConfigRequest_t mpi_request; | ||
690 | int r; | ||
691 | struct config_request mem; | ||
692 | |||
693 | mutex_lock(&ioc->config_cmds.mutex); | ||
694 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
695 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
696 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
697 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | ||
698 | mpi_request.Header.PageNumber = 1; | ||
699 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION; | ||
700 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
701 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
702 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
703 | if (r) | ||
704 | goto out; | ||
705 | |||
706 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
707 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
708 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
709 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
710 | mpi_request.Header.PageLength = mpi_reply->Header.PageLength; | ||
711 | mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; | ||
712 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
713 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
714 | if (r) | ||
715 | goto out; | ||
716 | } else { | ||
717 | mem.config_page_dma = ioc->config_page_dma; | ||
718 | mem.config_page = ioc->config_page; | ||
719 | } | ||
720 | |||
721 | memset(mem.config_page, 0, mem.config_page_sz); | ||
722 | memcpy(mem.config_page, &config_page, | ||
723 | sizeof(Mpi2IOUnitPage1_t)); | ||
724 | |||
725 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
726 | MPT2_CONFIG_COMMON_WRITE_SGLFLAGS | mem.config_page_sz, | ||
727 | mem.config_page_dma); | ||
728 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
729 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
730 | |||
731 | if (mem.config_page_sz > ioc->config_page_sz) | ||
732 | _config_free_config_dma_memory(ioc, &mem); | ||
733 | |||
734 | out: | ||
735 | mutex_unlock(&ioc->config_cmds.mutex); | ||
736 | return r; | ||
737 | } | ||
738 | |||
739 | /** | ||
740 | * mpt2sas_config_get_ioc_pg8 - obtain ioc page 8 | ||
741 | * @ioc: per adapter object | ||
742 | * @mpi_reply: reply mf payload returned from firmware | ||
743 | * @config_page: contents of the config page | ||
744 | * Context: sleep. | ||
745 | * | ||
746 | * Returns 0 for success, non-zero for failure. | ||
747 | */ | ||
748 | int | ||
749 | mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, | ||
750 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page) | ||
751 | { | ||
752 | Mpi2ConfigRequest_t mpi_request; | ||
753 | int r; | ||
754 | struct config_request mem; | ||
755 | |||
756 | mutex_lock(&ioc->config_cmds.mutex); | ||
757 | memset(config_page, 0, sizeof(Mpi2IOCPage8_t)); | ||
758 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
759 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
760 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
761 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; | ||
762 | mpi_request.Header.PageNumber = 8; | ||
763 | mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; | ||
764 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
765 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
766 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
767 | if (r) | ||
768 | goto out; | ||
769 | |||
770 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
771 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
772 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
773 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
774 | mpi_request.Header.PageLength = mpi_reply->Header.PageLength; | ||
775 | mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; | ||
776 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
777 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
778 | if (r) | ||
779 | goto out; | ||
780 | } else { | ||
781 | mem.config_page_dma = ioc->config_page_dma; | ||
782 | mem.config_page = ioc->config_page; | ||
783 | } | ||
784 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
785 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
786 | mem.config_page_dma); | ||
787 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
788 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
789 | if (!r) | ||
790 | memcpy(config_page, mem.config_page, | ||
791 | min_t(u16, mem.config_page_sz, | ||
792 | sizeof(Mpi2IOCPage8_t))); | ||
793 | |||
794 | if (mem.config_page_sz > ioc->config_page_sz) | ||
795 | _config_free_config_dma_memory(ioc, &mem); | ||
796 | |||
797 | out: | ||
798 | mutex_unlock(&ioc->config_cmds.mutex); | ||
799 | return r; | ||
800 | } | ||
801 | |||
802 | /** | ||
803 | * mpt2sas_config_get_sas_device_pg0 - obtain sas device page 0 | ||
804 | * @ioc: per adapter object | ||
805 | * @mpi_reply: reply mf payload returned from firmware | ||
806 | * @config_page: contents of the config page | ||
807 | * @form: GET_NEXT_HANDLE or HANDLE | ||
808 | * @handle: device handle | ||
809 | * Context: sleep. | ||
810 | * | ||
811 | * Returns 0 for success, non-zero for failure. | ||
812 | */ | ||
813 | int | ||
814 | mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
815 | *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle) | ||
816 | { | ||
817 | Mpi2ConfigRequest_t mpi_request; | ||
818 | int r; | ||
819 | struct config_request mem; | ||
820 | |||
821 | mutex_lock(&ioc->config_cmds.mutex); | ||
822 | memset(config_page, 0, sizeof(Mpi2SasDevicePage0_t)); | ||
823 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
824 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
825 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
826 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
827 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; | ||
828 | mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; | ||
829 | mpi_request.Header.PageNumber = 0; | ||
830 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
831 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
832 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
833 | if (r) | ||
834 | goto out; | ||
835 | |||
836 | mpi_request.PageAddress = cpu_to_le32(form | handle); | ||
837 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
838 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
839 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
840 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
841 | mpi_request.ExtPageLength = mpi_reply->ExtPageLength; | ||
842 | mpi_request.ExtPageType = mpi_reply->ExtPageType; | ||
843 | mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; | ||
844 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
845 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
846 | if (r) | ||
847 | goto out; | ||
848 | } else { | ||
849 | mem.config_page_dma = ioc->config_page_dma; | ||
850 | mem.config_page = ioc->config_page; | ||
851 | } | ||
852 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
853 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
854 | mem.config_page_dma); | ||
855 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
856 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
857 | if (!r) | ||
858 | memcpy(config_page, mem.config_page, | ||
859 | min_t(u16, mem.config_page_sz, | ||
860 | sizeof(Mpi2SasDevicePage0_t))); | ||
861 | |||
862 | if (mem.config_page_sz > ioc->config_page_sz) | ||
863 | _config_free_config_dma_memory(ioc, &mem); | ||
864 | |||
865 | out: | ||
866 | mutex_unlock(&ioc->config_cmds.mutex); | ||
867 | return r; | ||
868 | } | ||
869 | |||
870 | /** | ||
871 | * mpt2sas_config_get_sas_device_pg1 - obtain sas device page 1 | ||
872 | * @ioc: per adapter object | ||
873 | * @mpi_reply: reply mf payload returned from firmware | ||
874 | * @config_page: contents of the config page | ||
875 | * @form: GET_NEXT_HANDLE or HANDLE | ||
876 | * @handle: device handle | ||
877 | * Context: sleep. | ||
878 | * | ||
879 | * Returns 0 for success, non-zero for failure. | ||
880 | */ | ||
881 | int | ||
882 | mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
883 | *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle) | ||
884 | { | ||
885 | Mpi2ConfigRequest_t mpi_request; | ||
886 | int r; | ||
887 | struct config_request mem; | ||
888 | |||
889 | mutex_lock(&ioc->config_cmds.mutex); | ||
890 | memset(config_page, 0, sizeof(Mpi2SasDevicePage1_t)); | ||
891 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
892 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
893 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
894 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
895 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; | ||
896 | mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION; | ||
897 | mpi_request.Header.PageNumber = 1; | ||
898 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
899 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
900 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
901 | if (r) | ||
902 | goto out; | ||
903 | |||
904 | mpi_request.PageAddress = cpu_to_le32(form | handle); | ||
905 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
906 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
907 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
908 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
909 | mpi_request.ExtPageLength = mpi_reply->ExtPageLength; | ||
910 | mpi_request.ExtPageType = mpi_reply->ExtPageType; | ||
911 | mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; | ||
912 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
913 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
914 | if (r) | ||
915 | goto out; | ||
916 | } else { | ||
917 | mem.config_page_dma = ioc->config_page_dma; | ||
918 | mem.config_page = ioc->config_page; | ||
919 | } | ||
920 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
921 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
922 | mem.config_page_dma); | ||
923 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
924 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
925 | if (!r) | ||
926 | memcpy(config_page, mem.config_page, | ||
927 | min_t(u16, mem.config_page_sz, | ||
928 | sizeof(Mpi2SasDevicePage1_t))); | ||
929 | |||
930 | if (mem.config_page_sz > ioc->config_page_sz) | ||
931 | _config_free_config_dma_memory(ioc, &mem); | ||
932 | |||
933 | out: | ||
934 | mutex_unlock(&ioc->config_cmds.mutex); | ||
935 | return r; | ||
936 | } | ||
937 | |||
938 | /** | ||
939 | * mpt2sas_config_get_number_hba_phys - obtain number of phys on the host | ||
940 | * @ioc: per adapter object | ||
941 | * @num_phys: pointer returned with the number of phys | ||
942 | * Context: sleep. | ||
943 | * | ||
944 | * Returns 0 for success, non-zero for failure. | ||
945 | */ | ||
946 | int | ||
947 | mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys) | ||
948 | { | ||
949 | Mpi2ConfigRequest_t mpi_request; | ||
950 | int r; | ||
951 | struct config_request mem; | ||
952 | u16 ioc_status; | ||
953 | Mpi2ConfigReply_t mpi_reply; | ||
954 | Mpi2SasIOUnitPage0_t config_page; | ||
955 | |||
956 | mutex_lock(&ioc->config_cmds.mutex); | ||
957 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
958 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
959 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
960 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
961 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | ||
962 | mpi_request.Header.PageNumber = 0; | ||
963 | mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; | ||
964 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
965 | r = _config_request(ioc, &mpi_request, &mpi_reply, | ||
966 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
967 | if (r) | ||
968 | goto out; | ||
969 | |||
970 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
971 | mpi_request.Header.PageVersion = mpi_reply.Header.PageVersion; | ||
972 | mpi_request.Header.PageNumber = mpi_reply.Header.PageNumber; | ||
973 | mpi_request.Header.PageType = mpi_reply.Header.PageType; | ||
974 | mpi_request.ExtPageLength = mpi_reply.ExtPageLength; | ||
975 | mpi_request.ExtPageType = mpi_reply.ExtPageType; | ||
976 | mem.config_page_sz = le16_to_cpu(mpi_reply.ExtPageLength) * 4; | ||
977 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
978 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
979 | if (r) | ||
980 | goto out; | ||
981 | } else { | ||
982 | mem.config_page_dma = ioc->config_page_dma; | ||
983 | mem.config_page = ioc->config_page; | ||
984 | } | ||
985 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
986 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
987 | mem.config_page_dma); | ||
988 | r = _config_request(ioc, &mpi_request, &mpi_reply, | ||
989 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
990 | if (!r) { | ||
991 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
992 | MPI2_IOCSTATUS_MASK; | ||
993 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { | ||
994 | memcpy(&config_page, mem.config_page, | ||
995 | min_t(u16, mem.config_page_sz, | ||
996 | sizeof(Mpi2SasIOUnitPage0_t))); | ||
997 | *num_phys = config_page.NumPhys; | ||
998 | } | ||
999 | } | ||
1000 | |||
1001 | if (mem.config_page_sz > ioc->config_page_sz) | ||
1002 | _config_free_config_dma_memory(ioc, &mem); | ||
1003 | |||
1004 | out: | ||
1005 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1006 | return r; | ||
1007 | } | ||
1008 | |||
1009 | /** | ||
1010 | * mpt2sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0 | ||
1011 | * @ioc: per adapter object | ||
1012 | * @mpi_reply: reply mf payload returned from firmware | ||
1013 | * @config_page: contents of the config page | ||
1014 | * @sz: size of buffer passed in config_page | ||
1015 | * Context: sleep. | ||
1016 | * | ||
1017 | * Calling function should call config_get_number_hba_phys prior to | ||
1018 | * this function, so enough memory is allocated for config_page. | ||
1019 | * | ||
1020 | * Returns 0 for success, non-zero for failure. | ||
1021 | */ | ||
1022 | int | ||
1023 | mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
1024 | *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz) | ||
1025 | { | ||
1026 | Mpi2ConfigRequest_t mpi_request; | ||
1027 | int r; | ||
1028 | struct config_request mem; | ||
1029 | |||
1030 | mutex_lock(&ioc->config_cmds.mutex); | ||
1031 | memset(config_page, 0, sz); | ||
1032 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
1033 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
1034 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
1035 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
1036 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | ||
1037 | mpi_request.Header.PageNumber = 0; | ||
1038 | mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; | ||
1039 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
1040 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1041 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1042 | if (r) | ||
1043 | goto out; | ||
1044 | |||
1045 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
1046 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
1047 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
1048 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
1049 | mpi_request.ExtPageLength = mpi_reply->ExtPageLength; | ||
1050 | mpi_request.ExtPageType = mpi_reply->ExtPageType; | ||
1051 | mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; | ||
1052 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
1053 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
1054 | if (r) | ||
1055 | goto out; | ||
1056 | } else { | ||
1057 | mem.config_page_dma = ioc->config_page_dma; | ||
1058 | mem.config_page = ioc->config_page; | ||
1059 | } | ||
1060 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
1061 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
1062 | mem.config_page_dma); | ||
1063 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1064 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1065 | if (!r) | ||
1066 | memcpy(config_page, mem.config_page, | ||
1067 | min_t(u16, sz, mem.config_page_sz)); | ||
1068 | |||
1069 | if (mem.config_page_sz > ioc->config_page_sz) | ||
1070 | _config_free_config_dma_memory(ioc, &mem); | ||
1071 | |||
1072 | out: | ||
1073 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1074 | return r; | ||
1075 | } | ||
1076 | |||
1077 | /** | ||
1078 | * mpt2sas_config_get_sas_iounit_pg1 - obtain sas iounit page 0 | ||
1079 | * @ioc: per adapter object | ||
1080 | * @mpi_reply: reply mf payload returned from firmware | ||
1081 | * @config_page: contents of the config page | ||
1082 | * @sz: size of buffer passed in config_page | ||
1083 | * Context: sleep. | ||
1084 | * | ||
1085 | * Calling function should call config_get_number_hba_phys prior to | ||
1086 | * this function, so enough memory is allocated for config_page. | ||
1087 | * | ||
1088 | * Returns 0 for success, non-zero for failure. | ||
1089 | */ | ||
1090 | int | ||
1091 | mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
1092 | *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz) | ||
1093 | { | ||
1094 | Mpi2ConfigRequest_t mpi_request; | ||
1095 | int r; | ||
1096 | struct config_request mem; | ||
1097 | |||
1098 | mutex_lock(&ioc->config_cmds.mutex); | ||
1099 | memset(config_page, 0, sz); | ||
1100 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
1101 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
1102 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
1103 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
1104 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | ||
1105 | mpi_request.Header.PageNumber = 1; | ||
1106 | mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; | ||
1107 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
1108 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1109 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1110 | if (r) | ||
1111 | goto out; | ||
1112 | |||
1113 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
1114 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
1115 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
1116 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
1117 | mpi_request.ExtPageLength = mpi_reply->ExtPageLength; | ||
1118 | mpi_request.ExtPageType = mpi_reply->ExtPageType; | ||
1119 | mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; | ||
1120 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
1121 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
1122 | if (r) | ||
1123 | goto out; | ||
1124 | } else { | ||
1125 | mem.config_page_dma = ioc->config_page_dma; | ||
1126 | mem.config_page = ioc->config_page; | ||
1127 | } | ||
1128 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
1129 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
1130 | mem.config_page_dma); | ||
1131 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1132 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1133 | if (!r) | ||
1134 | memcpy(config_page, mem.config_page, | ||
1135 | min_t(u16, sz, mem.config_page_sz)); | ||
1136 | |||
1137 | if (mem.config_page_sz > ioc->config_page_sz) | ||
1138 | _config_free_config_dma_memory(ioc, &mem); | ||
1139 | |||
1140 | out: | ||
1141 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1142 | return r; | ||
1143 | } | ||
1144 | |||
1145 | /** | ||
1146 | * mpt2sas_config_get_expander_pg0 - obtain expander page 0 | ||
1147 | * @ioc: per adapter object | ||
1148 | * @mpi_reply: reply mf payload returned from firmware | ||
1149 | * @config_page: contents of the config page | ||
1150 | * @form: GET_NEXT_HANDLE or HANDLE | ||
1151 | * @handle: expander handle | ||
1152 | * Context: sleep. | ||
1153 | * | ||
1154 | * Returns 0 for success, non-zero for failure. | ||
1155 | */ | ||
1156 | int | ||
1157 | mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
1158 | *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle) | ||
1159 | { | ||
1160 | Mpi2ConfigRequest_t mpi_request; | ||
1161 | int r; | ||
1162 | struct config_request mem; | ||
1163 | |||
1164 | mutex_lock(&ioc->config_cmds.mutex); | ||
1165 | memset(config_page, 0, sizeof(Mpi2ExpanderPage0_t)); | ||
1166 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
1167 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
1168 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
1169 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
1170 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; | ||
1171 | mpi_request.Header.PageNumber = 0; | ||
1172 | mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION; | ||
1173 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
1174 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1175 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1176 | if (r) | ||
1177 | goto out; | ||
1178 | |||
1179 | mpi_request.PageAddress = cpu_to_le32(form | handle); | ||
1180 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
1181 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
1182 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
1183 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
1184 | mpi_request.ExtPageLength = mpi_reply->ExtPageLength; | ||
1185 | mpi_request.ExtPageType = mpi_reply->ExtPageType; | ||
1186 | mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; | ||
1187 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
1188 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
1189 | if (r) | ||
1190 | goto out; | ||
1191 | } else { | ||
1192 | mem.config_page_dma = ioc->config_page_dma; | ||
1193 | mem.config_page = ioc->config_page; | ||
1194 | } | ||
1195 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
1196 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
1197 | mem.config_page_dma); | ||
1198 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1199 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1200 | if (!r) | ||
1201 | memcpy(config_page, mem.config_page, | ||
1202 | min_t(u16, mem.config_page_sz, | ||
1203 | sizeof(Mpi2ExpanderPage0_t))); | ||
1204 | |||
1205 | if (mem.config_page_sz > ioc->config_page_sz) | ||
1206 | _config_free_config_dma_memory(ioc, &mem); | ||
1207 | |||
1208 | out: | ||
1209 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1210 | return r; | ||
1211 | } | ||
1212 | |||
1213 | /** | ||
1214 | * mpt2sas_config_get_expander_pg1 - obtain expander page 1 | ||
1215 | * @ioc: per adapter object | ||
1216 | * @mpi_reply: reply mf payload returned from firmware | ||
1217 | * @config_page: contents of the config page | ||
1218 | * @phy_number: phy number | ||
1219 | * @handle: expander handle | ||
1220 | * Context: sleep. | ||
1221 | * | ||
1222 | * Returns 0 for success, non-zero for failure. | ||
1223 | */ | ||
1224 | int | ||
1225 | mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
1226 | *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number, | ||
1227 | u16 handle) | ||
1228 | { | ||
1229 | Mpi2ConfigRequest_t mpi_request; | ||
1230 | int r; | ||
1231 | struct config_request mem; | ||
1232 | |||
1233 | mutex_lock(&ioc->config_cmds.mutex); | ||
1234 | memset(config_page, 0, sizeof(Mpi2ExpanderPage1_t)); | ||
1235 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
1236 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
1237 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
1238 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
1239 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; | ||
1240 | mpi_request.Header.PageNumber = 1; | ||
1241 | mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION; | ||
1242 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
1243 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1244 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1245 | if (r) | ||
1246 | goto out; | ||
1247 | |||
1248 | mpi_request.PageAddress = | ||
1249 | cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM | | ||
1250 | (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle); | ||
1251 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
1252 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
1253 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
1254 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
1255 | mpi_request.ExtPageLength = mpi_reply->ExtPageLength; | ||
1256 | mpi_request.ExtPageType = mpi_reply->ExtPageType; | ||
1257 | mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; | ||
1258 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
1259 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
1260 | if (r) | ||
1261 | goto out; | ||
1262 | } else { | ||
1263 | mem.config_page_dma = ioc->config_page_dma; | ||
1264 | mem.config_page = ioc->config_page; | ||
1265 | } | ||
1266 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
1267 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
1268 | mem.config_page_dma); | ||
1269 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1270 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1271 | if (!r) | ||
1272 | memcpy(config_page, mem.config_page, | ||
1273 | min_t(u16, mem.config_page_sz, | ||
1274 | sizeof(Mpi2ExpanderPage1_t))); | ||
1275 | |||
1276 | if (mem.config_page_sz > ioc->config_page_sz) | ||
1277 | _config_free_config_dma_memory(ioc, &mem); | ||
1278 | |||
1279 | out: | ||
1280 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1281 | return r; | ||
1282 | } | ||
1283 | |||
1284 | /** | ||
1285 | * mpt2sas_config_get_enclosure_pg0 - obtain enclosure page 0 | ||
1286 | * @ioc: per adapter object | ||
1287 | * @mpi_reply: reply mf payload returned from firmware | ||
1288 | * @config_page: contents of the config page | ||
1289 | * @form: GET_NEXT_HANDLE or HANDLE | ||
1290 | * @handle: expander handle | ||
1291 | * Context: sleep. | ||
1292 | * | ||
1293 | * Returns 0 for success, non-zero for failure. | ||
1294 | */ | ||
1295 | int | ||
1296 | mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
1297 | *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle) | ||
1298 | { | ||
1299 | Mpi2ConfigRequest_t mpi_request; | ||
1300 | int r; | ||
1301 | struct config_request mem; | ||
1302 | |||
1303 | mutex_lock(&ioc->config_cmds.mutex); | ||
1304 | memset(config_page, 0, sizeof(Mpi2SasEnclosurePage0_t)); | ||
1305 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
1306 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
1307 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
1308 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
1309 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE; | ||
1310 | mpi_request.Header.PageNumber = 0; | ||
1311 | mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION; | ||
1312 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
1313 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1314 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1315 | if (r) | ||
1316 | goto out; | ||
1317 | |||
1318 | mpi_request.PageAddress = cpu_to_le32(form | handle); | ||
1319 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
1320 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
1321 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
1322 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
1323 | mpi_request.ExtPageLength = mpi_reply->ExtPageLength; | ||
1324 | mpi_request.ExtPageType = mpi_reply->ExtPageType; | ||
1325 | mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; | ||
1326 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
1327 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
1328 | if (r) | ||
1329 | goto out; | ||
1330 | } else { | ||
1331 | mem.config_page_dma = ioc->config_page_dma; | ||
1332 | mem.config_page = ioc->config_page; | ||
1333 | } | ||
1334 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
1335 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
1336 | mem.config_page_dma); | ||
1337 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1338 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1339 | if (!r) | ||
1340 | memcpy(config_page, mem.config_page, | ||
1341 | min_t(u16, mem.config_page_sz, | ||
1342 | sizeof(Mpi2SasEnclosurePage0_t))); | ||
1343 | |||
1344 | if (mem.config_page_sz > ioc->config_page_sz) | ||
1345 | _config_free_config_dma_memory(ioc, &mem); | ||
1346 | |||
1347 | out: | ||
1348 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1349 | return r; | ||
1350 | } | ||
1351 | |||
1352 | /** | ||
1353 | * mpt2sas_config_get_phy_pg0 - obtain phy page 0 | ||
1354 | * @ioc: per adapter object | ||
1355 | * @mpi_reply: reply mf payload returned from firmware | ||
1356 | * @config_page: contents of the config page | ||
1357 | * @phy_number: phy number | ||
1358 | * Context: sleep. | ||
1359 | * | ||
1360 | * Returns 0 for success, non-zero for failure. | ||
1361 | */ | ||
1362 | int | ||
1363 | mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
1364 | *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number) | ||
1365 | { | ||
1366 | Mpi2ConfigRequest_t mpi_request; | ||
1367 | int r; | ||
1368 | struct config_request mem; | ||
1369 | |||
1370 | mutex_lock(&ioc->config_cmds.mutex); | ||
1371 | memset(config_page, 0, sizeof(Mpi2SasPhyPage0_t)); | ||
1372 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
1373 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
1374 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
1375 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
1376 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; | ||
1377 | mpi_request.Header.PageNumber = 0; | ||
1378 | mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION; | ||
1379 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
1380 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1381 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1382 | if (r) | ||
1383 | goto out; | ||
1384 | |||
1385 | mpi_request.PageAddress = | ||
1386 | cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); | ||
1387 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
1388 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
1389 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
1390 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
1391 | mpi_request.ExtPageLength = mpi_reply->ExtPageLength; | ||
1392 | mpi_request.ExtPageType = mpi_reply->ExtPageType; | ||
1393 | mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; | ||
1394 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
1395 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
1396 | if (r) | ||
1397 | goto out; | ||
1398 | } else { | ||
1399 | mem.config_page_dma = ioc->config_page_dma; | ||
1400 | mem.config_page = ioc->config_page; | ||
1401 | } | ||
1402 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
1403 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
1404 | mem.config_page_dma); | ||
1405 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1406 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1407 | if (!r) | ||
1408 | memcpy(config_page, mem.config_page, | ||
1409 | min_t(u16, mem.config_page_sz, | ||
1410 | sizeof(Mpi2SasPhyPage0_t))); | ||
1411 | |||
1412 | if (mem.config_page_sz > ioc->config_page_sz) | ||
1413 | _config_free_config_dma_memory(ioc, &mem); | ||
1414 | |||
1415 | out: | ||
1416 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1417 | return r; | ||
1418 | } | ||
1419 | |||
1420 | /** | ||
1421 | * mpt2sas_config_get_phy_pg1 - obtain phy page 1 | ||
1422 | * @ioc: per adapter object | ||
1423 | * @mpi_reply: reply mf payload returned from firmware | ||
1424 | * @config_page: contents of the config page | ||
1425 | * @phy_number: phy number | ||
1426 | * Context: sleep. | ||
1427 | * | ||
1428 | * Returns 0 for success, non-zero for failure. | ||
1429 | */ | ||
1430 | int | ||
1431 | mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
1432 | *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number) | ||
1433 | { | ||
1434 | Mpi2ConfigRequest_t mpi_request; | ||
1435 | int r; | ||
1436 | struct config_request mem; | ||
1437 | |||
1438 | mutex_lock(&ioc->config_cmds.mutex); | ||
1439 | memset(config_page, 0, sizeof(Mpi2SasPhyPage1_t)); | ||
1440 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
1441 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
1442 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
1443 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
1444 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; | ||
1445 | mpi_request.Header.PageNumber = 1; | ||
1446 | mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION; | ||
1447 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
1448 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1449 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1450 | if (r) | ||
1451 | goto out; | ||
1452 | |||
1453 | mpi_request.PageAddress = | ||
1454 | cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); | ||
1455 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
1456 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
1457 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
1458 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
1459 | mpi_request.ExtPageLength = mpi_reply->ExtPageLength; | ||
1460 | mpi_request.ExtPageType = mpi_reply->ExtPageType; | ||
1461 | mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; | ||
1462 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
1463 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
1464 | if (r) | ||
1465 | goto out; | ||
1466 | } else { | ||
1467 | mem.config_page_dma = ioc->config_page_dma; | ||
1468 | mem.config_page = ioc->config_page; | ||
1469 | } | ||
1470 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
1471 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
1472 | mem.config_page_dma); | ||
1473 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1474 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1475 | if (!r) | ||
1476 | memcpy(config_page, mem.config_page, | ||
1477 | min_t(u16, mem.config_page_sz, | ||
1478 | sizeof(Mpi2SasPhyPage1_t))); | ||
1479 | |||
1480 | if (mem.config_page_sz > ioc->config_page_sz) | ||
1481 | _config_free_config_dma_memory(ioc, &mem); | ||
1482 | |||
1483 | out: | ||
1484 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1485 | return r; | ||
1486 | } | ||
1487 | |||
1488 | /** | ||
1489 | * mpt2sas_config_get_raid_volume_pg1 - obtain raid volume page 1 | ||
1490 | * @ioc: per adapter object | ||
1491 | * @mpi_reply: reply mf payload returned from firmware | ||
1492 | * @config_page: contents of the config page | ||
1493 | * @form: GET_NEXT_HANDLE or HANDLE | ||
1494 | * @handle: volume handle | ||
1495 | * Context: sleep. | ||
1496 | * | ||
1497 | * Returns 0 for success, non-zero for failure. | ||
1498 | */ | ||
1499 | int | ||
1500 | mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, | ||
1501 | Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, | ||
1502 | u32 handle) | ||
1503 | { | ||
1504 | Mpi2ConfigRequest_t mpi_request; | ||
1505 | int r; | ||
1506 | struct config_request mem; | ||
1507 | |||
1508 | mutex_lock(&ioc->config_cmds.mutex); | ||
1509 | memset(config_page, 0, sizeof(Mpi2RaidVolPage1_t)); | ||
1510 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
1511 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
1512 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
1513 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; | ||
1514 | mpi_request.Header.PageNumber = 1; | ||
1515 | mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; | ||
1516 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
1517 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1518 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1519 | if (r) | ||
1520 | goto out; | ||
1521 | |||
1522 | mpi_request.PageAddress = cpu_to_le32(form | handle); | ||
1523 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
1524 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
1525 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
1526 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
1527 | mpi_request.Header.PageLength = mpi_reply->Header.PageLength; | ||
1528 | mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; | ||
1529 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
1530 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
1531 | if (r) | ||
1532 | goto out; | ||
1533 | } else { | ||
1534 | mem.config_page_dma = ioc->config_page_dma; | ||
1535 | mem.config_page = ioc->config_page; | ||
1536 | } | ||
1537 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
1538 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
1539 | mem.config_page_dma); | ||
1540 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1541 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1542 | if (!r) | ||
1543 | memcpy(config_page, mem.config_page, | ||
1544 | min_t(u16, mem.config_page_sz, | ||
1545 | sizeof(Mpi2RaidVolPage1_t))); | ||
1546 | |||
1547 | if (mem.config_page_sz > ioc->config_page_sz) | ||
1548 | _config_free_config_dma_memory(ioc, &mem); | ||
1549 | |||
1550 | out: | ||
1551 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1552 | return r; | ||
1553 | } | ||
1554 | |||
1555 | /** | ||
1556 | * mpt2sas_config_get_number_pds - obtain number of phys disk assigned to volume | ||
1557 | * @ioc: per adapter object | ||
1558 | * @handle: volume handle | ||
1559 | * @num_pds: returns pds count | ||
1560 | * Context: sleep. | ||
1561 | * | ||
1562 | * Returns 0 for success, non-zero for failure. | ||
1563 | */ | ||
1564 | int | ||
1565 | mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, | ||
1566 | u8 *num_pds) | ||
1567 | { | ||
1568 | Mpi2ConfigRequest_t mpi_request; | ||
1569 | Mpi2RaidVolPage0_t *config_page; | ||
1570 | Mpi2ConfigReply_t mpi_reply; | ||
1571 | int r; | ||
1572 | struct config_request mem; | ||
1573 | u16 ioc_status; | ||
1574 | |||
1575 | mutex_lock(&ioc->config_cmds.mutex); | ||
1576 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
1577 | *num_pds = 0; | ||
1578 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
1579 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
1580 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; | ||
1581 | mpi_request.Header.PageNumber = 0; | ||
1582 | mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; | ||
1583 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
1584 | r = _config_request(ioc, &mpi_request, &mpi_reply, | ||
1585 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1586 | if (r) | ||
1587 | goto out; | ||
1588 | |||
1589 | mpi_request.PageAddress = | ||
1590 | cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle); | ||
1591 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
1592 | mpi_request.Header.PageVersion = mpi_reply.Header.PageVersion; | ||
1593 | mpi_request.Header.PageNumber = mpi_reply.Header.PageNumber; | ||
1594 | mpi_request.Header.PageType = mpi_reply.Header.PageType; | ||
1595 | mpi_request.Header.PageLength = mpi_reply.Header.PageLength; | ||
1596 | mem.config_page_sz = le16_to_cpu(mpi_reply.Header.PageLength) * 4; | ||
1597 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
1598 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
1599 | if (r) | ||
1600 | goto out; | ||
1601 | } else { | ||
1602 | mem.config_page_dma = ioc->config_page_dma; | ||
1603 | mem.config_page = ioc->config_page; | ||
1604 | } | ||
1605 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
1606 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
1607 | mem.config_page_dma); | ||
1608 | r = _config_request(ioc, &mpi_request, &mpi_reply, | ||
1609 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1610 | if (!r) { | ||
1611 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
1612 | MPI2_IOCSTATUS_MASK; | ||
1613 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { | ||
1614 | config_page = mem.config_page; | ||
1615 | *num_pds = config_page->NumPhysDisks; | ||
1616 | } | ||
1617 | } | ||
1618 | |||
1619 | if (mem.config_page_sz > ioc->config_page_sz) | ||
1620 | _config_free_config_dma_memory(ioc, &mem); | ||
1621 | |||
1622 | out: | ||
1623 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1624 | return r; | ||
1625 | } | ||
1626 | |||
1627 | /** | ||
1628 | * mpt2sas_config_get_raid_volume_pg0 - obtain raid volume page 0 | ||
1629 | * @ioc: per adapter object | ||
1630 | * @mpi_reply: reply mf payload returned from firmware | ||
1631 | * @config_page: contents of the config page | ||
1632 | * @form: GET_NEXT_HANDLE or HANDLE | ||
1633 | * @handle: volume handle | ||
1634 | * @sz: size of buffer passed in config_page | ||
1635 | * Context: sleep. | ||
1636 | * | ||
1637 | * Returns 0 for success, non-zero for failure. | ||
1638 | */ | ||
1639 | int | ||
1640 | mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, | ||
1641 | Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, | ||
1642 | u32 handle, u16 sz) | ||
1643 | { | ||
1644 | Mpi2ConfigRequest_t mpi_request; | ||
1645 | int r; | ||
1646 | struct config_request mem; | ||
1647 | |||
1648 | mutex_lock(&ioc->config_cmds.mutex); | ||
1649 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
1650 | memset(config_page, 0, sz); | ||
1651 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
1652 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
1653 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; | ||
1654 | mpi_request.Header.PageNumber = 0; | ||
1655 | mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; | ||
1656 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
1657 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1658 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1659 | if (r) | ||
1660 | goto out; | ||
1661 | |||
1662 | mpi_request.PageAddress = cpu_to_le32(form | handle); | ||
1663 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
1664 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
1665 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
1666 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
1667 | mpi_request.Header.PageLength = mpi_reply->Header.PageLength; | ||
1668 | mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; | ||
1669 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
1670 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
1671 | if (r) | ||
1672 | goto out; | ||
1673 | } else { | ||
1674 | mem.config_page_dma = ioc->config_page_dma; | ||
1675 | mem.config_page = ioc->config_page; | ||
1676 | } | ||
1677 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
1678 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
1679 | mem.config_page_dma); | ||
1680 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1681 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1682 | if (!r) | ||
1683 | memcpy(config_page, mem.config_page, | ||
1684 | min_t(u16, sz, mem.config_page_sz)); | ||
1685 | |||
1686 | if (mem.config_page_sz > ioc->config_page_sz) | ||
1687 | _config_free_config_dma_memory(ioc, &mem); | ||
1688 | |||
1689 | out: | ||
1690 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1691 | return r; | ||
1692 | } | ||
1693 | |||
1694 | /** | ||
1695 | * mpt2sas_config_get_phys_disk_pg0 - obtain phys disk page 0 | ||
1696 | * @ioc: per adapter object | ||
1697 | * @mpi_reply: reply mf payload returned from firmware | ||
1698 | * @config_page: contents of the config page | ||
1699 | * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE | ||
1700 | * @form_specific: specific to the form | ||
1701 | * Context: sleep. | ||
1702 | * | ||
1703 | * Returns 0 for success, non-zero for failure. | ||
1704 | */ | ||
1705 | int | ||
1706 | mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | ||
1707 | *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form, | ||
1708 | u32 form_specific) | ||
1709 | { | ||
1710 | Mpi2ConfigRequest_t mpi_request; | ||
1711 | int r; | ||
1712 | struct config_request mem; | ||
1713 | |||
1714 | mutex_lock(&ioc->config_cmds.mutex); | ||
1715 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
1716 | memset(config_page, 0, sizeof(Mpi2RaidPhysDiskPage0_t)); | ||
1717 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
1718 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
1719 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; | ||
1720 | mpi_request.Header.PageNumber = 0; | ||
1721 | mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; | ||
1722 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
1723 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1724 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1725 | if (r) | ||
1726 | goto out; | ||
1727 | |||
1728 | mpi_request.PageAddress = cpu_to_le32(form | form_specific); | ||
1729 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
1730 | mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion; | ||
1731 | mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber; | ||
1732 | mpi_request.Header.PageType = mpi_reply->Header.PageType; | ||
1733 | mpi_request.Header.PageLength = mpi_reply->Header.PageLength; | ||
1734 | mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4; | ||
1735 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
1736 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
1737 | if (r) | ||
1738 | goto out; | ||
1739 | } else { | ||
1740 | mem.config_page_dma = ioc->config_page_dma; | ||
1741 | mem.config_page = ioc->config_page; | ||
1742 | } | ||
1743 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
1744 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
1745 | mem.config_page_dma); | ||
1746 | r = _config_request(ioc, &mpi_request, mpi_reply, | ||
1747 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1748 | if (!r) | ||
1749 | memcpy(config_page, mem.config_page, | ||
1750 | min_t(u16, mem.config_page_sz, | ||
1751 | sizeof(Mpi2RaidPhysDiskPage0_t))); | ||
1752 | |||
1753 | if (mem.config_page_sz > ioc->config_page_sz) | ||
1754 | _config_free_config_dma_memory(ioc, &mem); | ||
1755 | |||
1756 | out: | ||
1757 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1758 | return r; | ||
1759 | } | ||
1760 | |||
1761 | /** | ||
1762 | * mpt2sas_config_get_volume_handle - returns volume handle for give hidden raid components | ||
1763 | * @ioc: per adapter object | ||
1764 | * @pd_handle: phys disk handle | ||
1765 | * @volume_handle: volume handle | ||
1766 | * Context: sleep. | ||
1767 | * | ||
1768 | * Returns 0 for success, non-zero for failure. | ||
1769 | */ | ||
1770 | int | ||
1771 | mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle, | ||
1772 | u16 *volume_handle) | ||
1773 | { | ||
1774 | Mpi2RaidConfigurationPage0_t *config_page; | ||
1775 | Mpi2ConfigRequest_t mpi_request; | ||
1776 | Mpi2ConfigReply_t mpi_reply; | ||
1777 | int r, i; | ||
1778 | struct config_request mem; | ||
1779 | u16 ioc_status; | ||
1780 | |||
1781 | mutex_lock(&ioc->config_cmds.mutex); | ||
1782 | *volume_handle = 0; | ||
1783 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | ||
1784 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | ||
1785 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||
1786 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||
1787 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG; | ||
1788 | mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION; | ||
1789 | mpi_request.Header.PageNumber = 0; | ||
1790 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | ||
1791 | r = _config_request(ioc, &mpi_request, &mpi_reply, | ||
1792 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1793 | if (r) | ||
1794 | goto out; | ||
1795 | |||
1796 | mpi_request.PageAddress = | ||
1797 | cpu_to_le32(MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG); | ||
1798 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
1799 | mpi_request.Header.PageVersion = mpi_reply.Header.PageVersion; | ||
1800 | mpi_request.Header.PageNumber = mpi_reply.Header.PageNumber; | ||
1801 | mpi_request.Header.PageType = mpi_reply.Header.PageType; | ||
1802 | mpi_request.ExtPageLength = mpi_reply.ExtPageLength; | ||
1803 | mpi_request.ExtPageType = mpi_reply.ExtPageType; | ||
1804 | mem.config_page_sz = le16_to_cpu(mpi_reply.ExtPageLength) * 4; | ||
1805 | if (mem.config_page_sz > ioc->config_page_sz) { | ||
1806 | r = _config_alloc_config_dma_memory(ioc, &mem); | ||
1807 | if (r) | ||
1808 | goto out; | ||
1809 | } else { | ||
1810 | mem.config_page_dma = ioc->config_page_dma; | ||
1811 | mem.config_page = ioc->config_page; | ||
1812 | } | ||
1813 | ioc->base_add_sg_single(&mpi_request.PageBufferSGE, | ||
1814 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz, | ||
1815 | mem.config_page_dma); | ||
1816 | r = _config_request(ioc, &mpi_request, &mpi_reply, | ||
1817 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT); | ||
1818 | if (r) | ||
1819 | goto out; | ||
1820 | |||
1821 | r = -1; | ||
1822 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
1823 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | ||
1824 | goto done; | ||
1825 | config_page = mem.config_page; | ||
1826 | for (i = 0; i < config_page->NumElements; i++) { | ||
1827 | if ((config_page->ConfigElement[i].ElementFlags & | ||
1828 | MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE) != | ||
1829 | MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT) | ||
1830 | continue; | ||
1831 | if (config_page->ConfigElement[i].PhysDiskDevHandle == | ||
1832 | pd_handle) { | ||
1833 | *volume_handle = le16_to_cpu(config_page-> | ||
1834 | ConfigElement[i].VolDevHandle); | ||
1835 | r = 0; | ||
1836 | goto done; | ||
1837 | } | ||
1838 | } | ||
1839 | |||
1840 | done: | ||
1841 | if (mem.config_page_sz > ioc->config_page_sz) | ||
1842 | _config_free_config_dma_memory(ioc, &mem); | ||
1843 | |||
1844 | out: | ||
1845 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1846 | return r; | ||
1847 | } | ||
1848 | |||
1849 | /** | ||
1850 | * mpt2sas_config_get_volume_wwid - returns wwid given the volume handle | ||
1851 | * @ioc: per adapter object | ||
1852 | * @volume_handle: volume handle | ||
1853 | * @wwid: volume wwid | ||
1854 | * Context: sleep. | ||
1855 | * | ||
1856 | * Returns 0 for success, non-zero for failure. | ||
1857 | */ | ||
1858 | int | ||
1859 | mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle, | ||
1860 | u64 *wwid) | ||
1861 | { | ||
1862 | Mpi2ConfigReply_t mpi_reply; | ||
1863 | Mpi2RaidVolPage1_t raid_vol_pg1; | ||
1864 | |||
1865 | *wwid = 0; | ||
1866 | if (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, | ||
1867 | &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, | ||
1868 | volume_handle))) { | ||
1869 | *wwid = le64_to_cpu(raid_vol_pg1.WWID); | ||
1870 | return 0; | ||
1871 | } else | ||
1872 | return -1; | ||
1873 | } | ||