Commit | Line | Data |
---|---|---|
f92363d1 SR |
1 | /* |
2 | * This module provides common API for accessing firmware configuration pages | |
3 | * | |
4 | * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c | |
a4ffce0d | 5 | * Copyright (C) 2012-2014 LSI Corporation |
f92363d1 SR |
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 | ||
f92363d1 SR |
44 | #include <linux/module.h> |
45 | #include <linux/kernel.h> | |
46 | #include <linux/init.h> | |
47 | #include <linux/errno.h> | |
48 | #include <linux/blkdev.h> | |
49 | #include <linux/sched.h> | |
50 | #include <linux/workqueue.h> | |
51 | #include <linux/delay.h> | |
52 | #include <linux/pci.h> | |
53 | ||
54 | #include "mpt3sas_base.h" | |
55 | ||
56 | /* local definitions */ | |
57 | ||
58 | /* Timeout for config page request (in seconds) */ | |
59 | #define MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT 15 | |
60 | ||
61 | /* Common sgl flags for READING a config page. */ | |
62 | #define MPT3_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \ | |
63 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \ | |
64 | | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT) | |
65 | ||
66 | /* Common sgl flags for WRITING a config page. */ | |
67 | #define MPT3_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \ | |
68 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \ | |
69 | | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \ | |
70 | << MPI2_SGE_FLAGS_SHIFT) | |
71 | ||
72 | /** | |
73 | * struct config_request - obtain dma memory via routine | |
74 | * @sz: size | |
75 | * @page: virt pointer | |
76 | * @page_dma: phys pointer | |
77 | * | |
78 | */ | |
79 | struct config_request { | |
80 | u16 sz; | |
81 | void *page; | |
82 | dma_addr_t page_dma; | |
83 | }; | |
84 | ||
85 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | |
86 | /** | |
87 | * _config_display_some_debug - debug routine | |
88 | * @ioc: per adapter object | |
89 | * @smid: system request message index | |
90 | * @calling_function_name: string pass from calling function | |
91 | * @mpi_reply: reply message frame | |
92 | * Context: none. | |
93 | * | |
94 | * Function for displaying debug info helpful when debugging issues | |
95 | * in this module. | |
96 | */ | |
97 | static void | |
98 | _config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid, | |
99 | char *calling_function_name, MPI2DefaultReply_t *mpi_reply) | |
100 | { | |
101 | Mpi2ConfigRequest_t *mpi_request; | |
102 | char *desc = NULL; | |
103 | ||
104 | if (!(ioc->logging_level & MPT_DEBUG_CONFIG)) | |
105 | return; | |
106 | ||
107 | mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); | |
108 | switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) { | |
109 | case MPI2_CONFIG_PAGETYPE_IO_UNIT: | |
110 | desc = "io_unit"; | |
111 | break; | |
112 | case MPI2_CONFIG_PAGETYPE_IOC: | |
113 | desc = "ioc"; | |
114 | break; | |
115 | case MPI2_CONFIG_PAGETYPE_BIOS: | |
116 | desc = "bios"; | |
117 | break; | |
118 | case MPI2_CONFIG_PAGETYPE_RAID_VOLUME: | |
119 | desc = "raid_volume"; | |
120 | break; | |
121 | case MPI2_CONFIG_PAGETYPE_MANUFACTURING: | |
122 | desc = "manufaucturing"; | |
123 | break; | |
124 | case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK: | |
125 | desc = "physdisk"; | |
126 | break; | |
127 | case MPI2_CONFIG_PAGETYPE_EXTENDED: | |
128 | switch (mpi_request->ExtPageType) { | |
129 | case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT: | |
130 | desc = "sas_io_unit"; | |
131 | break; | |
132 | case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER: | |
133 | desc = "sas_expander"; | |
134 | break; | |
135 | case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE: | |
136 | desc = "sas_device"; | |
137 | break; | |
138 | case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY: | |
139 | desc = "sas_phy"; | |
140 | break; | |
141 | case MPI2_CONFIG_EXTPAGETYPE_LOG: | |
142 | desc = "log"; | |
143 | break; | |
144 | case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE: | |
145 | desc = "enclosure"; | |
146 | break; | |
147 | case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG: | |
148 | desc = "raid_config"; | |
149 | break; | |
150 | case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING: | |
07f42258 | 151 | desc = "driver_mapping"; |
f92363d1 SR |
152 | break; |
153 | } | |
154 | break; | |
155 | } | |
156 | ||
157 | if (!desc) | |
158 | return; | |
159 | ||
160 | pr_info(MPT3SAS_FMT | |
161 | "%s: %s(%d), action(%d), form(0x%08x), smid(%d)\n", | |
162 | 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 | pr_info(MPT3SAS_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 | * _config_alloc_config_dma_memory - obtain physical memory | |
179 | * @ioc: per adapter object | |
180 | * @mem: struct config_request | |
181 | * | |
182 | * A wrapper for obtaining dma-able memory for config page request. | |
183 | * | |
184 | * Returns 0 for success, non-zero for failure. | |
185 | */ | |
186 | static int | |
187 | _config_alloc_config_dma_memory(struct MPT3SAS_ADAPTER *ioc, | |
188 | struct config_request *mem) | |
189 | { | |
190 | int r = 0; | |
191 | ||
192 | if (mem->sz > ioc->config_page_sz) { | |
193 | mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz, | |
194 | &mem->page_dma, GFP_KERNEL); | |
195 | if (!mem->page) { | |
196 | pr_err(MPT3SAS_FMT | |
197 | "%s: dma_alloc_coherent failed asking for (%d) bytes!!\n", | |
198 | ioc->name, __func__, mem->sz); | |
199 | r = -ENOMEM; | |
200 | } | |
201 | } else { /* use tmp buffer if less than 512 bytes */ | |
202 | mem->page = ioc->config_page; | |
203 | mem->page_dma = ioc->config_page_dma; | |
204 | } | |
205 | return r; | |
206 | } | |
207 | ||
208 | /** | |
209 | * _config_free_config_dma_memory - wrapper to free the memory | |
210 | * @ioc: per adapter object | |
211 | * @mem: struct config_request | |
212 | * | |
213 | * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory. | |
214 | * | |
215 | * Returns 0 for success, non-zero for failure. | |
216 | */ | |
217 | static void | |
218 | _config_free_config_dma_memory(struct MPT3SAS_ADAPTER *ioc, | |
219 | struct config_request *mem) | |
220 | { | |
221 | if (mem->sz > ioc->config_page_sz) | |
222 | dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page, | |
223 | mem->page_dma); | |
224 | } | |
225 | ||
226 | /** | |
227 | * mpt3sas_config_done - config page completion routine | |
228 | * @ioc: per adapter object | |
229 | * @smid: system request message index | |
230 | * @msix_index: MSIX table index supplied by the OS | |
231 | * @reply: reply message frame(lower 32bit addr) | |
232 | * Context: none. | |
233 | * | |
234 | * The callback handler when using _config_request. | |
235 | * | |
236 | * Return 1 meaning mf should be freed from _base_interrupt | |
237 | * 0 means the mf is freed from this function. | |
238 | */ | |
239 | u8 | |
240 | mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |
241 | u32 reply) | |
242 | { | |
243 | MPI2DefaultReply_t *mpi_reply; | |
244 | ||
245 | if (ioc->config_cmds.status == MPT3_CMD_NOT_USED) | |
246 | return 1; | |
247 | if (ioc->config_cmds.smid != smid) | |
248 | return 1; | |
249 | ioc->config_cmds.status |= MPT3_CMD_COMPLETE; | |
250 | mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); | |
251 | if (mpi_reply) { | |
252 | ioc->config_cmds.status |= MPT3_CMD_REPLY_VALID; | |
253 | memcpy(ioc->config_cmds.reply, mpi_reply, | |
254 | mpi_reply->MsgLength*4); | |
255 | } | |
256 | ioc->config_cmds.status &= ~MPT3_CMD_PENDING; | |
257 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | |
258 | _config_display_some_debug(ioc, smid, "config_done", mpi_reply); | |
259 | #endif | |
260 | ioc->config_cmds.smid = USHRT_MAX; | |
261 | complete(&ioc->config_cmds.done); | |
262 | return 1; | |
263 | } | |
264 | ||
265 | /** | |
266 | * _config_request - main routine for sending config page requests | |
267 | * @ioc: per adapter object | |
268 | * @mpi_request: request message frame | |
269 | * @mpi_reply: reply mf payload returned from firmware | |
270 | * @timeout: timeout in seconds | |
271 | * @config_page: contents of the config page | |
272 | * @config_page_sz: size of config page | |
273 | * Context: sleep | |
274 | * | |
275 | * A generic API for config page requests to firmware. | |
276 | * | |
277 | * The ioc->config_cmds.status flag should be MPT3_CMD_NOT_USED before calling | |
278 | * this API. | |
279 | * | |
280 | * The callback index is set inside `ioc->config_cb_idx. | |
281 | * | |
282 | * Returns 0 for success, non-zero for failure. | |
283 | */ | |
284 | static int | |
285 | _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t | |
286 | *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout, | |
287 | void *config_page, u16 config_page_sz) | |
288 | { | |
289 | u16 smid; | |
290 | u32 ioc_state; | |
291 | unsigned long timeleft; | |
292 | Mpi2ConfigRequest_t *config_request; | |
293 | int r; | |
294 | u8 retry_count, issue_host_reset = 0; | |
295 | u16 wait_state_count; | |
296 | struct config_request mem; | |
297 | u32 ioc_status = UINT_MAX; | |
298 | ||
299 | mutex_lock(&ioc->config_cmds.mutex); | |
300 | if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) { | |
301 | pr_err(MPT3SAS_FMT "%s: config_cmd in use\n", | |
302 | ioc->name, __func__); | |
303 | mutex_unlock(&ioc->config_cmds.mutex); | |
304 | return -EAGAIN; | |
305 | } | |
306 | ||
307 | retry_count = 0; | |
308 | memset(&mem, 0, sizeof(struct config_request)); | |
309 | ||
310 | mpi_request->VF_ID = 0; /* TODO */ | |
311 | mpi_request->VP_ID = 0; | |
312 | ||
313 | if (config_page) { | |
314 | mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion; | |
315 | mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber; | |
316 | mpi_request->Header.PageType = mpi_reply->Header.PageType; | |
317 | mpi_request->Header.PageLength = mpi_reply->Header.PageLength; | |
318 | mpi_request->ExtPageLength = mpi_reply->ExtPageLength; | |
319 | mpi_request->ExtPageType = mpi_reply->ExtPageType; | |
320 | if (mpi_request->Header.PageLength) | |
321 | mem.sz = mpi_request->Header.PageLength * 4; | |
322 | else | |
323 | mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; | |
324 | r = _config_alloc_config_dma_memory(ioc, &mem); | |
325 | if (r != 0) | |
326 | goto out; | |
327 | if (mpi_request->Action == | |
328 | MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT || | |
329 | mpi_request->Action == | |
330 | MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) { | |
331 | ioc->base_add_sg_single(&mpi_request->PageBufferSGE, | |
332 | MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz, | |
333 | mem.page_dma); | |
334 | memcpy(mem.page, config_page, min_t(u16, mem.sz, | |
335 | config_page_sz)); | |
336 | } else { | |
337 | memset(config_page, 0, config_page_sz); | |
338 | ioc->base_add_sg_single(&mpi_request->PageBufferSGE, | |
339 | MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma); | |
340 | memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz)); | |
341 | } | |
342 | } | |
343 | ||
344 | retry_config: | |
345 | if (retry_count) { | |
346 | if (retry_count > 2) { /* attempt only 2 retries */ | |
347 | r = -EFAULT; | |
348 | goto free_mem; | |
349 | } | |
350 | pr_info(MPT3SAS_FMT "%s: attempting retry (%d)\n", | |
351 | ioc->name, __func__, retry_count); | |
352 | } | |
353 | wait_state_count = 0; | |
354 | ioc_state = mpt3sas_base_get_iocstate(ioc, 1); | |
355 | while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | |
356 | if (wait_state_count++ == MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT) { | |
357 | pr_err(MPT3SAS_FMT | |
358 | "%s: failed due to ioc not operational\n", | |
359 | ioc->name, __func__); | |
360 | ioc->config_cmds.status = MPT3_CMD_NOT_USED; | |
361 | r = -EFAULT; | |
362 | goto free_mem; | |
363 | } | |
364 | ssleep(1); | |
365 | ioc_state = mpt3sas_base_get_iocstate(ioc, 1); | |
366 | pr_info(MPT3SAS_FMT | |
367 | "%s: waiting for operational state(count=%d)\n", | |
368 | ioc->name, __func__, wait_state_count); | |
369 | } | |
370 | if (wait_state_count) | |
371 | pr_info(MPT3SAS_FMT "%s: ioc is operational\n", | |
372 | ioc->name, __func__); | |
373 | ||
374 | smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx); | |
375 | if (!smid) { | |
376 | pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", | |
377 | ioc->name, __func__); | |
378 | ioc->config_cmds.status = MPT3_CMD_NOT_USED; | |
379 | r = -EAGAIN; | |
380 | goto free_mem; | |
381 | } | |
382 | ||
383 | r = 0; | |
384 | memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t)); | |
385 | ioc->config_cmds.status = MPT3_CMD_PENDING; | |
386 | config_request = mpt3sas_base_get_msg_frame(ioc, smid); | |
387 | ioc->config_cmds.smid = smid; | |
388 | memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t)); | |
389 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | |
390 | _config_display_some_debug(ioc, smid, "config_request", NULL); | |
391 | #endif | |
392 | init_completion(&ioc->config_cmds.done); | |
393 | mpt3sas_base_put_smid_default(ioc, smid); | |
394 | timeleft = wait_for_completion_timeout(&ioc->config_cmds.done, | |
395 | timeout*HZ); | |
396 | if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) { | |
397 | pr_err(MPT3SAS_FMT "%s: timeout\n", | |
398 | ioc->name, __func__); | |
399 | _debug_dump_mf(mpi_request, | |
400 | sizeof(Mpi2ConfigRequest_t)/4); | |
401 | retry_count++; | |
402 | if (ioc->config_cmds.smid == smid) | |
403 | mpt3sas_base_free_smid(ioc, smid); | |
404 | if ((ioc->shost_recovery) || (ioc->config_cmds.status & | |
405 | MPT3_CMD_RESET) || ioc->pci_error_recovery) | |
406 | goto retry_config; | |
407 | issue_host_reset = 1; | |
408 | r = -EFAULT; | |
409 | goto free_mem; | |
410 | } | |
411 | ||
412 | if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) { | |
413 | memcpy(mpi_reply, ioc->config_cmds.reply, | |
414 | sizeof(Mpi2ConfigReply_t)); | |
415 | ||
416 | /* Reply Frame Sanity Checks to workaround FW issues */ | |
417 | if ((mpi_request->Header.PageType & 0xF) != | |
418 | (mpi_reply->Header.PageType & 0xF)) { | |
419 | _debug_dump_mf(mpi_request, ioc->request_sz/4); | |
420 | _debug_dump_reply(mpi_reply, ioc->request_sz/4); | |
421 | panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \ | |
422 | " mpi_reply mismatch: Requested PageType(0x%02x)" \ | |
423 | " Reply PageType(0x%02x)\n", \ | |
424 | ioc->name, __func__, | |
425 | (mpi_request->Header.PageType & 0xF), | |
426 | (mpi_reply->Header.PageType & 0xF)); | |
427 | } | |
428 | ||
429 | if (((mpi_request->Header.PageType & 0xF) == | |
430 | MPI2_CONFIG_PAGETYPE_EXTENDED) && | |
431 | mpi_request->ExtPageType != mpi_reply->ExtPageType) { | |
432 | _debug_dump_mf(mpi_request, ioc->request_sz/4); | |
433 | _debug_dump_reply(mpi_reply, ioc->request_sz/4); | |
434 | panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \ | |
435 | " mpi_reply mismatch: Requested ExtPageType(0x%02x)" | |
436 | " Reply ExtPageType(0x%02x)\n", | |
437 | ioc->name, __func__, mpi_request->ExtPageType, | |
438 | mpi_reply->ExtPageType); | |
439 | } | |
440 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus) | |
441 | & MPI2_IOCSTATUS_MASK; | |
442 | } | |
443 | ||
444 | if (retry_count) | |
445 | pr_info(MPT3SAS_FMT "%s: retry (%d) completed!!\n", \ | |
446 | ioc->name, __func__, retry_count); | |
447 | ||
448 | if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) && | |
449 | config_page && mpi_request->Action == | |
450 | MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) { | |
451 | u8 *p = (u8 *)mem.page; | |
452 | ||
453 | /* Config Page Sanity Checks to workaround FW issues */ | |
454 | if (p) { | |
455 | if ((mpi_request->Header.PageType & 0xF) != | |
456 | (p[3] & 0xF)) { | |
457 | _debug_dump_mf(mpi_request, ioc->request_sz/4); | |
458 | _debug_dump_reply(mpi_reply, ioc->request_sz/4); | |
459 | _debug_dump_config(p, min_t(u16, mem.sz, | |
460 | config_page_sz)/4); | |
461 | panic(KERN_WARNING MPT3SAS_FMT | |
462 | "%s: Firmware BUG:" \ | |
463 | " config page mismatch:" | |
464 | " Requested PageType(0x%02x)" | |
465 | " Reply PageType(0x%02x)\n", | |
466 | ioc->name, __func__, | |
467 | (mpi_request->Header.PageType & 0xF), | |
468 | (p[3] & 0xF)); | |
469 | } | |
470 | ||
471 | if (((mpi_request->Header.PageType & 0xF) == | |
472 | MPI2_CONFIG_PAGETYPE_EXTENDED) && | |
473 | (mpi_request->ExtPageType != p[6])) { | |
474 | _debug_dump_mf(mpi_request, ioc->request_sz/4); | |
475 | _debug_dump_reply(mpi_reply, ioc->request_sz/4); | |
476 | _debug_dump_config(p, min_t(u16, mem.sz, | |
477 | config_page_sz)/4); | |
478 | panic(KERN_WARNING MPT3SAS_FMT | |
479 | "%s: Firmware BUG:" \ | |
480 | " config page mismatch:" | |
481 | " Requested ExtPageType(0x%02x)" | |
482 | " Reply ExtPageType(0x%02x)\n", | |
483 | ioc->name, __func__, | |
484 | mpi_request->ExtPageType, p[6]); | |
485 | } | |
486 | } | |
487 | memcpy(config_page, mem.page, min_t(u16, mem.sz, | |
488 | config_page_sz)); | |
489 | } | |
490 | ||
491 | free_mem: | |
492 | if (config_page) | |
493 | _config_free_config_dma_memory(ioc, &mem); | |
494 | out: | |
495 | ioc->config_cmds.status = MPT3_CMD_NOT_USED; | |
496 | mutex_unlock(&ioc->config_cmds.mutex); | |
497 | ||
498 | if (issue_host_reset) | |
499 | mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
500 | FORCE_BIG_HAMMER); | |
501 | return r; | |
502 | } | |
503 | ||
504 | /** | |
505 | * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0 | |
506 | * @ioc: per adapter object | |
507 | * @mpi_reply: reply mf payload returned from firmware | |
508 | * @config_page: contents of the config page | |
509 | * Context: sleep. | |
510 | * | |
511 | * Returns 0 for success, non-zero for failure. | |
512 | */ | |
513 | int | |
514 | mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc, | |
515 | Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page) | |
516 | { | |
517 | Mpi2ConfigRequest_t mpi_request; | |
518 | int r; | |
519 | ||
520 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
521 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
522 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
523 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; | |
524 | mpi_request.Header.PageNumber = 0; | |
525 | mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; | |
526 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
527 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
528 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
529 | if (r) | |
530 | goto out; | |
531 | ||
532 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
533 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
534 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
535 | sizeof(*config_page)); | |
536 | out: | |
537 | return r; | |
538 | } | |
539 | ||
540 | /** | |
541 | * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7 | |
542 | * @ioc: per adapter object | |
543 | * @mpi_reply: reply mf payload returned from firmware | |
544 | * @config_page: contents of the config page | |
545 | * @sz: size of buffer passed in config_page | |
546 | * Context: sleep. | |
547 | * | |
548 | * Returns 0 for success, non-zero for failure. | |
549 | */ | |
550 | int | |
551 | mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc, | |
552 | Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page, | |
553 | u16 sz) | |
554 | { | |
555 | Mpi2ConfigRequest_t mpi_request; | |
556 | int r; | |
557 | ||
558 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
559 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
560 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
561 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; | |
562 | mpi_request.Header.PageNumber = 7; | |
563 | mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION; | |
564 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
565 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
566 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
567 | if (r) | |
568 | goto out; | |
569 | ||
570 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
571 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
572 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
573 | sz); | |
574 | out: | |
575 | return r; | |
576 | } | |
577 | ||
578 | /** | |
579 | * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10 | |
580 | * @ioc: per adapter object | |
581 | * @mpi_reply: reply mf payload returned from firmware | |
582 | * @config_page: contents of the config page | |
583 | * Context: sleep. | |
584 | * | |
585 | * Returns 0 for success, non-zero for failure. | |
586 | */ | |
587 | int | |
588 | mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc, | |
589 | Mpi2ConfigReply_t *mpi_reply, | |
590 | struct Mpi2ManufacturingPage10_t *config_page) | |
591 | { | |
592 | Mpi2ConfigRequest_t mpi_request; | |
593 | int r; | |
594 | ||
595 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
596 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
597 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
598 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; | |
599 | mpi_request.Header.PageNumber = 10; | |
600 | mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; | |
601 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
602 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
603 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
604 | if (r) | |
605 | goto out; | |
606 | ||
607 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
608 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
609 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
610 | sizeof(*config_page)); | |
611 | out: | |
612 | return r; | |
613 | } | |
614 | ||
615 | /** | |
616 | * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11 | |
617 | * @ioc: per adapter object | |
618 | * @mpi_reply: reply mf payload returned from firmware | |
619 | * @config_page: contents of the config page | |
620 | * Context: sleep. | |
621 | * | |
622 | * Returns 0 for success, non-zero for failure. | |
623 | */ | |
624 | int | |
625 | mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc, | |
626 | Mpi2ConfigReply_t *mpi_reply, | |
627 | struct Mpi2ManufacturingPage11_t *config_page) | |
628 | { | |
629 | Mpi2ConfigRequest_t mpi_request; | |
630 | int r; | |
631 | ||
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_MANUFACTURING; | |
636 | mpi_request.Header.PageNumber = 11; | |
637 | mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; | |
638 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
639 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
640 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
641 | if (r) | |
642 | goto out; | |
643 | ||
644 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
645 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
646 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
647 | sizeof(*config_page)); | |
648 | out: | |
649 | return r; | |
650 | } | |
651 | ||
652 | /** | |
653 | * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11 | |
654 | * @ioc: per adapter object | |
655 | * @mpi_reply: reply mf payload returned from firmware | |
656 | * @config_page: contents of the config page | |
657 | * Context: sleep. | |
658 | * | |
659 | * Returns 0 for success, non-zero for failure. | |
660 | */ | |
661 | int | |
662 | mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc, | |
663 | Mpi2ConfigReply_t *mpi_reply, | |
664 | struct Mpi2ManufacturingPage11_t *config_page) | |
665 | { | |
666 | Mpi2ConfigRequest_t mpi_request; | |
667 | int r; | |
668 | ||
669 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
670 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
671 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
672 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; | |
673 | mpi_request.Header.PageNumber = 11; | |
674 | mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; | |
675 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
676 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
677 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
678 | if (r) | |
679 | goto out; | |
680 | ||
681 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; | |
682 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
683 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
684 | sizeof(*config_page)); | |
685 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; | |
686 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
687 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
688 | sizeof(*config_page)); | |
689 | out: | |
690 | return r; | |
691 | } | |
692 | ||
693 | /** | |
694 | * mpt3sas_config_get_bios_pg2 - obtain bios page 2 | |
695 | * @ioc: per adapter object | |
696 | * @mpi_reply: reply mf payload returned from firmware | |
697 | * @config_page: contents of the config page | |
698 | * Context: sleep. | |
699 | * | |
700 | * Returns 0 for success, non-zero for failure. | |
701 | */ | |
702 | int | |
703 | mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc, | |
704 | Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page) | |
705 | { | |
706 | Mpi2ConfigRequest_t mpi_request; | |
707 | int r; | |
708 | ||
709 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
710 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
711 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
712 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; | |
713 | mpi_request.Header.PageNumber = 2; | |
714 | mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION; | |
715 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
716 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
717 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
718 | if (r) | |
719 | goto out; | |
720 | ||
721 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
722 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
723 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
724 | sizeof(*config_page)); | |
725 | out: | |
726 | return r; | |
727 | } | |
728 | ||
729 | /** | |
730 | * mpt3sas_config_get_bios_pg3 - obtain bios page 3 | |
731 | * @ioc: per adapter object | |
732 | * @mpi_reply: reply mf payload returned from firmware | |
733 | * @config_page: contents of the config page | |
734 | * Context: sleep. | |
735 | * | |
736 | * Returns 0 for success, non-zero for failure. | |
737 | */ | |
738 | int | |
739 | mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
740 | *mpi_reply, Mpi2BiosPage3_t *config_page) | |
741 | { | |
742 | Mpi2ConfigRequest_t mpi_request; | |
743 | int r; | |
744 | ||
745 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
746 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
747 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
748 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; | |
749 | mpi_request.Header.PageNumber = 3; | |
750 | mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; | |
751 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
752 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
753 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
754 | if (r) | |
755 | goto out; | |
756 | ||
757 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
758 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
759 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
760 | sizeof(*config_page)); | |
761 | out: | |
762 | return r; | |
763 | } | |
764 | ||
765 | /** | |
766 | * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0 | |
767 | * @ioc: per adapter object | |
768 | * @mpi_reply: reply mf payload returned from firmware | |
769 | * @config_page: contents of the config page | |
770 | * Context: sleep. | |
771 | * | |
772 | * Returns 0 for success, non-zero for failure. | |
773 | */ | |
774 | int | |
775 | mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, | |
776 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page) | |
777 | { | |
778 | Mpi2ConfigRequest_t mpi_request; | |
779 | int r; | |
780 | ||
781 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
782 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
783 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
784 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | |
785 | mpi_request.Header.PageNumber = 0; | |
786 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION; | |
787 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
788 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
789 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
790 | if (r) | |
791 | goto out; | |
792 | ||
793 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
794 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
795 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
796 | sizeof(*config_page)); | |
797 | out: | |
798 | return r; | |
799 | } | |
800 | ||
801 | /** | |
802 | * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1 | |
803 | * @ioc: per adapter object | |
804 | * @mpi_reply: reply mf payload returned from firmware | |
805 | * @config_page: contents of the config page | |
806 | * Context: sleep. | |
807 | * | |
808 | * Returns 0 for success, non-zero for failure. | |
809 | */ | |
810 | int | |
811 | mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, | |
812 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page) | |
813 | { | |
814 | Mpi2ConfigRequest_t mpi_request; | |
815 | int r; | |
816 | ||
817 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
818 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
819 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
820 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | |
821 | mpi_request.Header.PageNumber = 1; | |
822 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION; | |
823 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
824 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
825 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
826 | if (r) | |
827 | goto out; | |
828 | ||
829 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
830 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
831 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
832 | sizeof(*config_page)); | |
833 | out: | |
834 | return r; | |
835 | } | |
836 | ||
837 | /** | |
838 | * mpt3sas_config_set_iounit_pg1 - set iounit page 1 | |
839 | * @ioc: per adapter object | |
840 | * @mpi_reply: reply mf payload returned from firmware | |
841 | * @config_page: contents of the config page | |
842 | * Context: sleep. | |
843 | * | |
844 | * Returns 0 for success, non-zero for failure. | |
845 | */ | |
846 | int | |
847 | mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, | |
848 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page) | |
849 | { | |
850 | Mpi2ConfigRequest_t mpi_request; | |
851 | int r; | |
852 | ||
853 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
854 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
855 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
856 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | |
857 | mpi_request.Header.PageNumber = 1; | |
858 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION; | |
859 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
860 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
861 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
862 | if (r) | |
863 | goto out; | |
864 | ||
865 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; | |
866 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
867 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
868 | sizeof(*config_page)); | |
869 | out: | |
870 | return r; | |
871 | } | |
872 | ||
2d8ce8c9 SR |
873 | /** |
874 | * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8 | |
875 | * @ioc: per adapter object | |
876 | * @mpi_reply: reply mf payload returned from firmware | |
877 | * @config_page: contents of the config page | |
878 | * Context: sleep. | |
879 | * | |
880 | * Returns 0 for success, non-zero for failure. | |
881 | */ | |
882 | int | |
883 | mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc, | |
884 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page) | |
885 | { | |
886 | Mpi2ConfigRequest_t mpi_request; | |
887 | int r; | |
888 | ||
889 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
890 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
891 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
892 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | |
893 | mpi_request.Header.PageNumber = 8; | |
894 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION; | |
895 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
896 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
897 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
898 | if (r) | |
899 | goto out; | |
900 | ||
901 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
902 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
903 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
904 | sizeof(*config_page)); | |
905 | out: | |
906 | return r; | |
907 | } | |
908 | ||
f92363d1 SR |
909 | /** |
910 | * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8 | |
911 | * @ioc: per adapter object | |
912 | * @mpi_reply: reply mf payload returned from firmware | |
913 | * @config_page: contents of the config page | |
914 | * Context: sleep. | |
915 | * | |
916 | * Returns 0 for success, non-zero for failure. | |
917 | */ | |
918 | int | |
919 | mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc, | |
920 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page) | |
921 | { | |
922 | Mpi2ConfigRequest_t mpi_request; | |
923 | int r; | |
924 | ||
925 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
926 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
927 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
928 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; | |
929 | mpi_request.Header.PageNumber = 8; | |
930 | mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; | |
931 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
932 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
933 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
934 | if (r) | |
935 | goto out; | |
936 | ||
937 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
938 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
939 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
940 | sizeof(*config_page)); | |
941 | out: | |
942 | return r; | |
943 | } | |
944 | ||
945 | /** | |
946 | * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0 | |
947 | * @ioc: per adapter object | |
948 | * @mpi_reply: reply mf payload returned from firmware | |
949 | * @config_page: contents of the config page | |
950 | * @form: GET_NEXT_HANDLE or HANDLE | |
951 | * @handle: device handle | |
952 | * Context: sleep. | |
953 | * | |
954 | * Returns 0 for success, non-zero for failure. | |
955 | */ | |
956 | int | |
957 | mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc, | |
958 | Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page, | |
959 | u32 form, u32 handle) | |
960 | { | |
961 | Mpi2ConfigRequest_t mpi_request; | |
962 | int r; | |
963 | ||
964 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
965 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
966 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
967 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
968 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; | |
969 | mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; | |
970 | mpi_request.Header.PageNumber = 0; | |
971 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
972 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
973 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
974 | if (r) | |
975 | goto out; | |
976 | ||
977 | mpi_request.PageAddress = cpu_to_le32(form | handle); | |
978 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
979 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
980 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
981 | sizeof(*config_page)); | |
982 | out: | |
983 | return r; | |
984 | } | |
985 | ||
986 | /** | |
987 | * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1 | |
988 | * @ioc: per adapter object | |
989 | * @mpi_reply: reply mf payload returned from firmware | |
990 | * @config_page: contents of the config page | |
991 | * @form: GET_NEXT_HANDLE or HANDLE | |
992 | * @handle: device handle | |
993 | * Context: sleep. | |
994 | * | |
995 | * Returns 0 for success, non-zero for failure. | |
996 | */ | |
997 | int | |
998 | mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc, | |
999 | Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page, | |
1000 | u32 form, u32 handle) | |
1001 | { | |
1002 | Mpi2ConfigRequest_t mpi_request; | |
1003 | int r; | |
1004 | ||
1005 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
1006 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1007 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1008 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1009 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; | |
1010 | mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION; | |
1011 | mpi_request.Header.PageNumber = 1; | |
1012 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
1013 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1014 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
1015 | if (r) | |
1016 | goto out; | |
1017 | ||
1018 | mpi_request.PageAddress = cpu_to_le32(form | handle); | |
1019 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
1020 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1021 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
1022 | sizeof(*config_page)); | |
1023 | out: | |
1024 | return r; | |
1025 | } | |
1026 | ||
1027 | /** | |
1028 | * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host | |
1029 | * @ioc: per adapter object | |
1030 | * @num_phys: pointer returned with the number of phys | |
1031 | * Context: sleep. | |
1032 | * | |
1033 | * Returns 0 for success, non-zero for failure. | |
1034 | */ | |
1035 | int | |
1036 | mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys) | |
1037 | { | |
1038 | Mpi2ConfigRequest_t mpi_request; | |
1039 | int r; | |
1040 | u16 ioc_status; | |
1041 | Mpi2ConfigReply_t mpi_reply; | |
1042 | Mpi2SasIOUnitPage0_t config_page; | |
1043 | ||
1044 | *num_phys = 0; | |
1045 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
1046 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1047 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1048 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1049 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | |
1050 | mpi_request.Header.PageNumber = 0; | |
1051 | mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; | |
1052 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
1053 | r = _config_request(ioc, &mpi_request, &mpi_reply, | |
1054 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
1055 | if (r) | |
1056 | goto out; | |
1057 | ||
1058 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
1059 | r = _config_request(ioc, &mpi_request, &mpi_reply, | |
1060 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page, | |
1061 | sizeof(Mpi2SasIOUnitPage0_t)); | |
1062 | if (!r) { | |
1063 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | |
1064 | MPI2_IOCSTATUS_MASK; | |
1065 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) | |
1066 | *num_phys = config_page.NumPhys; | |
1067 | } | |
1068 | out: | |
1069 | return r; | |
1070 | } | |
1071 | ||
1072 | /** | |
1073 | * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0 | |
1074 | * @ioc: per adapter object | |
1075 | * @mpi_reply: reply mf payload returned from firmware | |
1076 | * @config_page: contents of the config page | |
1077 | * @sz: size of buffer passed in config_page | |
1078 | * Context: sleep. | |
1079 | * | |
1080 | * Calling function should call config_get_number_hba_phys prior to | |
1081 | * this function, so enough memory is allocated for config_page. | |
1082 | * | |
1083 | * Returns 0 for success, non-zero for failure. | |
1084 | */ | |
1085 | int | |
1086 | mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, | |
1087 | Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, | |
1088 | u16 sz) | |
1089 | { | |
1090 | Mpi2ConfigRequest_t mpi_request; | |
1091 | int r; | |
1092 | ||
1093 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
1094 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1095 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1096 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1097 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | |
1098 | mpi_request.Header.PageNumber = 0; | |
1099 | mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; | |
1100 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
1101 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1102 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
1103 | if (r) | |
1104 | goto out; | |
1105 | ||
1106 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
1107 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1108 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); | |
1109 | out: | |
1110 | return r; | |
1111 | } | |
1112 | ||
1113 | /** | |
1114 | * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1 | |
1115 | * @ioc: per adapter object | |
1116 | * @mpi_reply: reply mf payload returned from firmware | |
1117 | * @config_page: contents of the config page | |
1118 | * @sz: size of buffer passed in config_page | |
1119 | * Context: sleep. | |
1120 | * | |
1121 | * Calling function should call config_get_number_hba_phys prior to | |
1122 | * this function, so enough memory is allocated for config_page. | |
1123 | * | |
1124 | * Returns 0 for success, non-zero for failure. | |
1125 | */ | |
1126 | int | |
1127 | mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, | |
1128 | Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, | |
1129 | u16 sz) | |
1130 | { | |
1131 | Mpi2ConfigRequest_t mpi_request; | |
1132 | int r; | |
1133 | ||
1134 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
1135 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1136 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1137 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1138 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | |
1139 | mpi_request.Header.PageNumber = 1; | |
1140 | mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION; | |
1141 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
1142 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1143 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
1144 | if (r) | |
1145 | goto out; | |
1146 | ||
1147 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
1148 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1149 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); | |
1150 | out: | |
1151 | return r; | |
1152 | } | |
1153 | ||
1154 | /** | |
1155 | * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1 | |
1156 | * @ioc: per adapter object | |
1157 | * @mpi_reply: reply mf payload returned from firmware | |
1158 | * @config_page: contents of the config page | |
1159 | * @sz: size of buffer passed in config_page | |
1160 | * Context: sleep. | |
1161 | * | |
1162 | * Calling function should call config_get_number_hba_phys prior to | |
1163 | * this function, so enough memory is allocated for config_page. | |
1164 | * | |
1165 | * Returns 0 for success, non-zero for failure. | |
1166 | */ | |
1167 | int | |
1168 | mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, | |
1169 | Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, | |
1170 | u16 sz) | |
1171 | { | |
1172 | Mpi2ConfigRequest_t mpi_request; | |
1173 | int r; | |
1174 | ||
1175 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
1176 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1177 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1178 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1179 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | |
1180 | mpi_request.Header.PageNumber = 1; | |
1181 | mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION; | |
1182 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
1183 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1184 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
1185 | if (r) | |
1186 | goto out; | |
1187 | ||
1188 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; | |
1189 | _config_request(ioc, &mpi_request, mpi_reply, | |
1190 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); | |
1191 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; | |
1192 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1193 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); | |
1194 | out: | |
1195 | return r; | |
1196 | } | |
1197 | ||
1198 | /** | |
1199 | * mpt3sas_config_get_expander_pg0 - obtain expander page 0 | |
1200 | * @ioc: per adapter object | |
1201 | * @mpi_reply: reply mf payload returned from firmware | |
1202 | * @config_page: contents of the config page | |
1203 | * @form: GET_NEXT_HANDLE or HANDLE | |
1204 | * @handle: expander handle | |
1205 | * Context: sleep. | |
1206 | * | |
1207 | * Returns 0 for success, non-zero for failure. | |
1208 | */ | |
1209 | int | |
1210 | mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
1211 | *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle) | |
1212 | { | |
1213 | Mpi2ConfigRequest_t mpi_request; | |
1214 | int r; | |
1215 | ||
1216 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
1217 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1218 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1219 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1220 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; | |
1221 | mpi_request.Header.PageNumber = 0; | |
1222 | mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION; | |
1223 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
1224 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1225 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
1226 | if (r) | |
1227 | goto out; | |
1228 | ||
1229 | mpi_request.PageAddress = cpu_to_le32(form | handle); | |
1230 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
1231 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1232 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
1233 | sizeof(*config_page)); | |
1234 | out: | |
1235 | return r; | |
1236 | } | |
1237 | ||
1238 | /** | |
1239 | * mpt3sas_config_get_expander_pg1 - obtain expander page 1 | |
1240 | * @ioc: per adapter object | |
1241 | * @mpi_reply: reply mf payload returned from firmware | |
1242 | * @config_page: contents of the config page | |
1243 | * @phy_number: phy number | |
1244 | * @handle: expander handle | |
1245 | * Context: sleep. | |
1246 | * | |
1247 | * Returns 0 for success, non-zero for failure. | |
1248 | */ | |
1249 | int | |
1250 | mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
1251 | *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number, | |
1252 | u16 handle) | |
1253 | { | |
1254 | Mpi2ConfigRequest_t mpi_request; | |
1255 | int r; | |
1256 | ||
1257 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
1258 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1259 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1260 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1261 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; | |
1262 | mpi_request.Header.PageNumber = 1; | |
1263 | mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION; | |
1264 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
1265 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1266 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
1267 | if (r) | |
1268 | goto out; | |
1269 | ||
1270 | mpi_request.PageAddress = | |
1271 | cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM | | |
1272 | (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle); | |
1273 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
1274 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1275 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
1276 | sizeof(*config_page)); | |
1277 | out: | |
1278 | return r; | |
1279 | } | |
1280 | ||
1281 | /** | |
1282 | * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0 | |
1283 | * @ioc: per adapter object | |
1284 | * @mpi_reply: reply mf payload returned from firmware | |
1285 | * @config_page: contents of the config page | |
1286 | * @form: GET_NEXT_HANDLE or HANDLE | |
1287 | * @handle: expander handle | |
1288 | * Context: sleep. | |
1289 | * | |
1290 | * Returns 0 for success, non-zero for failure. | |
1291 | */ | |
1292 | int | |
1293 | mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
1294 | *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle) | |
1295 | { | |
1296 | Mpi2ConfigRequest_t mpi_request; | |
1297 | int r; | |
1298 | ||
1299 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
1300 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1301 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1302 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1303 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE; | |
1304 | mpi_request.Header.PageNumber = 0; | |
1305 | mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION; | |
1306 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
1307 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1308 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
1309 | if (r) | |
1310 | goto out; | |
1311 | ||
1312 | mpi_request.PageAddress = cpu_to_le32(form | handle); | |
1313 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
1314 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1315 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
1316 | sizeof(*config_page)); | |
1317 | out: | |
1318 | return r; | |
1319 | } | |
1320 | ||
1321 | /** | |
1322 | * mpt3sas_config_get_phy_pg0 - obtain phy page 0 | |
1323 | * @ioc: per adapter object | |
1324 | * @mpi_reply: reply mf payload returned from firmware | |
1325 | * @config_page: contents of the config page | |
1326 | * @phy_number: phy number | |
1327 | * Context: sleep. | |
1328 | * | |
1329 | * Returns 0 for success, non-zero for failure. | |
1330 | */ | |
1331 | int | |
1332 | mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
1333 | *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number) | |
1334 | { | |
1335 | Mpi2ConfigRequest_t mpi_request; | |
1336 | int r; | |
1337 | ||
1338 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
1339 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1340 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1341 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1342 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; | |
1343 | mpi_request.Header.PageNumber = 0; | |
1344 | mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION; | |
1345 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
1346 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1347 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
1348 | if (r) | |
1349 | goto out; | |
1350 | ||
1351 | mpi_request.PageAddress = | |
1352 | cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); | |
1353 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
1354 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1355 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
1356 | sizeof(*config_page)); | |
1357 | out: | |
1358 | return r; | |
1359 | } | |
1360 | ||
1361 | /** | |
1362 | * mpt3sas_config_get_phy_pg1 - obtain phy page 1 | |
1363 | * @ioc: per adapter object | |
1364 | * @mpi_reply: reply mf payload returned from firmware | |
1365 | * @config_page: contents of the config page | |
1366 | * @phy_number: phy number | |
1367 | * Context: sleep. | |
1368 | * | |
1369 | * Returns 0 for success, non-zero for failure. | |
1370 | */ | |
1371 | int | |
1372 | mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
1373 | *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number) | |
1374 | { | |
1375 | Mpi2ConfigRequest_t mpi_request; | |
1376 | int r; | |
1377 | ||
1378 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
1379 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1380 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1381 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1382 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; | |
1383 | mpi_request.Header.PageNumber = 1; | |
1384 | mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION; | |
1385 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
1386 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1387 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
1388 | if (r) | |
1389 | goto out; | |
1390 | ||
1391 | mpi_request.PageAddress = | |
1392 | cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); | |
1393 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
1394 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1395 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
1396 | sizeof(*config_page)); | |
1397 | out: | |
1398 | return r; | |
1399 | } | |
1400 | ||
1401 | /** | |
1402 | * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1 | |
1403 | * @ioc: per adapter object | |
1404 | * @mpi_reply: reply mf payload returned from firmware | |
1405 | * @config_page: contents of the config page | |
1406 | * @form: GET_NEXT_HANDLE or HANDLE | |
1407 | * @handle: volume handle | |
1408 | * Context: sleep. | |
1409 | * | |
1410 | * Returns 0 for success, non-zero for failure. | |
1411 | */ | |
1412 | int | |
1413 | mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc, | |
1414 | Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, | |
1415 | u32 handle) | |
1416 | { | |
1417 | Mpi2ConfigRequest_t mpi_request; | |
1418 | int r; | |
1419 | ||
1420 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
1421 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1422 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1423 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; | |
1424 | mpi_request.Header.PageNumber = 1; | |
1425 | mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; | |
1426 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
1427 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1428 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
1429 | if (r) | |
1430 | goto out; | |
1431 | ||
1432 | mpi_request.PageAddress = cpu_to_le32(form | handle); | |
1433 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
1434 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1435 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
1436 | sizeof(*config_page)); | |
1437 | out: | |
1438 | return r; | |
1439 | } | |
1440 | ||
1441 | /** | |
1442 | * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume | |
1443 | * @ioc: per adapter object | |
1444 | * @handle: volume handle | |
1445 | * @num_pds: returns pds count | |
1446 | * Context: sleep. | |
1447 | * | |
1448 | * Returns 0 for success, non-zero for failure. | |
1449 | */ | |
1450 | int | |
1451 | mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle, | |
1452 | u8 *num_pds) | |
1453 | { | |
1454 | Mpi2ConfigRequest_t mpi_request; | |
1455 | Mpi2RaidVolPage0_t config_page; | |
1456 | Mpi2ConfigReply_t mpi_reply; | |
1457 | int r; | |
1458 | u16 ioc_status; | |
1459 | ||
1460 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
1461 | *num_pds = 0; | |
1462 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1463 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1464 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; | |
1465 | mpi_request.Header.PageNumber = 0; | |
1466 | mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; | |
1467 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
1468 | r = _config_request(ioc, &mpi_request, &mpi_reply, | |
1469 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
1470 | if (r) | |
1471 | goto out; | |
1472 | ||
1473 | mpi_request.PageAddress = | |
1474 | cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle); | |
1475 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
1476 | r = _config_request(ioc, &mpi_request, &mpi_reply, | |
1477 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page, | |
1478 | sizeof(Mpi2RaidVolPage0_t)); | |
1479 | if (!r) { | |
1480 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | |
1481 | MPI2_IOCSTATUS_MASK; | |
1482 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) | |
1483 | *num_pds = config_page.NumPhysDisks; | |
1484 | } | |
1485 | ||
1486 | out: | |
1487 | return r; | |
1488 | } | |
1489 | ||
1490 | /** | |
1491 | * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0 | |
1492 | * @ioc: per adapter object | |
1493 | * @mpi_reply: reply mf payload returned from firmware | |
1494 | * @config_page: contents of the config page | |
1495 | * @form: GET_NEXT_HANDLE or HANDLE | |
1496 | * @handle: volume handle | |
1497 | * @sz: size of buffer passed in config_page | |
1498 | * Context: sleep. | |
1499 | * | |
1500 | * Returns 0 for success, non-zero for failure. | |
1501 | */ | |
1502 | int | |
1503 | mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc, | |
1504 | Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, | |
1505 | u32 handle, u16 sz) | |
1506 | { | |
1507 | Mpi2ConfigRequest_t mpi_request; | |
1508 | int r; | |
1509 | ||
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 = 0; | |
1515 | mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; | |
1516 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
1517 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1518 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
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 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1525 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); | |
1526 | out: | |
1527 | return r; | |
1528 | } | |
1529 | ||
1530 | /** | |
1531 | * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0 | |
1532 | * @ioc: per adapter object | |
1533 | * @mpi_reply: reply mf payload returned from firmware | |
1534 | * @config_page: contents of the config page | |
1535 | * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE | |
1536 | * @form_specific: specific to the form | |
1537 | * Context: sleep. | |
1538 | * | |
1539 | * Returns 0 for success, non-zero for failure. | |
1540 | */ | |
1541 | int | |
1542 | mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
1543 | *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form, | |
1544 | u32 form_specific) | |
1545 | { | |
1546 | Mpi2ConfigRequest_t mpi_request; | |
1547 | int r; | |
1548 | ||
1549 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
1550 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1551 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1552 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; | |
1553 | mpi_request.Header.PageNumber = 0; | |
1554 | mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; | |
1555 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
1556 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1557 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
1558 | if (r) | |
1559 | goto out; | |
1560 | ||
1561 | mpi_request.PageAddress = cpu_to_le32(form | form_specific); | |
1562 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
1563 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1564 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
1565 | sizeof(*config_page)); | |
1566 | out: | |
1567 | return r; | |
1568 | } | |
1569 | ||
1570 | /** | |
1571 | * mpt3sas_config_get_volume_handle - returns volume handle for give hidden | |
1572 | * raid components | |
1573 | * @ioc: per adapter object | |
1574 | * @pd_handle: phys disk handle | |
1575 | * @volume_handle: volume handle | |
1576 | * Context: sleep. | |
1577 | * | |
1578 | * Returns 0 for success, non-zero for failure. | |
1579 | */ | |
1580 | int | |
1581 | mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle, | |
1582 | u16 *volume_handle) | |
1583 | { | |
1584 | Mpi2RaidConfigurationPage0_t *config_page = NULL; | |
1585 | Mpi2ConfigRequest_t mpi_request; | |
1586 | Mpi2ConfigReply_t mpi_reply; | |
1587 | int r, i, config_page_sz; | |
1588 | u16 ioc_status; | |
1589 | int config_num; | |
1590 | u16 element_type; | |
1591 | u16 phys_disk_dev_handle; | |
1592 | ||
1593 | *volume_handle = 0; | |
1594 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
1595 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1596 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1597 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1598 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG; | |
1599 | mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION; | |
1600 | mpi_request.Header.PageNumber = 0; | |
1601 | ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); | |
1602 | r = _config_request(ioc, &mpi_request, &mpi_reply, | |
1603 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
1604 | if (r) | |
1605 | goto out; | |
1606 | ||
1607 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
1608 | config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4); | |
1609 | config_page = kmalloc(config_page_sz, GFP_KERNEL); | |
1610 | if (!config_page) { | |
1611 | r = -1; | |
1612 | goto out; | |
1613 | } | |
1614 | ||
1615 | config_num = 0xff; | |
1616 | while (1) { | |
1617 | mpi_request.PageAddress = cpu_to_le32(config_num + | |
1618 | MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM); | |
1619 | r = _config_request(ioc, &mpi_request, &mpi_reply, | |
1620 | MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
1621 | config_page_sz); | |
1622 | if (r) | |
1623 | goto out; | |
1624 | r = -1; | |
1625 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | |
1626 | MPI2_IOCSTATUS_MASK; | |
1627 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | |
1628 | goto out; | |
1629 | for (i = 0; i < config_page->NumElements; i++) { | |
1630 | element_type = le16_to_cpu(config_page-> | |
1631 | ConfigElement[i].ElementFlags) & | |
1632 | MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE; | |
1633 | if (element_type == | |
1634 | MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT || | |
1635 | element_type == | |
1636 | MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) { | |
1637 | phys_disk_dev_handle = | |
1638 | le16_to_cpu(config_page->ConfigElement[i]. | |
1639 | PhysDiskDevHandle); | |
1640 | if (phys_disk_dev_handle == pd_handle) { | |
1641 | *volume_handle = | |
1642 | le16_to_cpu(config_page-> | |
1643 | ConfigElement[i].VolDevHandle); | |
1644 | r = 0; | |
1645 | goto out; | |
1646 | } | |
1647 | } else if (element_type == | |
1648 | MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) { | |
1649 | *volume_handle = 0; | |
1650 | r = 0; | |
1651 | goto out; | |
1652 | } | |
1653 | } | |
1654 | config_num = config_page->ConfigNum; | |
1655 | } | |
1656 | out: | |
1657 | kfree(config_page); | |
1658 | return r; | |
1659 | } | |
1660 | ||
1661 | /** | |
1662 | * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle | |
1663 | * @ioc: per adapter object | |
1664 | * @volume_handle: volume handle | |
1665 | * @wwid: volume wwid | |
1666 | * Context: sleep. | |
1667 | * | |
1668 | * Returns 0 for success, non-zero for failure. | |
1669 | */ | |
1670 | int | |
1671 | mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle, | |
1672 | u64 *wwid) | |
1673 | { | |
1674 | Mpi2ConfigReply_t mpi_reply; | |
1675 | Mpi2RaidVolPage1_t raid_vol_pg1; | |
1676 | ||
1677 | *wwid = 0; | |
1678 | if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply, | |
1679 | &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, | |
1680 | volume_handle))) { | |
1681 | *wwid = le64_to_cpu(raid_vol_pg1.WWID); | |
1682 | return 0; | |
1683 | } else | |
1684 | return -1; | |
1685 | } |