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