mpt2sas_config.c 45 KB

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