Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mpt2sas_config.c
Go to the documentation of this file.
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-2012 LSI Corporation
6  * (mailto:[email protected])
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * NO WARRANTY
19  * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
20  * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
21  * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
22  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
23  * solely responsible for determining the appropriateness of using and
24  * distributing the Program and assumes all risks associated with its
25  * exercise of rights under this Agreement, including but not limited to
26  * the risks and costs of program errors, damage to or loss of data,
27  * programs or equipment, and unavailability or interruption of operations.
28 
29  * DISCLAIMER OF LIABILITY
30  * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
31  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
33  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
35  * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
36  * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
37 
38  * You should have received a copy of the GNU General Public License
39  * along with this program; if not, write to the Free Software
40  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
41  * USA.
42  */
43 
44 #include <linux/module.h>
45 #include <linux/kernel.h>
46 #include <linux/init.h>
47 #include <linux/errno.h>
48 #include <linux/blkdev.h>
49 #include <linux/sched.h>
50 #include <linux/workqueue.h>
51 #include <linux/delay.h>
52 #include <linux/pci.h>
53 #include <linux/slab.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 
82  void *page;
84 };
85 
86 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
87 
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) {
111  desc = "io_unit";
112  break;
114  desc = "ioc";
115  break;
117  desc = "bios";
118  break;
120  desc = "raid_volume";
121  break;
123  desc = "manufaucturing";
124  break;
126  desc = "physdisk";
127  break;
129  switch (mpi_request->ExtPageType) {
131  desc = "sas_io_unit";
132  break;
134  desc = "sas_expander";
135  break;
137  desc = "sas_device";
138  break;
140  desc = "sas_phy";
141  break;
143  desc = "log";
144  break;
146  desc = "enclosure";
147  break;
149  desc = "raid_config";
150  break;
152  desc = "driver_mapping";
153  break;
154  }
155  break;
156  }
157 
158  if (!desc)
159  return;
160 
161  printk(MPT2SAS_INFO_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)
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 
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 
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 
239 u8
240 mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
241  u32 reply)
242 {
243  MPI2DefaultReply_t *mpi_reply;
244 
245  if (ioc->config_cmds.status == MPT2_CMD_NOT_USED)
246  return 1;
247  if (ioc->config_cmds.smid != smid)
248  return 1;
249  ioc->config_cmds.status |= MPT2_CMD_COMPLETE;
250  mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
251  if (mpi_reply) {
252  ioc->config_cmds.status |= MPT2_CMD_REPLY_VALID;
253  memcpy(ioc->config_cmds.reply, mpi_reply,
254  mpi_reply->MsgLength*4);
255  }
256  ioc->config_cmds.status &= ~MPT2_CMD_PENDING;
257 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
258  _config_display_some_debug(ioc, smid, "config_done", mpi_reply);
259 #endif
260  ioc->config_cmds.smid = USHRT_MAX;
261  complete(&ioc->config_cmds.done);
262  return 1;
263 }
264 
284 static int
285 _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
286  *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout,
287  void *config_page, u16 config_page_sz)
288 {
289  u16 smid;
290  u32 ioc_state;
291  unsigned long timeleft;
293  int r;
294  u8 retry_count, issue_host_reset = 0;
295  u16 wait_state_count;
296  struct config_request mem;
297 
298  mutex_lock(&ioc->config_cmds.mutex);
299  if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) {
300  printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n",
301  ioc->name, __func__);
302  mutex_unlock(&ioc->config_cmds.mutex);
303  return -EAGAIN;
304  }
305 
306  retry_count = 0;
307  memset(&mem, 0, sizeof(struct config_request));
308 
309  mpi_request->VF_ID = 0; /* TODO */
310  mpi_request->VP_ID = 0;
311 
312  if (config_page) {
313  mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
314  mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
315  mpi_request->Header.PageType = mpi_reply->Header.PageType;
316  mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
317  mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
318  mpi_request->ExtPageType = mpi_reply->ExtPageType;
319  if (mpi_request->Header.PageLength)
320  mem.sz = mpi_request->Header.PageLength * 4;
321  else
322  mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
323  r = _config_alloc_config_dma_memory(ioc, &mem);
324  if (r != 0)
325  goto out;
326  if (mpi_request->Action ==
328  mpi_request->Action ==
330  ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
332  mem.page_dma);
333  memcpy(mem.page, config_page, min_t(u16, mem.sz,
334  config_page_sz));
335  } else {
336  memset(config_page, 0, config_page_sz);
337  ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
339  }
340  }
341 
342  retry_config:
343  if (retry_count) {
344  if (retry_count > 2) { /* attempt only 2 retries */
345  r = -EFAULT;
346  goto free_mem;
347  }
348  printk(MPT2SAS_INFO_FMT "%s: attempting retry (%d)\n",
349  ioc->name, __func__, retry_count);
350  }
351  wait_state_count = 0;
352  ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
353  while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
354  if (wait_state_count++ == MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT) {
356  "%s: failed due to ioc not operational\n",
357  ioc->name, __func__);
358  ioc->config_cmds.status = MPT2_CMD_NOT_USED;
359  r = -EFAULT;
360  goto free_mem;
361  }
362  ssleep(1);
363  ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
364  printk(MPT2SAS_INFO_FMT "%s: waiting for "
365  "operational state(count=%d)\n", ioc->name,
366  __func__, wait_state_count);
367  }
368  if (wait_state_count)
369  printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
370  ioc->name, __func__);
371 
372  smid = mpt2sas_base_get_smid(ioc, ioc->config_cb_idx);
373  if (!smid) {
374  printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
375  ioc->name, __func__);
376  ioc->config_cmds.status = MPT2_CMD_NOT_USED;
377  r = -EAGAIN;
378  goto free_mem;
379  }
380 
381  r = 0;
382  memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
383  ioc->config_cmds.status = MPT2_CMD_PENDING;
384  config_request = mpt2sas_base_get_msg_frame(ioc, smid);
385  ioc->config_cmds.smid = smid;
386  memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
387 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
388  _config_display_some_debug(ioc, smid, "config_request", NULL);
389 #endif
390  init_completion(&ioc->config_cmds.done);
392  timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
393  timeout*HZ);
394  if (!(ioc->config_cmds.status & MPT2_CMD_COMPLETE)) {
395  printk(MPT2SAS_ERR_FMT "%s: timeout\n",
396  ioc->name, __func__);
397  _debug_dump_mf(mpi_request,
398  sizeof(Mpi2ConfigRequest_t)/4);
399  retry_count++;
400  if (ioc->config_cmds.smid == smid)
401  mpt2sas_base_free_smid(ioc, smid);
402  if ((ioc->shost_recovery) || (ioc->config_cmds.status &
404  goto retry_config;
405  issue_host_reset = 1;
406  r = -EFAULT;
407  goto free_mem;
408  }
409 
410  if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID)
411  memcpy(mpi_reply, ioc->config_cmds.reply,
412  sizeof(Mpi2ConfigReply_t));
413  if (retry_count)
414  printk(MPT2SAS_INFO_FMT "%s: retry (%d) completed!!\n",
415  ioc->name, __func__, retry_count);
416  if (config_page && mpi_request->Action ==
418  memcpy(config_page, mem.page, min_t(u16, mem.sz,
419  config_page_sz));
420  free_mem:
421  if (config_page)
422  _config_free_config_dma_memory(ioc, &mem);
423  out:
424  ioc->config_cmds.status = MPT2_CMD_NOT_USED;
425  mutex_unlock(&ioc->config_cmds.mutex);
426 
427  if (issue_host_reset)
430  return r;
431 }
432 
442 int
444  Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
445 {
446  Mpi2ConfigRequest_t mpi_request;
447  int r;
448 
449  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
450  mpi_request.Function = MPI2_FUNCTION_CONFIG;
453  mpi_request.Header.PageNumber = 0;
456  r = _config_request(ioc, &mpi_request, mpi_reply,
458  if (r)
459  goto out;
460 
462  r = _config_request(ioc, &mpi_request, mpi_reply,
464  sizeof(*config_page));
465  out:
466  return r;
467 }
468 
478 int
480  Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage10_t *config_page)
481 {
482  Mpi2ConfigRequest_t mpi_request;
483  int r;
484 
485  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
486  mpi_request.Function = MPI2_FUNCTION_CONFIG;
489  mpi_request.Header.PageNumber = 10;
492  r = _config_request(ioc, &mpi_request, mpi_reply,
494  if (r)
495  goto out;
496 
498  r = _config_request(ioc, &mpi_request, mpi_reply,
500  sizeof(*config_page));
501  out:
502  return r;
503 }
504 
514 int
516  Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
517 {
518  Mpi2ConfigRequest_t mpi_request;
519  int r;
520 
521  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
522  mpi_request.Function = MPI2_FUNCTION_CONFIG;
525  mpi_request.Header.PageNumber = 2;
528  r = _config_request(ioc, &mpi_request, mpi_reply,
530  if (r)
531  goto out;
532 
534  r = _config_request(ioc, &mpi_request, mpi_reply,
536  sizeof(*config_page));
537  out:
538  return r;
539 }
540 
550 int
552  *mpi_reply, Mpi2BiosPage3_t *config_page)
553 {
554  Mpi2ConfigRequest_t mpi_request;
555  int r;
556 
557  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
558  mpi_request.Function = MPI2_FUNCTION_CONFIG;
561  mpi_request.Header.PageNumber = 3;
564  r = _config_request(ioc, &mpi_request, mpi_reply,
566  if (r)
567  goto out;
568 
570  r = _config_request(ioc, &mpi_request, mpi_reply,
572  sizeof(*config_page));
573  out:
574  return r;
575 }
576 
586 int
588  Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
589 {
590  Mpi2ConfigRequest_t mpi_request;
591  int r;
592 
593  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
594  mpi_request.Function = MPI2_FUNCTION_CONFIG;
597  mpi_request.Header.PageNumber = 0;
600  r = _config_request(ioc, &mpi_request, mpi_reply,
602  if (r)
603  goto out;
604 
606  r = _config_request(ioc, &mpi_request, mpi_reply,
608  sizeof(*config_page));
609  out:
610  return r;
611 }
612 
622 int
624  Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
625 {
626  Mpi2ConfigRequest_t mpi_request;
627  int r;
628 
629  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
630  mpi_request.Function = MPI2_FUNCTION_CONFIG;
633  mpi_request.Header.PageNumber = 1;
636  r = _config_request(ioc, &mpi_request, mpi_reply,
638  if (r)
639  goto out;
640 
642  r = _config_request(ioc, &mpi_request, mpi_reply,
644  sizeof(*config_page));
645  out:
646  return r;
647 }
648 
658 int
660  Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
661 {
662  Mpi2ConfigRequest_t mpi_request;
663  int r;
664 
665  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
666  mpi_request.Function = MPI2_FUNCTION_CONFIG;
669  mpi_request.Header.PageNumber = 1;
672  r = _config_request(ioc, &mpi_request, mpi_reply,
674  if (r)
675  goto out;
676 
678  r = _config_request(ioc, &mpi_request, mpi_reply,
680  sizeof(*config_page));
681  out:
682  return r;
683 }
684 
695 int
697  Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz)
698 {
699  Mpi2ConfigRequest_t mpi_request;
700  int r;
701 
702  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
703  mpi_request.Function = MPI2_FUNCTION_CONFIG;
706  mpi_request.Header.PageNumber = 3;
709  r = _config_request(ioc, &mpi_request, mpi_reply,
711  if (r)
712  goto out;
713 
715  r = _config_request(ioc, &mpi_request, mpi_reply,
716  MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
717  out:
718  return r;
719 }
720 
730 int
732  Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
733 {
734  Mpi2ConfigRequest_t mpi_request;
735  int r;
736 
737  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
738  mpi_request.Function = MPI2_FUNCTION_CONFIG;
741  mpi_request.Header.PageNumber = 8;
744  r = _config_request(ioc, &mpi_request, mpi_reply,
746  if (r)
747  goto out;
748 
750  r = _config_request(ioc, &mpi_request, mpi_reply,
752  sizeof(*config_page));
753  out:
754  return r;
755 }
756 
768 int
770  *mpi_reply, Mpi2SasDevicePage0_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;
781  mpi_request.Header.PageNumber = 0;
783  r = _config_request(ioc, &mpi_request, mpi_reply,
785  if (r)
786  goto out;
787 
788  mpi_request.PageAddress = cpu_to_le32(form | handle);
790  r = _config_request(ioc, &mpi_request, mpi_reply,
792  sizeof(*config_page));
793  out:
794  return r;
795 }
796 
808 int
810  *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle)
811 {
812  Mpi2ConfigRequest_t mpi_request;
813  int r;
814 
815  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
816  mpi_request.Function = MPI2_FUNCTION_CONFIG;
821  mpi_request.Header.PageNumber = 1;
823  r = _config_request(ioc, &mpi_request, mpi_reply,
825  if (r)
826  goto out;
827 
828  mpi_request.PageAddress = cpu_to_le32(form | handle);
830  r = _config_request(ioc, &mpi_request, mpi_reply,
832  sizeof(*config_page));
833  out:
834  return r;
835 }
836 
845 int
847 {
848  Mpi2ConfigRequest_t mpi_request;
849  int r;
850  u16 ioc_status;
851  Mpi2ConfigReply_t mpi_reply;
852  Mpi2SasIOUnitPage0_t config_page;
853 
854  *num_phys = 0;
855  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
856  mpi_request.Function = MPI2_FUNCTION_CONFIG;
860  mpi_request.Header.PageNumber = 0;
863  r = _config_request(ioc, &mpi_request, &mpi_reply,
865  if (r)
866  goto out;
867 
869  r = _config_request(ioc, &mpi_request, &mpi_reply,
870  MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
871  sizeof(Mpi2SasIOUnitPage0_t));
872  if (!r) {
873  ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
875  if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
876  *num_phys = config_page.NumPhys;
877  }
878  out:
879  return r;
880 }
881 
895 int
897  *mpi_reply, Mpi2SasIOUnitPage0_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;
907  mpi_request.Header.PageNumber = 0;
910  r = _config_request(ioc, &mpi_request, mpi_reply,
912  if (r)
913  goto out;
914 
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 
935 int
937  *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz)
938 {
939  Mpi2ConfigRequest_t mpi_request;
940  int r;
941 
942  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
943  mpi_request.Function = MPI2_FUNCTION_CONFIG;
947  mpi_request.Header.PageNumber = 1;
950  r = _config_request(ioc, &mpi_request, mpi_reply,
952  if (r)
953  goto out;
954 
956  r = _config_request(ioc, &mpi_request, mpi_reply,
957  MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
958  out:
959  return r;
960 }
961 
975 int
977  *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz)
978 {
979  Mpi2ConfigRequest_t mpi_request;
980  int r;
981 
982  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
983  mpi_request.Function = MPI2_FUNCTION_CONFIG;
987  mpi_request.Header.PageNumber = 1;
990  r = _config_request(ioc, &mpi_request, mpi_reply,
992  if (r)
993  goto out;
994 
996  _config_request(ioc, &mpi_request, mpi_reply,
997  MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
999  r = _config_request(ioc, &mpi_request, mpi_reply,
1000  MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1001  out:
1002  return r;
1003 }
1004 
1016 int
1018  *mpi_reply, Mpi2ExpanderPage0_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;
1028  mpi_request.Header.PageNumber = 0;
1031  r = _config_request(ioc, &mpi_request, mpi_reply,
1033  if (r)
1034  goto out;
1035 
1036  mpi_request.PageAddress = cpu_to_le32(form | handle);
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 
1056 int
1058  *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1059  u16 handle)
1060 {
1061  Mpi2ConfigRequest_t mpi_request;
1062  int r;
1063 
1064  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1065  mpi_request.Function = MPI2_FUNCTION_CONFIG;
1066  mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1069  mpi_request.Header.PageNumber = 1;
1072  r = _config_request(ioc, &mpi_request, mpi_reply,
1074  if (r)
1075  goto out;
1076 
1077  mpi_request.PageAddress =
1079  (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1081  r = _config_request(ioc, &mpi_request, mpi_reply,
1082  MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1083  sizeof(*config_page));
1084  out:
1085  return r;
1086 }
1087 
1099 int
1101  *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1102 {
1103  Mpi2ConfigRequest_t mpi_request;
1104  int r;
1105 
1106  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1107  mpi_request.Function = MPI2_FUNCTION_CONFIG;
1108  mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1111  mpi_request.Header.PageNumber = 0;
1114  r = _config_request(ioc, &mpi_request, mpi_reply,
1116  if (r)
1117  goto out;
1118 
1119  mpi_request.PageAddress = cpu_to_le32(form | handle);
1121  r = _config_request(ioc, &mpi_request, mpi_reply,
1122  MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1123  sizeof(*config_page));
1124  out:
1125  return r;
1126 }
1127 
1138 int
1140  *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1141 {
1142  Mpi2ConfigRequest_t mpi_request;
1143  int r;
1144 
1145  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1146  mpi_request.Function = MPI2_FUNCTION_CONFIG;
1147  mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1150  mpi_request.Header.PageNumber = 0;
1153  r = _config_request(ioc, &mpi_request, mpi_reply,
1155  if (r)
1156  goto out;
1157 
1158  mpi_request.PageAddress =
1161  r = _config_request(ioc, &mpi_request, mpi_reply,
1162  MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1163  sizeof(*config_page));
1164  out:
1165  return r;
1166 }
1167 
1178 int
1180  *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1181 {
1182  Mpi2ConfigRequest_t mpi_request;
1183  int r;
1184 
1185  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1186  mpi_request.Function = MPI2_FUNCTION_CONFIG;
1187  mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1190  mpi_request.Header.PageNumber = 1;
1193  r = _config_request(ioc, &mpi_request, mpi_reply,
1195  if (r)
1196  goto out;
1197 
1198  mpi_request.PageAddress =
1201  r = _config_request(ioc, &mpi_request, mpi_reply,
1202  MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1203  sizeof(*config_page));
1204  out:
1205  return r;
1206 }
1207 
1219 int
1221  Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1222  u32 handle)
1223 {
1224  Mpi2ConfigRequest_t mpi_request;
1225  int r;
1226 
1227  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1228  mpi_request.Function = MPI2_FUNCTION_CONFIG;
1229  mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1231  mpi_request.Header.PageNumber = 1;
1234  r = _config_request(ioc, &mpi_request, mpi_reply,
1236  if (r)
1237  goto out;
1238 
1239  mpi_request.PageAddress = cpu_to_le32(form | handle);
1241  r = _config_request(ioc, &mpi_request, mpi_reply,
1242  MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1243  sizeof(*config_page));
1244  out:
1245  return r;
1246 }
1247 
1257 int
1259  u8 *num_pds)
1260 {
1261  Mpi2ConfigRequest_t mpi_request;
1262  Mpi2RaidVolPage0_t config_page;
1263  Mpi2ConfigReply_t mpi_reply;
1264  int r;
1265  u16 ioc_status;
1266 
1267  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1268  *num_pds = 0;
1269  mpi_request.Function = MPI2_FUNCTION_CONFIG;
1270  mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1272  mpi_request.Header.PageNumber = 0;
1275  r = _config_request(ioc, &mpi_request, &mpi_reply,
1277  if (r)
1278  goto out;
1279 
1280  mpi_request.PageAddress =
1283  r = _config_request(ioc, &mpi_request, &mpi_reply,
1284  MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1285  sizeof(Mpi2RaidVolPage0_t));
1286  if (!r) {
1287  ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1289  if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1290  *num_pds = config_page.NumPhysDisks;
1291  }
1292 
1293  out:
1294  return r;
1295 }
1296 
1309 int
1311  Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1312  u32 handle, u16 sz)
1313 {
1314  Mpi2ConfigRequest_t mpi_request;
1315  int r;
1316 
1317  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1318  mpi_request.Function = MPI2_FUNCTION_CONFIG;
1319  mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1321  mpi_request.Header.PageNumber = 0;
1324  r = _config_request(ioc, &mpi_request, mpi_reply,
1326  if (r)
1327  goto out;
1328 
1329  mpi_request.PageAddress = cpu_to_le32(form | handle);
1331  r = _config_request(ioc, &mpi_request, mpi_reply,
1332  MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1333  out:
1334  return r;
1335 }
1336 
1348 int
1350  *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1351  u32 form_specific)
1352 {
1353  Mpi2ConfigRequest_t mpi_request;
1354  int r;
1355 
1356  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1357  mpi_request.Function = MPI2_FUNCTION_CONFIG;
1358  mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1360  mpi_request.Header.PageNumber = 0;
1363  r = _config_request(ioc, &mpi_request, mpi_reply,
1365  if (r)
1366  goto out;
1367 
1368  mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1370  r = _config_request(ioc, &mpi_request, mpi_reply,
1371  MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1372  sizeof(*config_page));
1373  out:
1374  return r;
1375 }
1376 
1386 int
1388  u16 *volume_handle)
1389 {
1390  Mpi2RaidConfigurationPage0_t *config_page = NULL;
1391  Mpi2ConfigRequest_t mpi_request;
1392  Mpi2ConfigReply_t mpi_reply;
1393  int r, i, config_page_sz;
1394  u16 ioc_status;
1395  int config_num;
1396  u16 element_type;
1397  u16 phys_disk_dev_handle;
1398 
1399  *volume_handle = 0;
1400  memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1401  mpi_request.Function = MPI2_FUNCTION_CONFIG;
1402  mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1406  mpi_request.Header.PageNumber = 0;
1408  r = _config_request(ioc, &mpi_request, &mpi_reply,
1410  if (r)
1411  goto out;
1412 
1414  config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
1415  config_page = kmalloc(config_page_sz, GFP_KERNEL);
1416  if (!config_page) {
1417  r = -1;
1418  goto out;
1419  }
1420  config_num = 0xff;
1421  while (1) {
1422  mpi_request.PageAddress = cpu_to_le32(config_num +
1424  r = _config_request(ioc, &mpi_request, &mpi_reply,
1425  MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1426  config_page_sz);
1427  if (r)
1428  goto out;
1429  r = -1;
1430  ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1432  if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
1433  goto out;
1434  for (i = 0; i < config_page->NumElements; i++) {
1435  element_type = le16_to_cpu(config_page->
1436  ConfigElement[i].ElementFlags) &
1438  if (element_type ==
1440  element_type ==
1442  phys_disk_dev_handle =
1443  le16_to_cpu(config_page->ConfigElement[i].
1444  PhysDiskDevHandle);
1445  if (phys_disk_dev_handle == pd_handle) {
1446  *volume_handle =
1447  le16_to_cpu(config_page->
1448  ConfigElement[i].VolDevHandle);
1449  r = 0;
1450  goto out;
1451  }
1452  } else if (element_type ==
1454  *volume_handle = 0;
1455  r = 0;
1456  goto out;
1457  }
1458  }
1459  config_num = config_page->ConfigNum;
1460  }
1461  out:
1462  kfree(config_page);
1463  return r;
1464 }
1465 
1475 int
1477  u64 *wwid)
1478 {
1479  Mpi2ConfigReply_t mpi_reply;
1480  Mpi2RaidVolPage1_t raid_vol_pg1;
1481 
1482  *wwid = 0;
1483  if (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1484  &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
1485  volume_handle))) {
1486  *wwid = le64_to_cpu(raid_vol_pg1.WWID);
1487  return 0;
1488  } else
1489  return -1;
1490 }