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