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