mpt3sas_config.c 54 KB

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