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