Commit | Line | Data |
---|---|---|
635374e7 EM |
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 | |
e9edbe31 | 5 | * Copyright (C) 2007-2014 LSI Corporation |
a03bd153 SR |
6 | * Copyright (C) 20013-2014 Avago Technologies |
7 | * (mailto: MPT-FusionLinux.pdl@avagotech.com) | |
635374e7 EM |
8 | * |
9 | * This program is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU General Public License | |
11 | * as published by the Free Software Foundation; either version 2 | |
12 | * of the License, or (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * NO WARRANTY | |
20 | * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | |
21 | * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | |
22 | * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | |
23 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | |
24 | * solely responsible for determining the appropriateness of using and | |
25 | * distributing the Program and assumes all risks associated with its | |
26 | * exercise of rights under this Agreement, including but not limited to | |
27 | * the risks and costs of program errors, damage to or loss of data, | |
28 | * programs or equipment, and unavailability or interruption of operations. | |
29 | ||
30 | * DISCLAIMER OF LIABILITY | |
31 | * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | |
32 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
33 | * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | |
34 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | |
35 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
36 | * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | |
37 | * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | |
38 | ||
39 | * You should have received a copy of the GNU General Public License | |
40 | * along with this program; if not, write to the Free Software | |
41 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | |
42 | * USA. | |
43 | */ | |
44 | ||
635374e7 EM |
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> | |
5a0e3ad6 | 54 | #include <linux/slab.h> |
635374e7 EM |
55 | |
56 | #include "mpt2sas_base.h" | |
57 | ||
58 | /* local definitions */ | |
59 | ||
60 | /* Timeout for config page request (in seconds) */ | |
61 | #define MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT 15 | |
62 | ||
63 | /* Common sgl flags for READING a config page. */ | |
64 | #define MPT2_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \ | |
65 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \ | |
66 | | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT) | |
67 | ||
68 | /* Common sgl flags for WRITING a config page. */ | |
69 | #define MPT2_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \ | |
70 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \ | |
71 | | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \ | |
72 | << MPI2_SGE_FLAGS_SHIFT) | |
73 | ||
74 | /** | |
75 | * struct config_request - obtain dma memory via routine | |
5b768581 KD |
76 | * @sz: size |
77 | * @page: virt pointer | |
78 | * @page_dma: phys pointer | |
635374e7 EM |
79 | * |
80 | */ | |
81 | struct config_request{ | |
5b768581 KD |
82 | u16 sz; |
83 | void *page; | |
84 | dma_addr_t page_dma; | |
635374e7 EM |
85 | }; |
86 | ||
87 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | |
88 | /** | |
89 | * _config_display_some_debug - debug routine | |
90 | * @ioc: per adapter object | |
91 | * @smid: system request message index | |
92 | * @calling_function_name: string pass from calling function | |
93 | * @mpi_reply: reply message frame | |
94 | * Context: none. | |
95 | * | |
25985edc | 96 | * Function for displaying debug info helpful when debugging issues |
635374e7 EM |
97 | * in this module. |
98 | */ | |
99 | static void | |
100 | _config_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid, | |
101 | char *calling_function_name, MPI2DefaultReply_t *mpi_reply) | |
102 | { | |
103 | Mpi2ConfigRequest_t *mpi_request; | |
104 | char *desc = NULL; | |
105 | ||
106 | if (!(ioc->logging_level & MPT_DEBUG_CONFIG)) | |
107 | return; | |
108 | ||
109 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | |
110 | switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) { | |
111 | case MPI2_CONFIG_PAGETYPE_IO_UNIT: | |
112 | desc = "io_unit"; | |
113 | break; | |
114 | case MPI2_CONFIG_PAGETYPE_IOC: | |
115 | desc = "ioc"; | |
116 | break; | |
117 | case MPI2_CONFIG_PAGETYPE_BIOS: | |
118 | desc = "bios"; | |
119 | break; | |
120 | case MPI2_CONFIG_PAGETYPE_RAID_VOLUME: | |
121 | desc = "raid_volume"; | |
122 | break; | |
123 | case MPI2_CONFIG_PAGETYPE_MANUFACTURING: | |
124 | desc = "manufaucturing"; | |
125 | break; | |
126 | case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK: | |
127 | desc = "physdisk"; | |
128 | break; | |
129 | case MPI2_CONFIG_PAGETYPE_EXTENDED: | |
130 | switch (mpi_request->ExtPageType) { | |
131 | case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT: | |
132 | desc = "sas_io_unit"; | |
133 | break; | |
134 | case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER: | |
135 | desc = "sas_expander"; | |
136 | break; | |
137 | case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE: | |
138 | desc = "sas_device"; | |
139 | break; | |
140 | case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY: | |
141 | desc = "sas_phy"; | |
142 | break; | |
143 | case MPI2_CONFIG_EXTPAGETYPE_LOG: | |
144 | desc = "log"; | |
145 | break; | |
146 | case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE: | |
147 | desc = "enclosure"; | |
148 | break; | |
149 | case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG: | |
150 | desc = "raid_config"; | |
151 | break; | |
152 | case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING: | |
19f2da35 | 153 | desc = "driver_mapping"; |
635374e7 EM |
154 | break; |
155 | } | |
156 | break; | |
157 | } | |
158 | ||
159 | if (!desc) | |
160 | return; | |
161 | ||
eabb08ad | 162 | printk(MPT2SAS_INFO_FMT "%s: %s(%d), action(%d), form(0x%08x), " |
635374e7 EM |
163 | "smid(%d)\n", ioc->name, calling_function_name, desc, |
164 | mpi_request->Header.PageNumber, mpi_request->Action, | |
165 | le32_to_cpu(mpi_request->PageAddress), smid); | |
166 | ||
167 | if (!mpi_reply) | |
168 | return; | |
169 | ||
170 | if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo) | |
eabb08ad | 171 | printk(MPT2SAS_INFO_FMT |
635374e7 EM |
172 | "\tiocstatus(0x%04x), loginfo(0x%08x)\n", |
173 | ioc->name, le16_to_cpu(mpi_reply->IOCStatus), | |
174 | le32_to_cpu(mpi_reply->IOCLogInfo)); | |
175 | } | |
176 | #endif | |
177 | ||
5b768581 KD |
178 | /** |
179 | * _config_alloc_config_dma_memory - obtain physical memory | |
180 | * @ioc: per adapter object | |
181 | * @mem: struct config_request | |
182 | * | |
183 | * A wrapper for obtaining dma-able memory for config page request. | |
184 | * | |
185 | * Returns 0 for success, non-zero for failure. | |
186 | */ | |
187 | static int | |
188 | _config_alloc_config_dma_memory(struct MPT2SAS_ADAPTER *ioc, | |
189 | struct config_request *mem) | |
190 | { | |
191 | int r = 0; | |
192 | ||
193 | if (mem->sz > ioc->config_page_sz) { | |
194 | mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz, | |
195 | &mem->page_dma, GFP_KERNEL); | |
196 | if (!mem->page) { | |
197 | printk(MPT2SAS_ERR_FMT "%s: dma_alloc_coherent" | |
198 | " failed asking for (%d) bytes!!\n", | |
199 | ioc->name, __func__, mem->sz); | |
200 | r = -ENOMEM; | |
201 | } | |
202 | } else { /* use tmp buffer if less than 512 bytes */ | |
203 | mem->page = ioc->config_page; | |
204 | mem->page_dma = ioc->config_page_dma; | |
205 | } | |
206 | return r; | |
207 | } | |
208 | ||
209 | /** | |
210 | * _config_free_config_dma_memory - wrapper to free the memory | |
211 | * @ioc: per adapter object | |
212 | * @mem: struct config_request | |
213 | * | |
214 | * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory. | |
215 | * | |
216 | * Returns 0 for success, non-zero for failure. | |
217 | */ | |
218 | static void | |
219 | _config_free_config_dma_memory(struct MPT2SAS_ADAPTER *ioc, | |
220 | struct config_request *mem) | |
221 | { | |
222 | if (mem->sz > ioc->config_page_sz) | |
223 | dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page, | |
224 | mem->page_dma); | |
225 | } | |
226 | ||
635374e7 EM |
227 | /** |
228 | * mpt2sas_config_done - config page completion routine | |
229 | * @ioc: per adapter object | |
230 | * @smid: system request message index | |
7b936b02 | 231 | * @msix_index: MSIX table index supplied by the OS |
635374e7 EM |
232 | * @reply: reply message frame(lower 32bit addr) |
233 | * Context: none. | |
234 | * | |
235 | * The callback handler when using _config_request. | |
236 | * | |
77e63ed4 KD |
237 | * Return 1 meaning mf should be freed from _base_interrupt |
238 | * 0 means the mf is freed from this function. | |
635374e7 | 239 | */ |
77e63ed4 | 240 | u8 |
7b936b02 KD |
241 | mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
242 | u32 reply) | |
635374e7 EM |
243 | { |
244 | MPI2DefaultReply_t *mpi_reply; | |
245 | ||
246 | if (ioc->config_cmds.status == MPT2_CMD_NOT_USED) | |
77e63ed4 | 247 | return 1; |
635374e7 | 248 | if (ioc->config_cmds.smid != smid) |
77e63ed4 | 249 | return 1; |
635374e7 EM |
250 | ioc->config_cmds.status |= MPT2_CMD_COMPLETE; |
251 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | |
252 | if (mpi_reply) { | |
253 | ioc->config_cmds.status |= MPT2_CMD_REPLY_VALID; | |
254 | memcpy(ioc->config_cmds.reply, mpi_reply, | |
255 | mpi_reply->MsgLength*4); | |
256 | } | |
257 | ioc->config_cmds.status &= ~MPT2_CMD_PENDING; | |
258 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | |
259 | _config_display_some_debug(ioc, smid, "config_done", mpi_reply); | |
260 | #endif | |
4be929be | 261 | ioc->config_cmds.smid = USHRT_MAX; |
635374e7 | 262 | complete(&ioc->config_cmds.done); |
77e63ed4 | 263 | return 1; |
635374e7 EM |
264 | } |
265 | ||
266 | /** | |
267 | * _config_request - main routine for sending config page requests | |
268 | * @ioc: per adapter object | |
269 | * @mpi_request: request message frame | |
270 | * @mpi_reply: reply mf payload returned from firmware | |
271 | * @timeout: timeout in seconds | |
5b768581 KD |
272 | * @config_page: contents of the config page |
273 | * @config_page_sz: size of config page | |
274 | * Context: sleep | |
635374e7 EM |
275 | * |
276 | * A generic API for config page requests to firmware. | |
277 | * | |
278 | * The ioc->config_cmds.status flag should be MPT2_CMD_NOT_USED before calling | |
279 | * this API. | |
280 | * | |
281 | * The callback index is set inside `ioc->config_cb_idx. | |
282 | * | |
283 | * Returns 0 for success, non-zero for failure. | |
284 | */ | |
285 | static int | |
286 | _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t | |
5b768581 KD |
287 | *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout, |
288 | void *config_page, u16 config_page_sz) | |
635374e7 EM |
289 | { |
290 | u16 smid; | |
291 | u32 ioc_state; | |
292 | unsigned long timeleft; | |
293 | Mpi2ConfigRequest_t *config_request; | |
294 | int r; | |
5b768581 | 295 | u8 retry_count, issue_host_reset = 0; |
635374e7 | 296 | u16 wait_state_count; |
5b768581 | 297 | struct config_request mem; |
635374e7 | 298 | |
388ce4be | 299 | mutex_lock(&ioc->config_cmds.mutex); |
635374e7 EM |
300 | if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) { |
301 | printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n", | |
302 | ioc->name, __func__); | |
388ce4be | 303 | mutex_unlock(&ioc->config_cmds.mutex); |
635374e7 EM |
304 | return -EAGAIN; |
305 | } | |
5b768581 | 306 | |
635374e7 | 307 | retry_count = 0; |
5b768581 KD |
308 | memset(&mem, 0, sizeof(struct config_request)); |
309 | ||
7b936b02 KD |
310 | mpi_request->VF_ID = 0; /* TODO */ |
311 | mpi_request->VP_ID = 0; | |
312 | ||
5b768581 KD |
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 == | |
50d5c606 KD |
328 | MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT || |
329 | mpi_request->Action == | |
330 | MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) { | |
5b768581 KD |
331 | ioc->base_add_sg_single(&mpi_request->PageBufferSGE, |
332 | MPT2_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 | MPT2_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma); | |
340 | } | |
341 | } | |
635374e7 EM |
342 | |
343 | retry_config: | |
6bd4e1e4 | 344 | if (retry_count) { |
5b768581 KD |
345 | if (retry_count > 2) { /* attempt only 2 retries */ |
346 | r = -EFAULT; | |
347 | goto free_mem; | |
348 | } | |
6bd4e1e4 KD |
349 | printk(MPT2SAS_INFO_FMT "%s: attempting retry (%d)\n", |
350 | ioc->name, __func__, retry_count); | |
351 | } | |
635374e7 EM |
352 | wait_state_count = 0; |
353 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | |
354 | while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | |
355 | if (wait_state_count++ == MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT) { | |
356 | printk(MPT2SAS_ERR_FMT | |
357 | "%s: failed due to ioc not operational\n", | |
358 | ioc->name, __func__); | |
5b768581 | 359 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; |
388ce4be | 360 | r = -EFAULT; |
5b768581 | 361 | goto free_mem; |
635374e7 EM |
362 | } |
363 | ssleep(1); | |
364 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | |
365 | printk(MPT2SAS_INFO_FMT "%s: waiting for " | |
366 | "operational state(count=%d)\n", ioc->name, | |
367 | __func__, wait_state_count); | |
368 | } | |
369 | if (wait_state_count) | |
370 | printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", | |
371 | ioc->name, __func__); | |
372 | ||
373 | smid = mpt2sas_base_get_smid(ioc, ioc->config_cb_idx); | |
374 | if (!smid) { | |
375 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | |
376 | ioc->name, __func__); | |
5b768581 | 377 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; |
388ce4be | 378 | r = -EAGAIN; |
5b768581 | 379 | goto free_mem; |
635374e7 EM |
380 | } |
381 | ||
382 | r = 0; | |
383 | memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t)); | |
384 | ioc->config_cmds.status = MPT2_CMD_PENDING; | |
385 | config_request = mpt2sas_base_get_msg_frame(ioc, smid); | |
386 | ioc->config_cmds.smid = smid; | |
387 | memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t)); | |
388 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | |
389 | _config_display_some_debug(ioc, smid, "config_request", NULL); | |
390 | #endif | |
5b768581 | 391 | init_completion(&ioc->config_cmds.done); |
7b936b02 | 392 | mpt2sas_base_put_smid_default(ioc, smid); |
635374e7 EM |
393 | timeleft = wait_for_completion_timeout(&ioc->config_cmds.done, |
394 | timeout*HZ); | |
395 | if (!(ioc->config_cmds.status & MPT2_CMD_COMPLETE)) { | |
396 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | |
397 | ioc->name, __func__); | |
398 | _debug_dump_mf(mpi_request, | |
399 | sizeof(Mpi2ConfigRequest_t)/4); | |
388ce4be KD |
400 | retry_count++; |
401 | if (ioc->config_cmds.smid == smid) | |
402 | mpt2sas_base_free_smid(ioc, smid); | |
5b768581 | 403 | if ((ioc->shost_recovery) || (ioc->config_cmds.status & |
3cb5469a | 404 | MPT2_CMD_RESET) || ioc->pci_error_recovery) |
388ce4be KD |
405 | goto retry_config; |
406 | issue_host_reset = 1; | |
407 | r = -EFAULT; | |
5b768581 | 408 | goto free_mem; |
635374e7 | 409 | } |
5b768581 | 410 | |
635374e7 EM |
411 | if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID) |
412 | memcpy(mpi_reply, ioc->config_cmds.reply, | |
413 | sizeof(Mpi2ConfigReply_t)); | |
414 | if (retry_count) | |
5b768581 KD |
415 | printk(MPT2SAS_INFO_FMT "%s: retry (%d) completed!!\n", |
416 | ioc->name, __func__, retry_count); | |
417 | if (config_page && mpi_request->Action == | |
418 | MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) | |
419 | memcpy(config_page, mem.page, min_t(u16, mem.sz, | |
420 | config_page_sz)); | |
421 | free_mem: | |
422 | if (config_page) | |
423 | _config_free_config_dma_memory(ioc, &mem); | |
424 | out: | |
635374e7 | 425 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; |
388ce4be | 426 | mutex_unlock(&ioc->config_cmds.mutex); |
5b768581 | 427 | |
388ce4be | 428 | if (issue_host_reset) |
635374e7 EM |
429 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, |
430 | FORCE_BIG_HAMMER); | |
388ce4be | 431 | return r; |
635374e7 EM |
432 | } |
433 | ||
635374e7 EM |
434 | /** |
435 | * mpt2sas_config_get_manufacturing_pg0 - obtain manufacturing page 0 | |
436 | * @ioc: per adapter object | |
437 | * @mpi_reply: reply mf payload returned from firmware | |
438 | * @config_page: contents of the config page | |
439 | * Context: sleep. | |
440 | * | |
441 | * Returns 0 for success, non-zero for failure. | |
442 | */ | |
443 | int | |
444 | mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc, | |
445 | Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page) | |
446 | { | |
447 | Mpi2ConfigRequest_t mpi_request; | |
448 | int r; | |
635374e7 | 449 | |
635374e7 EM |
450 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
451 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
452 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
453 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; | |
454 | mpi_request.Header.PageNumber = 0; | |
455 | mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; | |
456 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
457 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 458 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
459 | if (r) |
460 | goto out; | |
461 | ||
462 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 463 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
464 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
465 | sizeof(*config_page)); | |
635374e7 | 466 | out: |
635374e7 EM |
467 | return r; |
468 | } | |
469 | ||
ed79f128 KD |
470 | /** |
471 | * mpt2sas_config_get_manufacturing_pg10 - obtain manufacturing page 10 | |
472 | * @ioc: per adapter object | |
473 | * @mpi_reply: reply mf payload returned from firmware | |
474 | * @config_page: contents of the config page | |
475 | * Context: sleep. | |
476 | * | |
477 | * Returns 0 for success, non-zero for failure. | |
478 | */ | |
479 | int | |
480 | mpt2sas_config_get_manufacturing_pg10(struct MPT2SAS_ADAPTER *ioc, | |
481 | Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage10_t *config_page) | |
482 | { | |
483 | Mpi2ConfigRequest_t mpi_request; | |
484 | int r; | |
ed79f128 | 485 | |
ed79f128 KD |
486 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
487 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
488 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
489 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; | |
490 | mpi_request.Header.PageNumber = 10; | |
491 | mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; | |
492 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
493 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 494 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
ed79f128 KD |
495 | if (r) |
496 | goto out; | |
497 | ||
498 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
ed79f128 | 499 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
500 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
501 | sizeof(*config_page)); | |
ed79f128 KD |
502 | out: |
503 | return r; | |
504 | } | |
505 | ||
635374e7 EM |
506 | /** |
507 | * mpt2sas_config_get_bios_pg2 - obtain bios page 2 | |
508 | * @ioc: per adapter object | |
509 | * @mpi_reply: reply mf payload returned from firmware | |
510 | * @config_page: contents of the config page | |
511 | * Context: sleep. | |
512 | * | |
513 | * Returns 0 for success, non-zero for failure. | |
514 | */ | |
515 | int | |
516 | mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, | |
517 | Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page) | |
518 | { | |
519 | Mpi2ConfigRequest_t mpi_request; | |
520 | int r; | |
635374e7 | 521 | |
635374e7 EM |
522 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
523 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
524 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
525 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; | |
526 | mpi_request.Header.PageNumber = 2; | |
527 | mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION; | |
528 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
529 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 530 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
531 | if (r) |
532 | goto out; | |
533 | ||
534 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 535 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
536 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
537 | sizeof(*config_page)); | |
635374e7 | 538 | out: |
635374e7 EM |
539 | return r; |
540 | } | |
541 | ||
542 | /** | |
543 | * mpt2sas_config_get_bios_pg3 - obtain bios page 3 | |
544 | * @ioc: per adapter object | |
545 | * @mpi_reply: reply mf payload returned from firmware | |
546 | * @config_page: contents of the config page | |
547 | * Context: sleep. | |
548 | * | |
549 | * Returns 0 for success, non-zero for failure. | |
550 | */ | |
551 | int | |
552 | mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
553 | *mpi_reply, Mpi2BiosPage3_t *config_page) | |
554 | { | |
555 | Mpi2ConfigRequest_t mpi_request; | |
556 | int r; | |
635374e7 | 557 | |
635374e7 EM |
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_BIOS; | |
562 | mpi_request.Header.PageNumber = 3; | |
563 | mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; | |
564 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
565 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 566 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
567 | if (r) |
568 | goto out; | |
569 | ||
570 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 571 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
572 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
573 | sizeof(*config_page)); | |
635374e7 | 574 | out: |
635374e7 EM |
575 | return r; |
576 | } | |
577 | ||
578 | /** | |
579 | * mpt2sas_config_get_iounit_pg0 - obtain iounit page 0 | |
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 | mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, | |
589 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page) | |
590 | { | |
591 | Mpi2ConfigRequest_t mpi_request; | |
592 | int r; | |
635374e7 | 593 | |
635374e7 EM |
594 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
595 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
596 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
597 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | |
598 | mpi_request.Header.PageNumber = 0; | |
599 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION; | |
600 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
601 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 602 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
603 | if (r) |
604 | goto out; | |
605 | ||
606 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 607 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
608 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
609 | sizeof(*config_page)); | |
635374e7 | 610 | out: |
635374e7 EM |
611 | return r; |
612 | } | |
613 | ||
614 | /** | |
615 | * mpt2sas_config_get_iounit_pg1 - obtain iounit page 1 | |
616 | * @ioc: per adapter object | |
617 | * @mpi_reply: reply mf payload returned from firmware | |
618 | * @config_page: contents of the config page | |
619 | * Context: sleep. | |
620 | * | |
621 | * Returns 0 for success, non-zero for failure. | |
622 | */ | |
623 | int | |
624 | mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, | |
625 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page) | |
626 | { | |
627 | Mpi2ConfigRequest_t mpi_request; | |
628 | int r; | |
635374e7 | 629 | |
635374e7 EM |
630 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
631 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
632 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
633 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | |
634 | mpi_request.Header.PageNumber = 1; | |
635 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION; | |
636 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
637 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 638 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
639 | if (r) |
640 | goto out; | |
641 | ||
642 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 643 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
644 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
645 | sizeof(*config_page)); | |
635374e7 | 646 | out: |
635374e7 EM |
647 | return r; |
648 | } | |
649 | ||
650 | /** | |
651 | * mpt2sas_config_set_iounit_pg1 - set iounit page 1 | |
652 | * @ioc: per adapter object | |
653 | * @mpi_reply: reply mf payload returned from firmware | |
654 | * @config_page: contents of the config page | |
655 | * Context: sleep. | |
656 | * | |
657 | * Returns 0 for success, non-zero for failure. | |
658 | */ | |
659 | int | |
660 | mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, | |
5b768581 | 661 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page) |
635374e7 EM |
662 | { |
663 | Mpi2ConfigRequest_t mpi_request; | |
664 | int r; | |
635374e7 | 665 | |
635374e7 EM |
666 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
667 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
668 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
669 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | |
670 | mpi_request.Header.PageNumber = 1; | |
671 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION; | |
672 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
673 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 674 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
675 | if (r) |
676 | goto out; | |
677 | ||
678 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; | |
635374e7 | 679 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
680 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
681 | sizeof(*config_page)); | |
635374e7 | 682 | out: |
635374e7 EM |
683 | return r; |
684 | } | |
685 | ||
6c265660 | 686 | /** |
687 | * mpt2sas_config_get_iounit_pg3 - obtain iounit page 3 | |
688 | * @ioc: per adapter object | |
689 | * @mpi_reply: reply mf payload returned from firmware | |
690 | * @config_page: contents of the config page | |
691 | * @sz: size of buffer passed in config_page | |
692 | * Context: sleep. | |
693 | * | |
694 | * Returns 0 for success, non-zero for failure. | |
695 | */ | |
696 | int | |
697 | mpt2sas_config_get_iounit_pg3(struct MPT2SAS_ADAPTER *ioc, | |
698 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz) | |
699 | { | |
700 | Mpi2ConfigRequest_t mpi_request; | |
701 | int r; | |
702 | ||
703 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
704 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
705 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
706 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | |
707 | mpi_request.Header.PageNumber = 3; | |
708 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION; | |
709 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
710 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
711 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
712 | if (r) | |
713 | goto out; | |
714 | ||
715 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
716 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
717 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); | |
718 | out: | |
719 | return r; | |
720 | } | |
721 | ||
2d8ce8c9 SR |
722 | /** |
723 | * mpt2sas_config_get_iounit_pg8 - obtain iounit page 8 | |
724 | * @ioc: per adapter object | |
725 | * @mpi_reply: reply mf payload returned from firmware | |
726 | * @config_page: contents of the config page | |
727 | * Context: sleep. | |
728 | * | |
729 | * Returns 0 for success, non-zero for failure. | |
730 | */ | |
731 | int | |
732 | mpt2sas_config_get_iounit_pg8(struct MPT2SAS_ADAPTER *ioc, | |
733 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page) | |
734 | { | |
735 | Mpi2ConfigRequest_t mpi_request; | |
736 | int r; | |
737 | ||
738 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
739 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
740 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
741 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; | |
742 | mpi_request.Header.PageNumber = 8; | |
743 | mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION; | |
744 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
745 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
746 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
747 | if (r) | |
748 | goto out; | |
749 | ||
750 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
751 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
752 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
753 | sizeof(*config_page)); | |
754 | out: | |
755 | return r; | |
756 | } | |
757 | ||
635374e7 EM |
758 | /** |
759 | * mpt2sas_config_get_ioc_pg8 - obtain ioc page 8 | |
760 | * @ioc: per adapter object | |
761 | * @mpi_reply: reply mf payload returned from firmware | |
762 | * @config_page: contents of the config page | |
763 | * Context: sleep. | |
764 | * | |
765 | * Returns 0 for success, non-zero for failure. | |
766 | */ | |
767 | int | |
768 | mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, | |
769 | Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page) | |
770 | { | |
771 | Mpi2ConfigRequest_t mpi_request; | |
772 | int r; | |
635374e7 | 773 | |
635374e7 EM |
774 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
775 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
776 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
777 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; | |
778 | mpi_request.Header.PageNumber = 8; | |
779 | mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; | |
780 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
781 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 782 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
783 | if (r) |
784 | goto out; | |
785 | ||
786 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 787 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
788 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
789 | sizeof(*config_page)); | |
635374e7 | 790 | out: |
635374e7 EM |
791 | return r; |
792 | } | |
793 | ||
794 | /** | |
795 | * mpt2sas_config_get_sas_device_pg0 - obtain sas device page 0 | |
796 | * @ioc: per adapter object | |
797 | * @mpi_reply: reply mf payload returned from firmware | |
798 | * @config_page: contents of the config page | |
799 | * @form: GET_NEXT_HANDLE or HANDLE | |
800 | * @handle: device handle | |
801 | * Context: sleep. | |
802 | * | |
803 | * Returns 0 for success, non-zero for failure. | |
804 | */ | |
805 | int | |
806 | mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
807 | *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle) | |
808 | { | |
809 | Mpi2ConfigRequest_t mpi_request; | |
810 | int r; | |
635374e7 | 811 | |
635374e7 EM |
812 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
813 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
814 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
815 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
816 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; | |
817 | mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; | |
818 | mpi_request.Header.PageNumber = 0; | |
819 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
820 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 821 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
822 | if (r) |
823 | goto out; | |
824 | ||
825 | mpi_request.PageAddress = cpu_to_le32(form | handle); | |
826 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 827 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
828 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
829 | sizeof(*config_page)); | |
635374e7 | 830 | out: |
635374e7 EM |
831 | return r; |
832 | } | |
833 | ||
834 | /** | |
835 | * mpt2sas_config_get_sas_device_pg1 - obtain sas device page 1 | |
836 | * @ioc: per adapter object | |
837 | * @mpi_reply: reply mf payload returned from firmware | |
838 | * @config_page: contents of the config page | |
839 | * @form: GET_NEXT_HANDLE or HANDLE | |
840 | * @handle: device handle | |
841 | * Context: sleep. | |
842 | * | |
843 | * Returns 0 for success, non-zero for failure. | |
844 | */ | |
845 | int | |
846 | mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
847 | *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle) | |
848 | { | |
849 | Mpi2ConfigRequest_t mpi_request; | |
850 | int r; | |
635374e7 | 851 | |
635374e7 EM |
852 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
853 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
854 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
855 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
856 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; | |
857 | mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION; | |
858 | mpi_request.Header.PageNumber = 1; | |
859 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
860 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 861 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
862 | if (r) |
863 | goto out; | |
864 | ||
865 | mpi_request.PageAddress = cpu_to_le32(form | handle); | |
866 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 867 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
868 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
869 | sizeof(*config_page)); | |
635374e7 | 870 | out: |
635374e7 EM |
871 | return r; |
872 | } | |
873 | ||
874 | /** | |
875 | * mpt2sas_config_get_number_hba_phys - obtain number of phys on the host | |
876 | * @ioc: per adapter object | |
877 | * @num_phys: pointer returned with the number of phys | |
878 | * Context: sleep. | |
879 | * | |
880 | * Returns 0 for success, non-zero for failure. | |
881 | */ | |
882 | int | |
883 | mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys) | |
884 | { | |
885 | Mpi2ConfigRequest_t mpi_request; | |
886 | int r; | |
635374e7 EM |
887 | u16 ioc_status; |
888 | Mpi2ConfigReply_t mpi_reply; | |
889 | Mpi2SasIOUnitPage0_t config_page; | |
890 | ||
5b768581 | 891 | *num_phys = 0; |
635374e7 EM |
892 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
893 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
894 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
895 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
896 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | |
897 | mpi_request.Header.PageNumber = 0; | |
898 | mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; | |
899 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
900 | r = _config_request(ioc, &mpi_request, &mpi_reply, | |
5b768581 | 901 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
902 | if (r) |
903 | goto out; | |
904 | ||
905 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 906 | r = _config_request(ioc, &mpi_request, &mpi_reply, |
5b768581 KD |
907 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page, |
908 | sizeof(Mpi2SasIOUnitPage0_t)); | |
635374e7 EM |
909 | if (!r) { |
910 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | |
911 | MPI2_IOCSTATUS_MASK; | |
5b768581 | 912 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) |
635374e7 | 913 | *num_phys = config_page.NumPhys; |
635374e7 | 914 | } |
635374e7 | 915 | out: |
635374e7 EM |
916 | return r; |
917 | } | |
918 | ||
919 | /** | |
920 | * mpt2sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0 | |
921 | * @ioc: per adapter object | |
922 | * @mpi_reply: reply mf payload returned from firmware | |
923 | * @config_page: contents of the config page | |
924 | * @sz: size of buffer passed in config_page | |
925 | * Context: sleep. | |
926 | * | |
927 | * Calling function should call config_get_number_hba_phys prior to | |
928 | * this function, so enough memory is allocated for config_page. | |
929 | * | |
930 | * Returns 0 for success, non-zero for failure. | |
931 | */ | |
932 | int | |
933 | mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
934 | *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz) | |
935 | { | |
936 | Mpi2ConfigRequest_t mpi_request; | |
937 | int r; | |
5b768581 | 938 | |
635374e7 EM |
939 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
940 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
941 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
942 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
943 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | |
944 | mpi_request.Header.PageNumber = 0; | |
945 | mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; | |
946 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
947 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 948 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
949 | if (r) |
950 | goto out; | |
951 | ||
952 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 953 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 | 954 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); |
635374e7 | 955 | out: |
635374e7 EM |
956 | return r; |
957 | } | |
958 | ||
959 | /** | |
50d5c606 | 960 | * mpt2sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1 |
635374e7 EM |
961 | * @ioc: per adapter object |
962 | * @mpi_reply: reply mf payload returned from firmware | |
963 | * @config_page: contents of the config page | |
964 | * @sz: size of buffer passed in config_page | |
965 | * Context: sleep. | |
966 | * | |
967 | * Calling function should call config_get_number_hba_phys prior to | |
968 | * this function, so enough memory is allocated for config_page. | |
969 | * | |
970 | * Returns 0 for success, non-zero for failure. | |
971 | */ | |
972 | int | |
973 | mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
974 | *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz) | |
975 | { | |
976 | Mpi2ConfigRequest_t mpi_request; | |
977 | int r; | |
635374e7 | 978 | |
635374e7 EM |
979 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
980 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
981 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
982 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
983 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | |
984 | mpi_request.Header.PageNumber = 1; | |
50d5c606 | 985 | mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION; |
635374e7 EM |
986 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); |
987 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 988 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
989 | if (r) |
990 | goto out; | |
991 | ||
992 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 993 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 | 994 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); |
635374e7 | 995 | out: |
635374e7 EM |
996 | return r; |
997 | } | |
998 | ||
50d5c606 KD |
999 | /** |
1000 | * mpt2sas_config_set_sas_iounit_pg1 - send sas iounit page 1 | |
1001 | * @ioc: per adapter object | |
1002 | * @mpi_reply: reply mf payload returned from firmware | |
1003 | * @config_page: contents of the config page | |
1004 | * @sz: size of buffer passed in config_page | |
1005 | * Context: sleep. | |
1006 | * | |
1007 | * Calling function should call config_get_number_hba_phys prior to | |
1008 | * this function, so enough memory is allocated for config_page. | |
1009 | * | |
1010 | * Returns 0 for success, non-zero for failure. | |
1011 | */ | |
1012 | int | |
1013 | mpt2sas_config_set_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
1014 | *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz) | |
1015 | { | |
1016 | Mpi2ConfigRequest_t mpi_request; | |
1017 | int r; | |
1018 | ||
1019 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
1020 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1021 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1022 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1023 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | |
1024 | mpi_request.Header.PageNumber = 1; | |
1025 | mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION; | |
1026 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
1027 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1028 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); | |
1029 | if (r) | |
1030 | goto out; | |
1031 | ||
1032 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; | |
1033 | _config_request(ioc, &mpi_request, mpi_reply, | |
1034 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); | |
1035 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; | |
1036 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
1037 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); | |
1038 | out: | |
1039 | return r; | |
1040 | } | |
1041 | ||
635374e7 EM |
1042 | /** |
1043 | * mpt2sas_config_get_expander_pg0 - obtain expander page 0 | |
1044 | * @ioc: per adapter object | |
1045 | * @mpi_reply: reply mf payload returned from firmware | |
1046 | * @config_page: contents of the config page | |
1047 | * @form: GET_NEXT_HANDLE or HANDLE | |
1048 | * @handle: expander handle | |
1049 | * Context: sleep. | |
1050 | * | |
1051 | * Returns 0 for success, non-zero for failure. | |
1052 | */ | |
1053 | int | |
1054 | mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
1055 | *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle) | |
1056 | { | |
1057 | Mpi2ConfigRequest_t mpi_request; | |
1058 | int r; | |
635374e7 | 1059 | |
635374e7 EM |
1060 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1061 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1062 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1063 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1064 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; | |
1065 | mpi_request.Header.PageNumber = 0; | |
1066 | mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION; | |
1067 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
1068 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 1069 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
1070 | if (r) |
1071 | goto out; | |
1072 | ||
1073 | mpi_request.PageAddress = cpu_to_le32(form | handle); | |
1074 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 1075 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
1076 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
1077 | sizeof(*config_page)); | |
635374e7 | 1078 | out: |
635374e7 EM |
1079 | return r; |
1080 | } | |
1081 | ||
1082 | /** | |
1083 | * mpt2sas_config_get_expander_pg1 - obtain expander page 1 | |
1084 | * @ioc: per adapter object | |
1085 | * @mpi_reply: reply mf payload returned from firmware | |
1086 | * @config_page: contents of the config page | |
1087 | * @phy_number: phy number | |
1088 | * @handle: expander handle | |
1089 | * Context: sleep. | |
1090 | * | |
1091 | * Returns 0 for success, non-zero for failure. | |
1092 | */ | |
1093 | int | |
1094 | mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
1095 | *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number, | |
1096 | u16 handle) | |
1097 | { | |
1098 | Mpi2ConfigRequest_t mpi_request; | |
1099 | int r; | |
635374e7 | 1100 | |
635374e7 EM |
1101 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1102 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1103 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1104 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1105 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; | |
1106 | mpi_request.Header.PageNumber = 1; | |
1107 | mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION; | |
1108 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
1109 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 1110 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
1111 | if (r) |
1112 | goto out; | |
1113 | ||
1114 | mpi_request.PageAddress = | |
1115 | cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM | | |
1116 | (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle); | |
1117 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 1118 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
1119 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
1120 | sizeof(*config_page)); | |
635374e7 | 1121 | out: |
635374e7 EM |
1122 | return r; |
1123 | } | |
1124 | ||
1125 | /** | |
1126 | * mpt2sas_config_get_enclosure_pg0 - obtain enclosure page 0 | |
1127 | * @ioc: per adapter object | |
1128 | * @mpi_reply: reply mf payload returned from firmware | |
1129 | * @config_page: contents of the config page | |
1130 | * @form: GET_NEXT_HANDLE or HANDLE | |
1131 | * @handle: expander handle | |
1132 | * Context: sleep. | |
1133 | * | |
1134 | * Returns 0 for success, non-zero for failure. | |
1135 | */ | |
1136 | int | |
1137 | mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
1138 | *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle) | |
1139 | { | |
1140 | Mpi2ConfigRequest_t mpi_request; | |
1141 | int r; | |
635374e7 | 1142 | |
635374e7 EM |
1143 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1144 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1145 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1146 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1147 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE; | |
1148 | mpi_request.Header.PageNumber = 0; | |
1149 | mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION; | |
1150 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
1151 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 1152 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
1153 | if (r) |
1154 | goto out; | |
1155 | ||
1156 | mpi_request.PageAddress = cpu_to_le32(form | handle); | |
1157 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 1158 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
1159 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
1160 | sizeof(*config_page)); | |
635374e7 | 1161 | out: |
635374e7 EM |
1162 | return r; |
1163 | } | |
1164 | ||
1165 | /** | |
1166 | * mpt2sas_config_get_phy_pg0 - obtain phy page 0 | |
1167 | * @ioc: per adapter object | |
1168 | * @mpi_reply: reply mf payload returned from firmware | |
1169 | * @config_page: contents of the config page | |
1170 | * @phy_number: phy number | |
1171 | * Context: sleep. | |
1172 | * | |
1173 | * Returns 0 for success, non-zero for failure. | |
1174 | */ | |
1175 | int | |
1176 | mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
1177 | *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number) | |
1178 | { | |
1179 | Mpi2ConfigRequest_t mpi_request; | |
1180 | int r; | |
635374e7 | 1181 | |
635374e7 EM |
1182 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1183 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1184 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1185 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1186 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; | |
1187 | mpi_request.Header.PageNumber = 0; | |
1188 | mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION; | |
1189 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
1190 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 1191 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
1192 | if (r) |
1193 | goto out; | |
1194 | ||
1195 | mpi_request.PageAddress = | |
1196 | cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); | |
1197 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 1198 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
1199 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
1200 | sizeof(*config_page)); | |
635374e7 | 1201 | out: |
635374e7 EM |
1202 | return r; |
1203 | } | |
1204 | ||
1205 | /** | |
1206 | * mpt2sas_config_get_phy_pg1 - obtain phy page 1 | |
1207 | * @ioc: per adapter object | |
1208 | * @mpi_reply: reply mf payload returned from firmware | |
1209 | * @config_page: contents of the config page | |
1210 | * @phy_number: phy number | |
1211 | * Context: sleep. | |
1212 | * | |
1213 | * Returns 0 for success, non-zero for failure. | |
1214 | */ | |
1215 | int | |
1216 | mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
1217 | *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number) | |
1218 | { | |
1219 | Mpi2ConfigRequest_t mpi_request; | |
1220 | int r; | |
635374e7 | 1221 | |
635374e7 EM |
1222 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1223 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1224 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1225 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1226 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; | |
1227 | mpi_request.Header.PageNumber = 1; | |
1228 | mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION; | |
1229 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
1230 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 1231 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
1232 | if (r) |
1233 | goto out; | |
1234 | ||
1235 | mpi_request.PageAddress = | |
1236 | cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); | |
1237 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 1238 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
1239 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
1240 | sizeof(*config_page)); | |
635374e7 | 1241 | out: |
635374e7 EM |
1242 | return r; |
1243 | } | |
1244 | ||
1245 | /** | |
1246 | * mpt2sas_config_get_raid_volume_pg1 - obtain raid volume page 1 | |
1247 | * @ioc: per adapter object | |
1248 | * @mpi_reply: reply mf payload returned from firmware | |
1249 | * @config_page: contents of the config page | |
1250 | * @form: GET_NEXT_HANDLE or HANDLE | |
1251 | * @handle: volume handle | |
1252 | * Context: sleep. | |
1253 | * | |
1254 | * Returns 0 for success, non-zero for failure. | |
1255 | */ | |
1256 | int | |
1257 | mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, | |
1258 | Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, | |
1259 | u32 handle) | |
1260 | { | |
1261 | Mpi2ConfigRequest_t mpi_request; | |
1262 | int r; | |
635374e7 | 1263 | |
635374e7 EM |
1264 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1265 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1266 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1267 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; | |
1268 | mpi_request.Header.PageNumber = 1; | |
1269 | mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; | |
1270 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
1271 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 1272 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
1273 | if (r) |
1274 | goto out; | |
1275 | ||
1276 | mpi_request.PageAddress = cpu_to_le32(form | handle); | |
1277 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 1278 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
1279 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
1280 | sizeof(*config_page)); | |
635374e7 | 1281 | out: |
635374e7 EM |
1282 | return r; |
1283 | } | |
1284 | ||
1285 | /** | |
1286 | * mpt2sas_config_get_number_pds - obtain number of phys disk assigned to volume | |
1287 | * @ioc: per adapter object | |
1288 | * @handle: volume handle | |
1289 | * @num_pds: returns pds count | |
1290 | * Context: sleep. | |
1291 | * | |
1292 | * Returns 0 for success, non-zero for failure. | |
1293 | */ | |
1294 | int | |
1295 | mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, | |
1296 | u8 *num_pds) | |
1297 | { | |
1298 | Mpi2ConfigRequest_t mpi_request; | |
5b768581 | 1299 | Mpi2RaidVolPage0_t config_page; |
635374e7 EM |
1300 | Mpi2ConfigReply_t mpi_reply; |
1301 | int r; | |
635374e7 EM |
1302 | u16 ioc_status; |
1303 | ||
635374e7 EM |
1304 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1305 | *num_pds = 0; | |
1306 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1307 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1308 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; | |
1309 | mpi_request.Header.PageNumber = 0; | |
1310 | mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; | |
1311 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
1312 | r = _config_request(ioc, &mpi_request, &mpi_reply, | |
5b768581 | 1313 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
1314 | if (r) |
1315 | goto out; | |
1316 | ||
1317 | mpi_request.PageAddress = | |
1318 | cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle); | |
1319 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 1320 | r = _config_request(ioc, &mpi_request, &mpi_reply, |
5b768581 KD |
1321 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page, |
1322 | sizeof(Mpi2RaidVolPage0_t)); | |
635374e7 EM |
1323 | if (!r) { |
1324 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | |
1325 | MPI2_IOCSTATUS_MASK; | |
5b768581 KD |
1326 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) |
1327 | *num_pds = config_page.NumPhysDisks; | |
635374e7 EM |
1328 | } |
1329 | ||
635374e7 | 1330 | out: |
635374e7 EM |
1331 | return r; |
1332 | } | |
1333 | ||
1334 | /** | |
1335 | * mpt2sas_config_get_raid_volume_pg0 - obtain raid volume page 0 | |
1336 | * @ioc: per adapter object | |
1337 | * @mpi_reply: reply mf payload returned from firmware | |
1338 | * @config_page: contents of the config page | |
1339 | * @form: GET_NEXT_HANDLE or HANDLE | |
1340 | * @handle: volume handle | |
1341 | * @sz: size of buffer passed in config_page | |
1342 | * Context: sleep. | |
1343 | * | |
1344 | * Returns 0 for success, non-zero for failure. | |
1345 | */ | |
1346 | int | |
1347 | mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, | |
1348 | Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, | |
1349 | u32 handle, u16 sz) | |
1350 | { | |
1351 | Mpi2ConfigRequest_t mpi_request; | |
1352 | int r; | |
635374e7 | 1353 | |
635374e7 | 1354 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
635374e7 EM |
1355 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
1356 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1357 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; | |
1358 | mpi_request.Header.PageNumber = 0; | |
1359 | mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; | |
1360 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
1361 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 1362 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
1363 | if (r) |
1364 | goto out; | |
1365 | ||
1366 | mpi_request.PageAddress = cpu_to_le32(form | handle); | |
1367 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 1368 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 | 1369 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); |
635374e7 | 1370 | out: |
635374e7 EM |
1371 | return r; |
1372 | } | |
1373 | ||
1374 | /** | |
1375 | * mpt2sas_config_get_phys_disk_pg0 - obtain phys disk page 0 | |
1376 | * @ioc: per adapter object | |
1377 | * @mpi_reply: reply mf payload returned from firmware | |
1378 | * @config_page: contents of the config page | |
1379 | * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE | |
1380 | * @form_specific: specific to the form | |
1381 | * Context: sleep. | |
1382 | * | |
1383 | * Returns 0 for success, non-zero for failure. | |
1384 | */ | |
1385 | int | |
1386 | mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |
1387 | *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form, | |
1388 | u32 form_specific) | |
1389 | { | |
1390 | Mpi2ConfigRequest_t mpi_request; | |
1391 | int r; | |
635374e7 | 1392 | |
635374e7 | 1393 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
635374e7 EM |
1394 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
1395 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1396 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; | |
1397 | mpi_request.Header.PageNumber = 0; | |
1398 | mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; | |
1399 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
1400 | r = _config_request(ioc, &mpi_request, mpi_reply, | |
5b768581 | 1401 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
1402 | if (r) |
1403 | goto out; | |
1404 | ||
1405 | mpi_request.PageAddress = cpu_to_le32(form | form_specific); | |
1406 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | |
635374e7 | 1407 | r = _config_request(ioc, &mpi_request, mpi_reply, |
5b768581 KD |
1408 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, |
1409 | sizeof(*config_page)); | |
635374e7 | 1410 | out: |
635374e7 EM |
1411 | return r; |
1412 | } | |
1413 | ||
1414 | /** | |
1415 | * mpt2sas_config_get_volume_handle - returns volume handle for give hidden raid components | |
1416 | * @ioc: per adapter object | |
1417 | * @pd_handle: phys disk handle | |
1418 | * @volume_handle: volume handle | |
1419 | * Context: sleep. | |
1420 | * | |
1421 | * Returns 0 for success, non-zero for failure. | |
1422 | */ | |
1423 | int | |
1424 | mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle, | |
1425 | u16 *volume_handle) | |
1426 | { | |
5b768581 | 1427 | Mpi2RaidConfigurationPage0_t *config_page = NULL; |
635374e7 EM |
1428 | Mpi2ConfigRequest_t mpi_request; |
1429 | Mpi2ConfigReply_t mpi_reply; | |
5b768581 | 1430 | int r, i, config_page_sz; |
635374e7 | 1431 | u16 ioc_status; |
35116db9 | 1432 | int config_num; |
1433 | u16 element_type; | |
1434 | u16 phys_disk_dev_handle; | |
635374e7 | 1435 | |
635374e7 EM |
1436 | *volume_handle = 0; |
1437 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | |
1438 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | |
1439 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | |
1440 | mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | |
1441 | mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG; | |
1442 | mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION; | |
1443 | mpi_request.Header.PageNumber = 0; | |
1444 | mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE); | |
1445 | r = _config_request(ioc, &mpi_request, &mpi_reply, | |
5b768581 | 1446 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); |
635374e7 EM |
1447 | if (r) |
1448 | goto out; | |
1449 | ||
635374e7 | 1450 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; |
5b768581 KD |
1451 | config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4); |
1452 | config_page = kmalloc(config_page_sz, GFP_KERNEL); | |
35116db9 | 1453 | if (!config_page) { |
1454 | r = -1; | |
635374e7 | 1455 | goto out; |
35116db9 | 1456 | } |
1457 | config_num = 0xff; | |
1458 | while (1) { | |
1459 | mpi_request.PageAddress = cpu_to_le32(config_num + | |
1460 | MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM); | |
1461 | r = _config_request(ioc, &mpi_request, &mpi_reply, | |
1462 | MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, | |
1463 | config_page_sz); | |
1464 | if (r) | |
1465 | goto out; | |
1466 | r = -1; | |
1467 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | |
1468 | MPI2_IOCSTATUS_MASK; | |
1469 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | |
5b768581 | 1470 | goto out; |
35116db9 | 1471 | for (i = 0; i < config_page->NumElements; i++) { |
1472 | element_type = le16_to_cpu(config_page-> | |
1473 | ConfigElement[i].ElementFlags) & | |
1474 | MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE; | |
1475 | if (element_type == | |
1476 | MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT || | |
1477 | element_type == | |
1478 | MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) { | |
1479 | phys_disk_dev_handle = | |
1480 | le16_to_cpu(config_page->ConfigElement[i]. | |
1481 | PhysDiskDevHandle); | |
1482 | if (phys_disk_dev_handle == pd_handle) { | |
1483 | *volume_handle = | |
1484 | le16_to_cpu(config_page-> | |
1485 | ConfigElement[i].VolDevHandle); | |
1486 | r = 0; | |
1487 | goto out; | |
1488 | } | |
1489 | } else if (element_type == | |
1490 | MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) { | |
1491 | *volume_handle = 0; | |
1492 | r = 0; | |
1493 | goto out; | |
1494 | } | |
635374e7 | 1495 | } |
35116db9 | 1496 | config_num = config_page->ConfigNum; |
635374e7 | 1497 | } |
635374e7 | 1498 | out: |
5b768581 | 1499 | kfree(config_page); |
635374e7 EM |
1500 | return r; |
1501 | } | |
1502 | ||
1503 | /** | |
1504 | * mpt2sas_config_get_volume_wwid - returns wwid given the volume handle | |
1505 | * @ioc: per adapter object | |
1506 | * @volume_handle: volume handle | |
1507 | * @wwid: volume wwid | |
1508 | * Context: sleep. | |
1509 | * | |
1510 | * Returns 0 for success, non-zero for failure. | |
1511 | */ | |
1512 | int | |
1513 | mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle, | |
1514 | u64 *wwid) | |
1515 | { | |
1516 | Mpi2ConfigReply_t mpi_reply; | |
1517 | Mpi2RaidVolPage1_t raid_vol_pg1; | |
1518 | ||
1519 | *wwid = 0; | |
1520 | if (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, | |
1521 | &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, | |
1522 | volume_handle))) { | |
1523 | *wwid = le64_to_cpu(raid_vol_pg1.WWID); | |
1524 | return 0; | |
1525 | } else | |
1526 | return -1; | |
1527 | } |