mpt3sas_config.c 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687
  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-2014 LSI Corporation
  6. * Copyright (C) 2013-2014 Avago Technologies
  7. * (mailto: MPT-FusionLinux.pdl@avagotech.com)
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 2
  12. * of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * NO WARRANTY
  20. * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
  21. * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
  22. * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
  23. * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
  24. * solely responsible for determining the appropriateness of using and
  25. * distributing the Program and assumes all risks associated with its
  26. * exercise of rights under this Agreement, including but not limited to
  27. * the risks and costs of program errors, damage to or loss of data,
  28. * programs or equipment, and unavailability or interruption of operations.
  29. * DISCLAIMER OF LIABILITY
  30. * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
  31. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  32. * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
  33. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  34. * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  35. * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
  36. * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
  37. * You should have received a copy of the GNU General Public License
  38. * along with this program; if not, write to the Free Software
  39. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
  40. * USA.
  41. */
  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_mapping";
  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_iounit_pg8 - obtain iounit 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_iounit_pg8(struct MPT3SAS_ADAPTER *ioc,
  816. Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_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_IO_UNIT;
  824. mpi_request.Header.PageNumber = 8;
  825. mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_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_ioc_pg8 - obtain ioc page 8
  840. * @ioc: per adapter object
  841. * @mpi_reply: reply mf payload returned from firmware
  842. * @config_page: contents of the config page
  843. * Context: sleep.
  844. *
  845. * Returns 0 for success, non-zero for failure.
  846. */
  847. int
  848. mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
  849. Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
  850. {
  851. Mpi2ConfigRequest_t mpi_request;
  852. int r;
  853. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  854. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  855. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  856. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
  857. mpi_request.Header.PageNumber = 8;
  858. mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
  859. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  860. r = _config_request(ioc, &mpi_request, mpi_reply,
  861. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  862. if (r)
  863. goto out;
  864. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  865. r = _config_request(ioc, &mpi_request, mpi_reply,
  866. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  867. sizeof(*config_page));
  868. out:
  869. return r;
  870. }
  871. /**
  872. * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
  873. * @ioc: per adapter object
  874. * @mpi_reply: reply mf payload returned from firmware
  875. * @config_page: contents of the config page
  876. * @form: GET_NEXT_HANDLE or HANDLE
  877. * @handle: device handle
  878. * Context: sleep.
  879. *
  880. * Returns 0 for success, non-zero for failure.
  881. */
  882. int
  883. mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
  884. Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
  885. u32 form, u32 handle)
  886. {
  887. Mpi2ConfigRequest_t mpi_request;
  888. int r;
  889. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  890. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  891. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  892. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  893. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
  894. mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
  895. mpi_request.Header.PageNumber = 0;
  896. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  897. r = _config_request(ioc, &mpi_request, mpi_reply,
  898. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  899. if (r)
  900. goto out;
  901. mpi_request.PageAddress = cpu_to_le32(form | handle);
  902. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  903. r = _config_request(ioc, &mpi_request, mpi_reply,
  904. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  905. sizeof(*config_page));
  906. out:
  907. return r;
  908. }
  909. /**
  910. * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
  911. * @ioc: per adapter object
  912. * @mpi_reply: reply mf payload returned from firmware
  913. * @config_page: contents of the config page
  914. * @form: GET_NEXT_HANDLE or HANDLE
  915. * @handle: device handle
  916. * Context: sleep.
  917. *
  918. * Returns 0 for success, non-zero for failure.
  919. */
  920. int
  921. mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
  922. Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
  923. u32 form, u32 handle)
  924. {
  925. Mpi2ConfigRequest_t mpi_request;
  926. int r;
  927. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  928. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  929. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  930. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  931. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
  932. mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
  933. mpi_request.Header.PageNumber = 1;
  934. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  935. r = _config_request(ioc, &mpi_request, mpi_reply,
  936. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  937. if (r)
  938. goto out;
  939. mpi_request.PageAddress = cpu_to_le32(form | handle);
  940. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  941. r = _config_request(ioc, &mpi_request, mpi_reply,
  942. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  943. sizeof(*config_page));
  944. out:
  945. return r;
  946. }
  947. /**
  948. * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
  949. * @ioc: per adapter object
  950. * @num_phys: pointer returned with the number of phys
  951. * Context: sleep.
  952. *
  953. * Returns 0 for success, non-zero for failure.
  954. */
  955. int
  956. mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
  957. {
  958. Mpi2ConfigRequest_t mpi_request;
  959. int r;
  960. u16 ioc_status;
  961. Mpi2ConfigReply_t mpi_reply;
  962. Mpi2SasIOUnitPage0_t config_page;
  963. *num_phys = 0;
  964. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  965. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  966. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  967. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  968. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
  969. mpi_request.Header.PageNumber = 0;
  970. mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
  971. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  972. r = _config_request(ioc, &mpi_request, &mpi_reply,
  973. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  974. if (r)
  975. goto out;
  976. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  977. r = _config_request(ioc, &mpi_request, &mpi_reply,
  978. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
  979. sizeof(Mpi2SasIOUnitPage0_t));
  980. if (!r) {
  981. ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
  982. MPI2_IOCSTATUS_MASK;
  983. if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
  984. *num_phys = config_page.NumPhys;
  985. }
  986. out:
  987. return r;
  988. }
  989. /**
  990. * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
  991. * @ioc: per adapter object
  992. * @mpi_reply: reply mf payload returned from firmware
  993. * @config_page: contents of the config page
  994. * @sz: size of buffer passed in config_page
  995. * Context: sleep.
  996. *
  997. * Calling function should call config_get_number_hba_phys prior to
  998. * this function, so enough memory is allocated for config_page.
  999. *
  1000. * Returns 0 for success, non-zero for failure.
  1001. */
  1002. int
  1003. mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
  1004. Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
  1005. u16 sz)
  1006. {
  1007. Mpi2ConfigRequest_t mpi_request;
  1008. int r;
  1009. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1010. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1011. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1012. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1013. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
  1014. mpi_request.Header.PageNumber = 0;
  1015. mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
  1016. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1017. r = _config_request(ioc, &mpi_request, mpi_reply,
  1018. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1019. if (r)
  1020. goto out;
  1021. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1022. r = _config_request(ioc, &mpi_request, mpi_reply,
  1023. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
  1024. out:
  1025. return r;
  1026. }
  1027. /**
  1028. * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
  1029. * @ioc: per adapter object
  1030. * @mpi_reply: reply mf payload returned from firmware
  1031. * @config_page: contents of the config page
  1032. * @sz: size of buffer passed in config_page
  1033. * Context: sleep.
  1034. *
  1035. * Calling function should call config_get_number_hba_phys prior to
  1036. * this function, so enough memory is allocated for config_page.
  1037. *
  1038. * Returns 0 for success, non-zero for failure.
  1039. */
  1040. int
  1041. mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
  1042. Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
  1043. u16 sz)
  1044. {
  1045. Mpi2ConfigRequest_t mpi_request;
  1046. int r;
  1047. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1048. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1049. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1050. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1051. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
  1052. mpi_request.Header.PageNumber = 1;
  1053. mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
  1054. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1055. r = _config_request(ioc, &mpi_request, mpi_reply,
  1056. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1057. if (r)
  1058. goto out;
  1059. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1060. r = _config_request(ioc, &mpi_request, mpi_reply,
  1061. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
  1062. out:
  1063. return r;
  1064. }
  1065. /**
  1066. * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
  1067. * @ioc: per adapter object
  1068. * @mpi_reply: reply mf payload returned from firmware
  1069. * @config_page: contents of the config page
  1070. * @sz: size of buffer passed in config_page
  1071. * Context: sleep.
  1072. *
  1073. * Calling function should call config_get_number_hba_phys prior to
  1074. * this function, so enough memory is allocated for config_page.
  1075. *
  1076. * Returns 0 for success, non-zero for failure.
  1077. */
  1078. int
  1079. mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
  1080. Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
  1081. u16 sz)
  1082. {
  1083. Mpi2ConfigRequest_t mpi_request;
  1084. int r;
  1085. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1086. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1087. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1088. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1089. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
  1090. mpi_request.Header.PageNumber = 1;
  1091. mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
  1092. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1093. r = _config_request(ioc, &mpi_request, mpi_reply,
  1094. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1095. if (r)
  1096. goto out;
  1097. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
  1098. _config_request(ioc, &mpi_request, mpi_reply,
  1099. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
  1100. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
  1101. r = _config_request(ioc, &mpi_request, mpi_reply,
  1102. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
  1103. out:
  1104. return r;
  1105. }
  1106. /**
  1107. * mpt3sas_config_get_expander_pg0 - obtain expander page 0
  1108. * @ioc: per adapter object
  1109. * @mpi_reply: reply mf payload returned from firmware
  1110. * @config_page: contents of the config page
  1111. * @form: GET_NEXT_HANDLE or HANDLE
  1112. * @handle: expander handle
  1113. * Context: sleep.
  1114. *
  1115. * Returns 0 for success, non-zero for failure.
  1116. */
  1117. int
  1118. mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
  1119. *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
  1120. {
  1121. Mpi2ConfigRequest_t mpi_request;
  1122. int r;
  1123. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1124. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1125. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1126. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1127. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
  1128. mpi_request.Header.PageNumber = 0;
  1129. mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
  1130. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1131. r = _config_request(ioc, &mpi_request, mpi_reply,
  1132. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1133. if (r)
  1134. goto out;
  1135. mpi_request.PageAddress = cpu_to_le32(form | handle);
  1136. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1137. r = _config_request(ioc, &mpi_request, mpi_reply,
  1138. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  1139. sizeof(*config_page));
  1140. out:
  1141. return r;
  1142. }
  1143. /**
  1144. * mpt3sas_config_get_expander_pg1 - obtain expander page 1
  1145. * @ioc: per adapter object
  1146. * @mpi_reply: reply mf payload returned from firmware
  1147. * @config_page: contents of the config page
  1148. * @phy_number: phy number
  1149. * @handle: expander handle
  1150. * Context: sleep.
  1151. *
  1152. * Returns 0 for success, non-zero for failure.
  1153. */
  1154. int
  1155. mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
  1156. *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
  1157. u16 handle)
  1158. {
  1159. Mpi2ConfigRequest_t mpi_request;
  1160. int r;
  1161. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1162. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1163. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1164. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1165. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
  1166. mpi_request.Header.PageNumber = 1;
  1167. mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
  1168. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1169. r = _config_request(ioc, &mpi_request, mpi_reply,
  1170. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1171. if (r)
  1172. goto out;
  1173. mpi_request.PageAddress =
  1174. cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
  1175. (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
  1176. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1177. r = _config_request(ioc, &mpi_request, mpi_reply,
  1178. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  1179. sizeof(*config_page));
  1180. out:
  1181. return r;
  1182. }
  1183. /**
  1184. * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
  1185. * @ioc: per adapter object
  1186. * @mpi_reply: reply mf payload returned from firmware
  1187. * @config_page: contents of the config page
  1188. * @form: GET_NEXT_HANDLE or HANDLE
  1189. * @handle: expander handle
  1190. * Context: sleep.
  1191. *
  1192. * Returns 0 for success, non-zero for failure.
  1193. */
  1194. int
  1195. mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
  1196. *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
  1197. {
  1198. Mpi2ConfigRequest_t mpi_request;
  1199. int r;
  1200. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1201. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1202. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1203. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1204. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
  1205. mpi_request.Header.PageNumber = 0;
  1206. mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
  1207. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1208. r = _config_request(ioc, &mpi_request, mpi_reply,
  1209. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1210. if (r)
  1211. goto out;
  1212. mpi_request.PageAddress = cpu_to_le32(form | handle);
  1213. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1214. r = _config_request(ioc, &mpi_request, mpi_reply,
  1215. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  1216. sizeof(*config_page));
  1217. out:
  1218. return r;
  1219. }
  1220. /**
  1221. * mpt3sas_config_get_phy_pg0 - obtain phy page 0
  1222. * @ioc: per adapter object
  1223. * @mpi_reply: reply mf payload returned from firmware
  1224. * @config_page: contents of the config page
  1225. * @phy_number: phy number
  1226. * Context: sleep.
  1227. *
  1228. * Returns 0 for success, non-zero for failure.
  1229. */
  1230. int
  1231. mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
  1232. *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
  1233. {
  1234. Mpi2ConfigRequest_t mpi_request;
  1235. int r;
  1236. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1237. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1238. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1239. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1240. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
  1241. mpi_request.Header.PageNumber = 0;
  1242. mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
  1243. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1244. r = _config_request(ioc, &mpi_request, mpi_reply,
  1245. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1246. if (r)
  1247. goto out;
  1248. mpi_request.PageAddress =
  1249. cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
  1250. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1251. r = _config_request(ioc, &mpi_request, mpi_reply,
  1252. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  1253. sizeof(*config_page));
  1254. out:
  1255. return r;
  1256. }
  1257. /**
  1258. * mpt3sas_config_get_phy_pg1 - obtain phy page 1
  1259. * @ioc: per adapter object
  1260. * @mpi_reply: reply mf payload returned from firmware
  1261. * @config_page: contents of the config page
  1262. * @phy_number: phy number
  1263. * Context: sleep.
  1264. *
  1265. * Returns 0 for success, non-zero for failure.
  1266. */
  1267. int
  1268. mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
  1269. *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
  1270. {
  1271. Mpi2ConfigRequest_t mpi_request;
  1272. int r;
  1273. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1274. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1275. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1276. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1277. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
  1278. mpi_request.Header.PageNumber = 1;
  1279. mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
  1280. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1281. r = _config_request(ioc, &mpi_request, mpi_reply,
  1282. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1283. if (r)
  1284. goto out;
  1285. mpi_request.PageAddress =
  1286. cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
  1287. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1288. r = _config_request(ioc, &mpi_request, mpi_reply,
  1289. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  1290. sizeof(*config_page));
  1291. out:
  1292. return r;
  1293. }
  1294. /**
  1295. * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
  1296. * @ioc: per adapter object
  1297. * @mpi_reply: reply mf payload returned from firmware
  1298. * @config_page: contents of the config page
  1299. * @form: GET_NEXT_HANDLE or HANDLE
  1300. * @handle: volume handle
  1301. * Context: sleep.
  1302. *
  1303. * Returns 0 for success, non-zero for failure.
  1304. */
  1305. int
  1306. mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
  1307. Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
  1308. u32 handle)
  1309. {
  1310. Mpi2ConfigRequest_t mpi_request;
  1311. int r;
  1312. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1313. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1314. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1315. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
  1316. mpi_request.Header.PageNumber = 1;
  1317. mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
  1318. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1319. r = _config_request(ioc, &mpi_request, mpi_reply,
  1320. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1321. if (r)
  1322. goto out;
  1323. mpi_request.PageAddress = cpu_to_le32(form | handle);
  1324. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1325. r = _config_request(ioc, &mpi_request, mpi_reply,
  1326. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  1327. sizeof(*config_page));
  1328. out:
  1329. return r;
  1330. }
  1331. /**
  1332. * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
  1333. * @ioc: per adapter object
  1334. * @handle: volume handle
  1335. * @num_pds: returns pds count
  1336. * Context: sleep.
  1337. *
  1338. * Returns 0 for success, non-zero for failure.
  1339. */
  1340. int
  1341. mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
  1342. u8 *num_pds)
  1343. {
  1344. Mpi2ConfigRequest_t mpi_request;
  1345. Mpi2RaidVolPage0_t config_page;
  1346. Mpi2ConfigReply_t mpi_reply;
  1347. int r;
  1348. u16 ioc_status;
  1349. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1350. *num_pds = 0;
  1351. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1352. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1353. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
  1354. mpi_request.Header.PageNumber = 0;
  1355. mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
  1356. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1357. r = _config_request(ioc, &mpi_request, &mpi_reply,
  1358. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1359. if (r)
  1360. goto out;
  1361. mpi_request.PageAddress =
  1362. cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
  1363. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1364. r = _config_request(ioc, &mpi_request, &mpi_reply,
  1365. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
  1366. sizeof(Mpi2RaidVolPage0_t));
  1367. if (!r) {
  1368. ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
  1369. MPI2_IOCSTATUS_MASK;
  1370. if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
  1371. *num_pds = config_page.NumPhysDisks;
  1372. }
  1373. out:
  1374. return r;
  1375. }
  1376. /**
  1377. * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
  1378. * @ioc: per adapter object
  1379. * @mpi_reply: reply mf payload returned from firmware
  1380. * @config_page: contents of the config page
  1381. * @form: GET_NEXT_HANDLE or HANDLE
  1382. * @handle: volume handle
  1383. * @sz: size of buffer passed in config_page
  1384. * Context: sleep.
  1385. *
  1386. * Returns 0 for success, non-zero for failure.
  1387. */
  1388. int
  1389. mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
  1390. Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
  1391. u32 handle, u16 sz)
  1392. {
  1393. Mpi2ConfigRequest_t mpi_request;
  1394. int r;
  1395. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1396. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1397. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1398. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
  1399. mpi_request.Header.PageNumber = 0;
  1400. mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
  1401. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1402. r = _config_request(ioc, &mpi_request, mpi_reply,
  1403. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1404. if (r)
  1405. goto out;
  1406. mpi_request.PageAddress = cpu_to_le32(form | handle);
  1407. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1408. r = _config_request(ioc, &mpi_request, mpi_reply,
  1409. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
  1410. out:
  1411. return r;
  1412. }
  1413. /**
  1414. * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
  1415. * @ioc: per adapter object
  1416. * @mpi_reply: reply mf payload returned from firmware
  1417. * @config_page: contents of the config page
  1418. * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
  1419. * @form_specific: specific to the form
  1420. * Context: sleep.
  1421. *
  1422. * Returns 0 for success, non-zero for failure.
  1423. */
  1424. int
  1425. mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
  1426. *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
  1427. u32 form_specific)
  1428. {
  1429. Mpi2ConfigRequest_t mpi_request;
  1430. int r;
  1431. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1432. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1433. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1434. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
  1435. mpi_request.Header.PageNumber = 0;
  1436. mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
  1437. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1438. r = _config_request(ioc, &mpi_request, mpi_reply,
  1439. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1440. if (r)
  1441. goto out;
  1442. mpi_request.PageAddress = cpu_to_le32(form | form_specific);
  1443. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1444. r = _config_request(ioc, &mpi_request, mpi_reply,
  1445. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  1446. sizeof(*config_page));
  1447. out:
  1448. return r;
  1449. }
  1450. /**
  1451. * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
  1452. * raid components
  1453. * @ioc: per adapter object
  1454. * @pd_handle: phys disk handle
  1455. * @volume_handle: volume handle
  1456. * Context: sleep.
  1457. *
  1458. * Returns 0 for success, non-zero for failure.
  1459. */
  1460. int
  1461. mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
  1462. u16 *volume_handle)
  1463. {
  1464. Mpi2RaidConfigurationPage0_t *config_page = NULL;
  1465. Mpi2ConfigRequest_t mpi_request;
  1466. Mpi2ConfigReply_t mpi_reply;
  1467. int r, i, config_page_sz;
  1468. u16 ioc_status;
  1469. int config_num;
  1470. u16 element_type;
  1471. u16 phys_disk_dev_handle;
  1472. *volume_handle = 0;
  1473. memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
  1474. mpi_request.Function = MPI2_FUNCTION_CONFIG;
  1475. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  1476. mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  1477. mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
  1478. mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
  1479. mpi_request.Header.PageNumber = 0;
  1480. ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
  1481. r = _config_request(ioc, &mpi_request, &mpi_reply,
  1482. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
  1483. if (r)
  1484. goto out;
  1485. mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  1486. config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
  1487. config_page = kmalloc(config_page_sz, GFP_KERNEL);
  1488. if (!config_page) {
  1489. r = -1;
  1490. goto out;
  1491. }
  1492. config_num = 0xff;
  1493. while (1) {
  1494. mpi_request.PageAddress = cpu_to_le32(config_num +
  1495. MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
  1496. r = _config_request(ioc, &mpi_request, &mpi_reply,
  1497. MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
  1498. config_page_sz);
  1499. if (r)
  1500. goto out;
  1501. r = -1;
  1502. ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
  1503. MPI2_IOCSTATUS_MASK;
  1504. if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
  1505. goto out;
  1506. for (i = 0; i < config_page->NumElements; i++) {
  1507. element_type = le16_to_cpu(config_page->
  1508. ConfigElement[i].ElementFlags) &
  1509. MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
  1510. if (element_type ==
  1511. MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
  1512. element_type ==
  1513. MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
  1514. phys_disk_dev_handle =
  1515. le16_to_cpu(config_page->ConfigElement[i].
  1516. PhysDiskDevHandle);
  1517. if (phys_disk_dev_handle == pd_handle) {
  1518. *volume_handle =
  1519. le16_to_cpu(config_page->
  1520. ConfigElement[i].VolDevHandle);
  1521. r = 0;
  1522. goto out;
  1523. }
  1524. } else if (element_type ==
  1525. MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
  1526. *volume_handle = 0;
  1527. r = 0;
  1528. goto out;
  1529. }
  1530. }
  1531. config_num = config_page->ConfigNum;
  1532. }
  1533. out:
  1534. kfree(config_page);
  1535. return r;
  1536. }
  1537. /**
  1538. * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
  1539. * @ioc: per adapter object
  1540. * @volume_handle: volume handle
  1541. * @wwid: volume wwid
  1542. * Context: sleep.
  1543. *
  1544. * Returns 0 for success, non-zero for failure.
  1545. */
  1546. int
  1547. mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
  1548. u64 *wwid)
  1549. {
  1550. Mpi2ConfigReply_t mpi_reply;
  1551. Mpi2RaidVolPage1_t raid_vol_pg1;
  1552. *wwid = 0;
  1553. if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
  1554. &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
  1555. volume_handle))) {
  1556. *wwid = le64_to_cpu(raid_vol_pg1.WWID);
  1557. return 0;
  1558. } else
  1559. return -1;
  1560. }