mpt3sas_config.c 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650
  1. /*
  2. * This module provides common API for accessing firmware configuration pages
  3. *
  4. * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c
  5. * Copyright (C) 2012 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 "mpt3sas_base.h"
  52. /* local definitions */
  53. /* Timeout for config page request (in seconds) */
  54. #define MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT 15
  55. /* Common sgl flags for READING a config page. */
  56. #define MPT3_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
  57. MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
  58. | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT)
  59. /* Common sgl flags for WRITING a config page. */
  60. #define MPT3_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
  61. MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
  62. | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \
  63. << MPI2_SGE_FLAGS_SHIFT)
  64. /**
  65. * struct config_request - obtain dma memory via routine
  66. * @sz: size
  67. * @page: virt pointer
  68. * @page_dma: phys pointer
  69. *
  70. */
  71. struct config_request {
  72. u16 sz;
  73. void *page;
  74. dma_addr_t page_dma;
  75. };
  76. #ifdef CONFIG_SCSI_MPT3SAS_LOGGING
  77. /**
  78. * _config_display_some_debug - debug routine
  79. * @ioc: per adapter object
  80. * @smid: system request message index
  81. * @calling_function_name: string pass from calling function
  82. * @mpi_reply: reply message frame
  83. * Context: none.
  84. *
  85. * Function for displaying debug info helpful when debugging issues
  86. * in this module.
  87. */
  88. static void
  89. _config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
  90. char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
  91. {
  92. Mpi2ConfigRequest_t *mpi_request;
  93. char *desc = NULL;
  94. if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
  95. return;
  96. mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
  97. switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) {
  98. case MPI2_CONFIG_PAGETYPE_IO_UNIT:
  99. desc = "io_unit";
  100. break;
  101. case MPI2_CONFIG_PAGETYPE_IOC:
  102. desc = "ioc";
  103. break;
  104. case MPI2_CONFIG_PAGETYPE_BIOS:
  105. desc = "bios";
  106. break;
  107. case MPI2_CONFIG_PAGETYPE_RAID_VOLUME:
  108. desc = "raid_volume";
  109. break;
  110. case MPI2_CONFIG_PAGETYPE_MANUFACTURING:
  111. desc = "manufaucturing";
  112. break;
  113. case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK:
  114. desc = "physdisk";
  115. break;
  116. case MPI2_CONFIG_PAGETYPE_EXTENDED:
  117. switch (mpi_request->ExtPageType) {
  118. case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT:
  119. desc = "sas_io_unit";
  120. break;
  121. case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER:
  122. desc = "sas_expander";
  123. break;
  124. case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE:
  125. desc = "sas_device";
  126. break;
  127. case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY:
  128. desc = "sas_phy";
  129. break;
  130. case MPI2_CONFIG_EXTPAGETYPE_LOG:
  131. desc = "log";
  132. break;
  133. case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE:
  134. desc = "enclosure";
  135. break;
  136. case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG:
  137. desc = "raid_config";
  138. break;
  139. case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
  140. desc = "driver_mappping";
  141. break;
  142. }
  143. break;
  144. }
  145. if (!desc)
  146. return;
  147. pr_info(MPT3SAS_FMT
  148. "%s: %s(%d), action(%d), form(0x%08x), smid(%d)\n",
  149. 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. pr_info(MPT3SAS_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 MPT3SAS_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. pr_err(MPT3SAS_FMT
  180. "%s: dma_alloc_coherent 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 MPT3SAS_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. * mpt3sas_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. mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
  222. u32 reply)
  223. {
  224. MPI2DefaultReply_t *mpi_reply;
  225. if (ioc->config_cmds.status == MPT3_CMD_NOT_USED)
  226. return 1;
  227. if (ioc->config_cmds.smid != smid)
  228. return 1;
  229. ioc->config_cmds.status |= MPT3_CMD_COMPLETE;
  230. mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
  231. if (mpi_reply) {
  232. ioc->config_cmds.status |= MPT3_CMD_REPLY_VALID;
  233. memcpy(ioc->config_cmds.reply, mpi_reply,
  234. mpi_reply->MsgLength*4);
  235. }
  236. ioc->config_cmds.status &= ~MPT3_CMD_PENDING;
  237. #ifdef CONFIG_SCSI_MPT3SAS_LOGGING
  238. _config_display_some_debug(ioc, smid, "config_done", mpi_reply);
  239. #endif
  240. ioc->config_cmds.smid = USHRT_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 MPT3_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 MPT3SAS_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. u32 ioc_status = UINT_MAX;
  277. mutex_lock(&ioc->config_cmds.mutex);
  278. if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) {
  279. pr_err(MPT3SAS_FMT "%s: config_cmd in use\n",
  280. ioc->name, __func__);
  281. mutex_unlock(&ioc->config_cmds.mutex);
  282. return -EAGAIN;
  283. }
  284. retry_count = 0;
  285. memset(&mem, 0, sizeof(struct config_request));
  286. mpi_request->VF_ID = 0; /* TODO */
  287. mpi_request->VP_ID = 0;
  288. if (config_page) {
  289. mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
  290. mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
  291. mpi_request->Header.PageType = mpi_reply->Header.PageType;
  292. mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
  293. mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
  294. mpi_request->ExtPageType = mpi_reply->ExtPageType;
  295. if (mpi_request->Header.PageLength)
  296. mem.sz = mpi_request->Header.PageLength * 4;
  297. else
  298. mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
  299. r = _config_alloc_config_dma_memory(ioc, &mem);
  300. if (r != 0)
  301. goto out;
  302. if (mpi_request->Action ==
  303. MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
  304. mpi_request->Action ==
  305. MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
  306. ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
  307. MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz,
  308. mem.page_dma);
  309. memcpy(mem.page, config_page, min_t(u16, mem.sz,
  310. config_page_sz));
  311. } else {
  312. memset(config_page, 0, config_page_sz);
  313. ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
  314. MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma);
  315. memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz));
  316. }
  317. }
  318. retry_config:
  319. if (retry_count) {
  320. if (retry_count > 2) { /* attempt only 2 retries */
  321. r = -EFAULT;
  322. goto free_mem;
  323. }
  324. pr_info(MPT3SAS_FMT "%s: attempting retry (%d)\n",
  325. ioc->name, __func__, retry_count);
  326. }
  327. wait_state_count = 0;
  328. ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
  329. while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
  330. if (wait_state_count++ == MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT) {
  331. pr_err(MPT3SAS_FMT
  332. "%s: failed due to ioc not operational\n",
  333. ioc->name, __func__);
  334. ioc->config_cmds.status = MPT3_CMD_NOT_USED;
  335. r = -EFAULT;
  336. goto free_mem;
  337. }
  338. ssleep(1);
  339. ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
  340. pr_info(MPT3SAS_FMT
  341. "%s: waiting for operational state(count=%d)\n",
  342. ioc->name, __func__, wait_state_count);
  343. }
  344. if (wait_state_count)
  345. pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
  346. ioc->name, __func__);
  347. smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx);
  348. if (!smid) {
  349. pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
  350. ioc->name, __func__);
  351. ioc->config_cmds.status = MPT3_CMD_NOT_USED;
  352. r = -EAGAIN;
  353. goto free_mem;
  354. }
  355. r = 0;
  356. memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
  357. ioc->config_cmds.status = MPT3_CMD_PENDING;
  358. config_request = mpt3sas_base_get_msg_frame(ioc, smid);
  359. ioc->config_cmds.smid = smid;
  360. memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
  361. #ifdef CONFIG_SCSI_MPT3SAS_LOGGING
  362. _config_display_some_debug(ioc, smid, "config_request", NULL);
  363. #endif
  364. init_completion(&ioc->config_cmds.done);
  365. mpt3sas_base_put_smid_default(ioc, smid);
  366. timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
  367. timeout*HZ);
  368. if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
  369. pr_err(MPT3SAS_FMT "%s: timeout\n",
  370. ioc->name, __func__);
  371. _debug_dump_mf(mpi_request,
  372. sizeof(Mpi2ConfigRequest_t)/4);
  373. retry_count++;
  374. if (ioc->config_cmds.smid == smid)
  375. mpt3sas_base_free_smid(ioc, smid);
  376. if ((ioc->shost_recovery) || (ioc->config_cmds.status &
  377. MPT3_CMD_RESET) || ioc->pci_error_recovery)
  378. goto retry_config;
  379. issue_host_reset = 1;
  380. r = -EFAULT;
  381. goto free_mem;
  382. }
  383. if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) {
  384. memcpy(mpi_reply, ioc->config_cmds.reply,
  385. sizeof(Mpi2ConfigReply_t));
  386. /* Reply Frame Sanity Checks to workaround FW issues */
  387. if ((mpi_request->Header.PageType & 0xF) !=
  388. (mpi_reply->Header.PageType & 0xF)) {
  389. _debug_dump_mf(mpi_request, ioc->request_sz/4);
  390. _debug_dump_reply(mpi_reply, ioc->request_sz/4);
  391. panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \
  392. " mpi_reply mismatch: Requested PageType(0x%02x)" \
  393. " Reply PageType(0x%02x)\n", \
  394. ioc->name, __func__,
  395. (mpi_request->Header.PageType & 0xF),
  396. (mpi_reply->Header.PageType & 0xF));
  397. }
  398. if (((mpi_request->Header.PageType & 0xF) ==
  399. MPI2_CONFIG_PAGETYPE_EXTENDED) &&
  400. mpi_request->ExtPageType != mpi_reply->ExtPageType) {
  401. _debug_dump_mf(mpi_request, ioc->request_sz/4);
  402. _debug_dump_reply(mpi_reply, ioc->request_sz/4);
  403. panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \
  404. " mpi_reply mismatch: Requested ExtPageType(0x%02x)"
  405. " Reply ExtPageType(0x%02x)\n",
  406. ioc->name, __func__, mpi_request->ExtPageType,
  407. mpi_reply->ExtPageType);
  408. }
  409. ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
  410. & MPI2_IOCSTATUS_MASK;
  411. }
  412. if (retry_count)
  413. pr_info(MPT3SAS_FMT "%s: retry (%d) completed!!\n", \
  414. ioc->name, __func__, retry_count);
  415. if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
  416. config_page && mpi_request->Action ==
  417. MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) {
  418. u8 *p = (u8 *)mem.page;
  419. /* Config Page Sanity Checks to workaround FW issues */
  420. if (p) {
  421. if ((mpi_request->Header.PageType & 0xF) !=
  422. (p[3] & 0xF)) {
  423. _debug_dump_mf(mpi_request, ioc->request_sz/4);
  424. _debug_dump_reply(mpi_reply, ioc->request_sz/4);
  425. _debug_dump_config(p, min_t(u16, mem.sz,
  426. config_page_sz)/4);
  427. panic(KERN_WARNING MPT3SAS_FMT
  428. "%s: Firmware BUG:" \
  429. " config page mismatch:"
  430. " Requested PageType(0x%02x)"
  431. " Reply PageType(0x%02x)\n",
  432. ioc->name, __func__,
  433. (mpi_request->Header.PageType & 0xF),
  434. (p[3] & 0xF));
  435. }
  436. if (((mpi_request->Header.PageType & 0xF) ==
  437. MPI2_CONFIG_PAGETYPE_EXTENDED) &&
  438. (mpi_request->ExtPageType != p[6])) {
  439. _debug_dump_mf(mpi_request, ioc->request_sz/4);
  440. _debug_dump_reply(mpi_reply, ioc->request_sz/4);
  441. _debug_dump_config(p, min_t(u16, mem.sz,
  442. config_page_sz)/4);
  443. panic(KERN_WARNING MPT3SAS_FMT
  444. "%s: Firmware BUG:" \
  445. " config page mismatch:"
  446. " Requested ExtPageType(0x%02x)"
  447. " Reply ExtPageType(0x%02x)\n",
  448. ioc->name, __func__,
  449. mpi_request->ExtPageType, p[6]);
  450. }
  451. }
  452. memcpy(config_page, mem.page, min_t(u16, mem.sz,
  453. config_page_sz));
  454. }
  455. free_mem:
  456. if (config_page)
  457. _config_free_config_dma_memory(ioc, &mem);
  458. out:
  459. ioc->config_cmds.status = MPT3_CMD_NOT_USED;
  460. mutex_unlock(&ioc->config_cmds.mutex);
  461. if (issue_host_reset)
  462. mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
  463. FORCE_BIG_HAMMER);
  464. return r;
  465. }
  466. /**
  467. * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
  468. * @ioc: per adapter object
  469. * @mpi_reply: reply mf payload returned from firmware
  470. * @config_page: contents of the config page
  471. * Context: sleep.
  472. *
  473. * Returns 0 for success, non-zero for failure.
  474. */
  475. int
  476. mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
  477. Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
  478. {
  479. Mpi2ConfigRequest_t mpi_request;
  480. int r;
  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 = 0;
  486. mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
  487. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  488. r = _config_request(ioc, &mpi_request, mpi_reply,
  489. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  490. if (r)
  491. goto out;
  492. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  493. r = _config_request(ioc, &mpi_request, mpi_reply,
  494. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  495. sizeof(*config_page));
  496. out:
  497. return r;
  498. }
  499. /**
  500. * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7
  501. * @ioc: per adapter object
  502. * @mpi_reply: reply mf payload returned from firmware
  503. * @config_page: contents of the config page
  504. * @sz: size of buffer passed in config_page
  505. * Context: sleep.
  506. *
  507. * Returns 0 for success, non-zero for failure.
  508. */
  509. int
  510. mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
  511. Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
  512. u16 sz)
  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_MANUFACTURING;
  520. mpi_request.Header.PageNumber = 7;
  521. mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION;
  522. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  523. r = _config_request(ioc, &mpi_request, mpi_reply,
  524. MPT3_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. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  530. sz);
  531. out:
  532. return r;
  533. }
  534. /**
  535. * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
  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. mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
  545. Mpi2ConfigReply_t *mpi_reply,
  546. struct Mpi2ManufacturingPage10_t *config_page)
  547. {
  548. Mpi2ConfigRequest_t mpi_request;
  549. int r;
  550. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  551. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  552. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  553. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
  554. mpi_request.Header.PageNumber = 10;
  555. mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
  556. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  557. r = _config_request(ioc, &mpi_request, mpi_reply,
  558. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  559. if (r)
  560. goto out;
  561. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  562. r = _config_request(ioc, &mpi_request, mpi_reply,
  563. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  564. sizeof(*config_page));
  565. out:
  566. return r;
  567. }
  568. /**
  569. * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11
  570. * @ioc: per adapter object
  571. * @mpi_reply: reply mf payload returned from firmware
  572. * @config_page: contents of the config page
  573. * Context: sleep.
  574. *
  575. * Returns 0 for success, non-zero for failure.
  576. */
  577. int
  578. mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
  579. Mpi2ConfigReply_t *mpi_reply,
  580. struct Mpi2ManufacturingPage11_t *config_page)
  581. {
  582. Mpi2ConfigRequest_t mpi_request;
  583. int r;
  584. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  585. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  586. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  587. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
  588. mpi_request.Header.PageNumber = 11;
  589. mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
  590. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  591. r = _config_request(ioc, &mpi_request, mpi_reply,
  592. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  593. if (r)
  594. goto out;
  595. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  596. r = _config_request(ioc, &mpi_request, mpi_reply,
  597. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  598. sizeof(*config_page));
  599. out:
  600. return r;
  601. }
  602. /**
  603. * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11
  604. * @ioc: per adapter object
  605. * @mpi_reply: reply mf payload returned from firmware
  606. * @config_page: contents of the config page
  607. * Context: sleep.
  608. *
  609. * Returns 0 for success, non-zero for failure.
  610. */
  611. int
  612. mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
  613. Mpi2ConfigReply_t *mpi_reply,
  614. struct Mpi2ManufacturingPage11_t *config_page)
  615. {
  616. Mpi2ConfigRequest_t mpi_request;
  617. int r;
  618. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  619. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  620. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  621. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
  622. mpi_request.Header.PageNumber = 11;
  623. mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
  624. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  625. r = _config_request(ioc, &mpi_request, mpi_reply,
  626. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  627. if (r)
  628. goto out;
  629. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
  630. r = _config_request(ioc, &mpi_request, mpi_reply,
  631. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  632. sizeof(*config_page));
  633. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
  634. r = _config_request(ioc, &mpi_request, mpi_reply,
  635. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  636. sizeof(*config_page));
  637. out:
  638. return r;
  639. }
  640. /**
  641. * mpt3sas_config_get_bios_pg2 - obtain bios page 2
  642. * @ioc: per adapter object
  643. * @mpi_reply: reply mf payload returned from firmware
  644. * @config_page: contents of the config page
  645. * Context: sleep.
  646. *
  647. * Returns 0 for success, non-zero for failure.
  648. */
  649. int
  650. mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc,
  651. Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
  652. {
  653. Mpi2ConfigRequest_t mpi_request;
  654. int r;
  655. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  656. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  657. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  658. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
  659. mpi_request.Header.PageNumber = 2;
  660. mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
  661. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  662. r = _config_request(ioc, &mpi_request, mpi_reply,
  663. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  664. if (r)
  665. goto out;
  666. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  667. r = _config_request(ioc, &mpi_request, mpi_reply,
  668. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  669. sizeof(*config_page));
  670. out:
  671. return r;
  672. }
  673. /**
  674. * mpt3sas_config_get_bios_pg3 - obtain bios page 3
  675. * @ioc: per adapter object
  676. * @mpi_reply: reply mf payload returned from firmware
  677. * @config_page: contents of the config page
  678. * Context: sleep.
  679. *
  680. * Returns 0 for success, non-zero for failure.
  681. */
  682. int
  683. mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
  684. *mpi_reply, Mpi2BiosPage3_t *config_page)
  685. {
  686. Mpi2ConfigRequest_t mpi_request;
  687. int r;
  688. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  689. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  690. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  691. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
  692. mpi_request.Header.PageNumber = 3;
  693. mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
  694. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  695. r = _config_request(ioc, &mpi_request, mpi_reply,
  696. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  697. if (r)
  698. goto out;
  699. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  700. r = _config_request(ioc, &mpi_request, mpi_reply,
  701. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  702. sizeof(*config_page));
  703. out:
  704. return r;
  705. }
  706. /**
  707. * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
  708. * @ioc: per adapter object
  709. * @mpi_reply: reply mf payload returned from firmware
  710. * @config_page: contents of the config page
  711. * Context: sleep.
  712. *
  713. * Returns 0 for success, non-zero for failure.
  714. */
  715. int
  716. mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
  717. Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
  718. {
  719. Mpi2ConfigRequest_t mpi_request;
  720. int r;
  721. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  722. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  723. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  724. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
  725. mpi_request.Header.PageNumber = 0;
  726. mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
  727. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  728. r = _config_request(ioc, &mpi_request, mpi_reply,
  729. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  730. if (r)
  731. goto out;
  732. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  733. r = _config_request(ioc, &mpi_request, mpi_reply,
  734. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  735. sizeof(*config_page));
  736. out:
  737. return r;
  738. }
  739. /**
  740. * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1
  741. * @ioc: per adapter object
  742. * @mpi_reply: reply mf payload returned from firmware
  743. * @config_page: contents of the config page
  744. * Context: sleep.
  745. *
  746. * Returns 0 for success, non-zero for failure.
  747. */
  748. int
  749. mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
  750. Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
  751. {
  752. Mpi2ConfigRequest_t mpi_request;
  753. int r;
  754. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  755. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  756. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  757. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
  758. mpi_request.Header.PageNumber = 1;
  759. mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
  760. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  761. r = _config_request(ioc, &mpi_request, mpi_reply,
  762. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  763. if (r)
  764. goto out;
  765. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  766. r = _config_request(ioc, &mpi_request, mpi_reply,
  767. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  768. sizeof(*config_page));
  769. out:
  770. return r;
  771. }
  772. /**
  773. * mpt3sas_config_set_iounit_pg1 - set iounit page 1
  774. * @ioc: per adapter object
  775. * @mpi_reply: reply mf payload returned from firmware
  776. * @config_page: contents of the config page
  777. * Context: sleep.
  778. *
  779. * Returns 0 for success, non-zero for failure.
  780. */
  781. int
  782. mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
  783. Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
  784. {
  785. Mpi2ConfigRequest_t mpi_request;
  786. int r;
  787. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  788. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  789. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  790. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
  791. mpi_request.Header.PageNumber = 1;
  792. mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
  793. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  794. r = _config_request(ioc, &mpi_request, mpi_reply,
  795. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  796. if (r)
  797. goto out;
  798. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
  799. r = _config_request(ioc, &mpi_request, mpi_reply,
  800. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  801. sizeof(*config_page));
  802. out:
  803. return r;
  804. }
  805. /**
  806. * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8
  807. * @ioc: per adapter object
  808. * @mpi_reply: reply mf payload returned from firmware
  809. * @config_page: contents of the config page
  810. * Context: sleep.
  811. *
  812. * Returns 0 for success, non-zero for failure.
  813. */
  814. int
  815. mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
  816. Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
  817. {
  818. Mpi2ConfigRequest_t mpi_request;
  819. int r;
  820. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  821. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  822. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  823. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
  824. mpi_request.Header.PageNumber = 8;
  825. mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
  826. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  827. r = _config_request(ioc, &mpi_request, mpi_reply,
  828. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  829. if (r)
  830. goto out;
  831. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  832. r = _config_request(ioc, &mpi_request, mpi_reply,
  833. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  834. sizeof(*config_page));
  835. out:
  836. return r;
  837. }
  838. /**
  839. * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
  840. * @ioc: per adapter object
  841. * @mpi_reply: reply mf payload returned from firmware
  842. * @config_page: contents of the config page
  843. * @form: GET_NEXT_HANDLE or HANDLE
  844. * @handle: device handle
  845. * Context: sleep.
  846. *
  847. * Returns 0 for success, non-zero for failure.
  848. */
  849. int
  850. mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
  851. Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
  852. u32 form, u32 handle)
  853. {
  854. Mpi2ConfigRequest_t mpi_request;
  855. int r;
  856. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  857. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  858. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  859. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  860. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
  861. mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
  862. mpi_request.Header.PageNumber = 0;
  863. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  864. r = _config_request(ioc, &mpi_request, mpi_reply,
  865. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  866. if (r)
  867. goto out;
  868. mpi_request.PageAddress = cpu_to_le32(form | handle);
  869. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  870. r = _config_request(ioc, &mpi_request, mpi_reply,
  871. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  872. sizeof(*config_page));
  873. out:
  874. return r;
  875. }
  876. /**
  877. * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
  878. * @ioc: per adapter object
  879. * @mpi_reply: reply mf payload returned from firmware
  880. * @config_page: contents of the config page
  881. * @form: GET_NEXT_HANDLE or HANDLE
  882. * @handle: device handle
  883. * Context: sleep.
  884. *
  885. * Returns 0 for success, non-zero for failure.
  886. */
  887. int
  888. mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
  889. Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
  890. u32 form, u32 handle)
  891. {
  892. Mpi2ConfigRequest_t mpi_request;
  893. int r;
  894. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  895. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  896. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  897. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  898. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
  899. mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
  900. mpi_request.Header.PageNumber = 1;
  901. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  902. r = _config_request(ioc, &mpi_request, mpi_reply,
  903. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  904. if (r)
  905. goto out;
  906. mpi_request.PageAddress = cpu_to_le32(form | handle);
  907. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  908. r = _config_request(ioc, &mpi_request, mpi_reply,
  909. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  910. sizeof(*config_page));
  911. out:
  912. return r;
  913. }
  914. /**
  915. * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
  916. * @ioc: per adapter object
  917. * @num_phys: pointer returned with the number of phys
  918. * Context: sleep.
  919. *
  920. * Returns 0 for success, non-zero for failure.
  921. */
  922. int
  923. mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
  924. {
  925. Mpi2ConfigRequest_t mpi_request;
  926. int r;
  927. u16 ioc_status;
  928. Mpi2ConfigReply_t mpi_reply;
  929. Mpi2SasIOUnitPage0_t config_page;
  930. *num_phys = 0;
  931. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  932. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  933. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  934. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  935. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
  936. mpi_request.Header.PageNumber = 0;
  937. mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
  938. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  939. r = _config_request(ioc, &mpi_request, &mpi_reply,
  940. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  941. if (r)
  942. goto out;
  943. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  944. r = _config_request(ioc, &mpi_request, &mpi_reply,
  945. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
  946. sizeof(Mpi2SasIOUnitPage0_t));
  947. if (!r) {
  948. ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
  949. MPI2_IOCSTATUS_MASK;
  950. if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
  951. *num_phys = config_page.NumPhys;
  952. }
  953. out:
  954. return r;
  955. }
  956. /**
  957. * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
  958. * @ioc: per adapter object
  959. * @mpi_reply: reply mf payload returned from firmware
  960. * @config_page: contents of the config page
  961. * @sz: size of buffer passed in config_page
  962. * Context: sleep.
  963. *
  964. * Calling function should call config_get_number_hba_phys prior to
  965. * this function, so enough memory is allocated for config_page.
  966. *
  967. * Returns 0 for success, non-zero for failure.
  968. */
  969. int
  970. mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
  971. Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
  972. u16 sz)
  973. {
  974. Mpi2ConfigRequest_t mpi_request;
  975. int r;
  976. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  977. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  978. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  979. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  980. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
  981. mpi_request.Header.PageNumber = 0;
  982. mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
  983. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  984. r = _config_request(ioc, &mpi_request, mpi_reply,
  985. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  986. if (r)
  987. goto out;
  988. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  989. r = _config_request(ioc, &mpi_request, mpi_reply,
  990. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
  991. out:
  992. return r;
  993. }
  994. /**
  995. * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
  996. * @ioc: per adapter object
  997. * @mpi_reply: reply mf payload returned from firmware
  998. * @config_page: contents of the config page
  999. * @sz: size of buffer passed in config_page
  1000. * Context: sleep.
  1001. *
  1002. * Calling function should call config_get_number_hba_phys prior to
  1003. * this function, so enough memory is allocated for config_page.
  1004. *
  1005. * Returns 0 for success, non-zero for failure.
  1006. */
  1007. int
  1008. mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
  1009. Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
  1010. u16 sz)
  1011. {
  1012. Mpi2ConfigRequest_t mpi_request;
  1013. int r;
  1014. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1015. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1016. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1017. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1018. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
  1019. mpi_request.Header.PageNumber = 1;
  1020. mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
  1021. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1022. r = _config_request(ioc, &mpi_request, mpi_reply,
  1023. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1024. if (r)
  1025. goto out;
  1026. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1027. r = _config_request(ioc, &mpi_request, mpi_reply,
  1028. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
  1029. out:
  1030. return r;
  1031. }
  1032. /**
  1033. * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
  1034. * @ioc: per adapter object
  1035. * @mpi_reply: reply mf payload returned from firmware
  1036. * @config_page: contents of the config page
  1037. * @sz: size of buffer passed in config_page
  1038. * Context: sleep.
  1039. *
  1040. * Calling function should call config_get_number_hba_phys prior to
  1041. * this function, so enough memory is allocated for config_page.
  1042. *
  1043. * Returns 0 for success, non-zero for failure.
  1044. */
  1045. int
  1046. mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
  1047. Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
  1048. u16 sz)
  1049. {
  1050. Mpi2ConfigRequest_t mpi_request;
  1051. int r;
  1052. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1053. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1054. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1055. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1056. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
  1057. mpi_request.Header.PageNumber = 1;
  1058. mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
  1059. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1060. r = _config_request(ioc, &mpi_request, mpi_reply,
  1061. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1062. if (r)
  1063. goto out;
  1064. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
  1065. _config_request(ioc, &mpi_request, mpi_reply,
  1066. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
  1067. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
  1068. r = _config_request(ioc, &mpi_request, mpi_reply,
  1069. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
  1070. out:
  1071. return r;
  1072. }
  1073. /**
  1074. * mpt3sas_config_get_expander_pg0 - obtain expander page 0
  1075. * @ioc: per adapter object
  1076. * @mpi_reply: reply mf payload returned from firmware
  1077. * @config_page: contents of the config page
  1078. * @form: GET_NEXT_HANDLE or HANDLE
  1079. * @handle: expander handle
  1080. * Context: sleep.
  1081. *
  1082. * Returns 0 for success, non-zero for failure.
  1083. */
  1084. int
  1085. mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
  1086. *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
  1087. {
  1088. Mpi2ConfigRequest_t mpi_request;
  1089. int r;
  1090. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1091. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1092. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1093. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1094. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
  1095. mpi_request.Header.PageNumber = 0;
  1096. mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
  1097. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1098. r = _config_request(ioc, &mpi_request, mpi_reply,
  1099. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1100. if (r)
  1101. goto out;
  1102. mpi_request.PageAddress = cpu_to_le32(form | handle);
  1103. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1104. r = _config_request(ioc, &mpi_request, mpi_reply,
  1105. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  1106. sizeof(*config_page));
  1107. out:
  1108. return r;
  1109. }
  1110. /**
  1111. * mpt3sas_config_get_expander_pg1 - obtain expander page 1
  1112. * @ioc: per adapter object
  1113. * @mpi_reply: reply mf payload returned from firmware
  1114. * @config_page: contents of the config page
  1115. * @phy_number: phy number
  1116. * @handle: expander handle
  1117. * Context: sleep.
  1118. *
  1119. * Returns 0 for success, non-zero for failure.
  1120. */
  1121. int
  1122. mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
  1123. *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
  1124. u16 handle)
  1125. {
  1126. Mpi2ConfigRequest_t mpi_request;
  1127. int r;
  1128. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1129. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1130. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1131. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1132. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
  1133. mpi_request.Header.PageNumber = 1;
  1134. mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
  1135. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1136. r = _config_request(ioc, &mpi_request, mpi_reply,
  1137. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1138. if (r)
  1139. goto out;
  1140. mpi_request.PageAddress =
  1141. cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
  1142. (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
  1143. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1144. r = _config_request(ioc, &mpi_request, mpi_reply,
  1145. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  1146. sizeof(*config_page));
  1147. out:
  1148. return r;
  1149. }
  1150. /**
  1151. * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
  1152. * @ioc: per adapter object
  1153. * @mpi_reply: reply mf payload returned from firmware
  1154. * @config_page: contents of the config page
  1155. * @form: GET_NEXT_HANDLE or HANDLE
  1156. * @handle: expander handle
  1157. * Context: sleep.
  1158. *
  1159. * Returns 0 for success, non-zero for failure.
  1160. */
  1161. int
  1162. mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
  1163. *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
  1164. {
  1165. Mpi2ConfigRequest_t mpi_request;
  1166. int r;
  1167. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1168. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1169. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1170. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1171. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
  1172. mpi_request.Header.PageNumber = 0;
  1173. mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
  1174. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1175. r = _config_request(ioc, &mpi_request, mpi_reply,
  1176. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1177. if (r)
  1178. goto out;
  1179. mpi_request.PageAddress = cpu_to_le32(form | handle);
  1180. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1181. r = _config_request(ioc, &mpi_request, mpi_reply,
  1182. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  1183. sizeof(*config_page));
  1184. out:
  1185. return r;
  1186. }
  1187. /**
  1188. * mpt3sas_config_get_phy_pg0 - obtain phy page 0
  1189. * @ioc: per adapter object
  1190. * @mpi_reply: reply mf payload returned from firmware
  1191. * @config_page: contents of the config page
  1192. * @phy_number: phy number
  1193. * Context: sleep.
  1194. *
  1195. * Returns 0 for success, non-zero for failure.
  1196. */
  1197. int
  1198. mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
  1199. *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
  1200. {
  1201. Mpi2ConfigRequest_t mpi_request;
  1202. int r;
  1203. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1204. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1205. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1206. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1207. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
  1208. mpi_request.Header.PageNumber = 0;
  1209. mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
  1210. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1211. r = _config_request(ioc, &mpi_request, mpi_reply,
  1212. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1213. if (r)
  1214. goto out;
  1215. mpi_request.PageAddress =
  1216. cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
  1217. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1218. r = _config_request(ioc, &mpi_request, mpi_reply,
  1219. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  1220. sizeof(*config_page));
  1221. out:
  1222. return r;
  1223. }
  1224. /**
  1225. * mpt3sas_config_get_phy_pg1 - obtain phy page 1
  1226. * @ioc: per adapter object
  1227. * @mpi_reply: reply mf payload returned from firmware
  1228. * @config_page: contents of the config page
  1229. * @phy_number: phy number
  1230. * Context: sleep.
  1231. *
  1232. * Returns 0 for success, non-zero for failure.
  1233. */
  1234. int
  1235. mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
  1236. *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
  1237. {
  1238. Mpi2ConfigRequest_t mpi_request;
  1239. int r;
  1240. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1241. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1242. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1243. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1244. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
  1245. mpi_request.Header.PageNumber = 1;
  1246. mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
  1247. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1248. r = _config_request(ioc, &mpi_request, mpi_reply,
  1249. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1250. if (r)
  1251. goto out;
  1252. mpi_request.PageAddress =
  1253. cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
  1254. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1255. r = _config_request(ioc, &mpi_request, mpi_reply,
  1256. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  1257. sizeof(*config_page));
  1258. out:
  1259. return r;
  1260. }
  1261. /**
  1262. * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
  1263. * @ioc: per adapter object
  1264. * @mpi_reply: reply mf payload returned from firmware
  1265. * @config_page: contents of the config page
  1266. * @form: GET_NEXT_HANDLE or HANDLE
  1267. * @handle: volume handle
  1268. * Context: sleep.
  1269. *
  1270. * Returns 0 for success, non-zero for failure.
  1271. */
  1272. int
  1273. mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
  1274. Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
  1275. u32 handle)
  1276. {
  1277. Mpi2ConfigRequest_t mpi_request;
  1278. int r;
  1279. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1280. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1281. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1282. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
  1283. mpi_request.Header.PageNumber = 1;
  1284. mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
  1285. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1286. r = _config_request(ioc, &mpi_request, mpi_reply,
  1287. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1288. if (r)
  1289. goto out;
  1290. mpi_request.PageAddress = cpu_to_le32(form | handle);
  1291. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1292. r = _config_request(ioc, &mpi_request, mpi_reply,
  1293. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  1294. sizeof(*config_page));
  1295. out:
  1296. return r;
  1297. }
  1298. /**
  1299. * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
  1300. * @ioc: per adapter object
  1301. * @handle: volume handle
  1302. * @num_pds: returns pds count
  1303. * Context: sleep.
  1304. *
  1305. * Returns 0 for success, non-zero for failure.
  1306. */
  1307. int
  1308. mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
  1309. u8 *num_pds)
  1310. {
  1311. Mpi2ConfigRequest_t mpi_request;
  1312. Mpi2RaidVolPage0_t config_page;
  1313. Mpi2ConfigReply_t mpi_reply;
  1314. int r;
  1315. u16 ioc_status;
  1316. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1317. *num_pds = 0;
  1318. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1319. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1320. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
  1321. mpi_request.Header.PageNumber = 0;
  1322. mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
  1323. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1324. r = _config_request(ioc, &mpi_request, &mpi_reply,
  1325. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1326. if (r)
  1327. goto out;
  1328. mpi_request.PageAddress =
  1329. cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
  1330. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1331. r = _config_request(ioc, &mpi_request, &mpi_reply,
  1332. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
  1333. sizeof(Mpi2RaidVolPage0_t));
  1334. if (!r) {
  1335. ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
  1336. MPI2_IOCSTATUS_MASK;
  1337. if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
  1338. *num_pds = config_page.NumPhysDisks;
  1339. }
  1340. out:
  1341. return r;
  1342. }
  1343. /**
  1344. * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
  1345. * @ioc: per adapter object
  1346. * @mpi_reply: reply mf payload returned from firmware
  1347. * @config_page: contents of the config page
  1348. * @form: GET_NEXT_HANDLE or HANDLE
  1349. * @handle: volume handle
  1350. * @sz: size of buffer passed in config_page
  1351. * Context: sleep.
  1352. *
  1353. * Returns 0 for success, non-zero for failure.
  1354. */
  1355. int
  1356. mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
  1357. Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
  1358. u32 handle, u16 sz)
  1359. {
  1360. Mpi2ConfigRequest_t mpi_request;
  1361. int r;
  1362. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1363. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1364. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1365. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
  1366. mpi_request.Header.PageNumber = 0;
  1367. mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
  1368. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1369. r = _config_request(ioc, &mpi_request, mpi_reply,
  1370. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1371. if (r)
  1372. goto out;
  1373. mpi_request.PageAddress = cpu_to_le32(form | handle);
  1374. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1375. r = _config_request(ioc, &mpi_request, mpi_reply,
  1376. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
  1377. out:
  1378. return r;
  1379. }
  1380. /**
  1381. * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
  1382. * @ioc: per adapter object
  1383. * @mpi_reply: reply mf payload returned from firmware
  1384. * @config_page: contents of the config page
  1385. * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
  1386. * @form_specific: specific to the form
  1387. * Context: sleep.
  1388. *
  1389. * Returns 0 for success, non-zero for failure.
  1390. */
  1391. int
  1392. mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
  1393. *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
  1394. u32 form_specific)
  1395. {
  1396. Mpi2ConfigRequest_t mpi_request;
  1397. int r;
  1398. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1399. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1400. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1401. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
  1402. mpi_request.Header.PageNumber = 0;
  1403. mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
  1404. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1405. r = _config_request(ioc, &mpi_request, mpi_reply,
  1406. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1407. if (r)
  1408. goto out;
  1409. mpi_request.PageAddress = cpu_to_le32(form | form_specific);
  1410. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1411. r = _config_request(ioc, &mpi_request, mpi_reply,
  1412. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  1413. sizeof(*config_page));
  1414. out:
  1415. return r;
  1416. }
  1417. /**
  1418. * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
  1419. * raid components
  1420. * @ioc: per adapter object
  1421. * @pd_handle: phys disk handle
  1422. * @volume_handle: volume handle
  1423. * Context: sleep.
  1424. *
  1425. * Returns 0 for success, non-zero for failure.
  1426. */
  1427. int
  1428. mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
  1429. u16 *volume_handle)
  1430. {
  1431. Mpi2RaidConfigurationPage0_t *config_page = NULL;
  1432. Mpi2ConfigRequest_t mpi_request;
  1433. Mpi2ConfigReply_t mpi_reply;
  1434. int r, i, config_page_sz;
  1435. u16 ioc_status;
  1436. int config_num;
  1437. u16 element_type;
  1438. u16 phys_disk_dev_handle;
  1439. *volume_handle = 0;
  1440. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1441. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1442. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1443. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1444. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
  1445. mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
  1446. mpi_request.Header.PageNumber = 0;
  1447. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1448. r = _config_request(ioc, &mpi_request, &mpi_reply,
  1449. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1450. if (r)
  1451. goto out;
  1452. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1453. config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
  1454. config_page = kmalloc(config_page_sz, GFP_KERNEL);
  1455. if (!config_page) {
  1456. r = -1;
  1457. goto out;
  1458. }
  1459. config_num = 0xff;
  1460. while (1) {
  1461. mpi_request.PageAddress = cpu_to_le32(config_num +
  1462. MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
  1463. r = _config_request(ioc, &mpi_request, &mpi_reply,
  1464. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  1465. config_page_sz);
  1466. if (r)
  1467. goto out;
  1468. r = -1;
  1469. ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
  1470. MPI2_IOCSTATUS_MASK;
  1471. if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
  1472. goto out;
  1473. for (i = 0; i < config_page->NumElements; i++) {
  1474. element_type = le16_to_cpu(config_page->
  1475. ConfigElement[i].ElementFlags) &
  1476. MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
  1477. if (element_type ==
  1478. MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
  1479. element_type ==
  1480. MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
  1481. phys_disk_dev_handle =
  1482. le16_to_cpu(config_page->ConfigElement[i].
  1483. PhysDiskDevHandle);
  1484. if (phys_disk_dev_handle == pd_handle) {
  1485. *volume_handle =
  1486. le16_to_cpu(config_page->
  1487. ConfigElement[i].VolDevHandle);
  1488. r = 0;
  1489. goto out;
  1490. }
  1491. } else if (element_type ==
  1492. MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
  1493. *volume_handle = 0;
  1494. r = 0;
  1495. goto out;
  1496. }
  1497. }
  1498. config_num = config_page->ConfigNum;
  1499. }
  1500. out:
  1501. kfree(config_page);
  1502. return r;
  1503. }
  1504. /**
  1505. * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
  1506. * @ioc: per adapter object
  1507. * @volume_handle: volume handle
  1508. * @wwid: volume wwid
  1509. * Context: sleep.
  1510. *
  1511. * Returns 0 for success, non-zero for failure.
  1512. */
  1513. int
  1514. mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
  1515. u64 *wwid)
  1516. {
  1517. Mpi2ConfigReply_t mpi_reply;
  1518. Mpi2RaidVolPage1_t raid_vol_pg1;
  1519. *wwid = 0;
  1520. if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
  1521. &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
  1522. volume_handle))) {
  1523. *wwid = le64_to_cpu(raid_vol_pg1.WWID);
  1524. return 0;
  1525. } else
  1526. return -1;
  1527. }