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