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