lpfc_mbox.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904
  1. /*******************************************************************
  2. * This file is part of the Emulex Linux Device Driver for *
  3. * Fibre Channel Host Bus Adapters. *
  4. * Copyright (C) 2004-2007 Emulex. All rights reserved. *
  5. * EMULEX and SLI are trademarks of Emulex. *
  6. * www.emulex.com *
  7. * Portions Copyright (C) 2004-2005 Christoph Hellwig *
  8. * *
  9. * This program is free software; you can redistribute it and/or *
  10. * modify it under the terms of version 2 of the GNU General *
  11. * Public License as published by the Free Software Foundation. *
  12. * This program is distributed in the hope that it will be useful. *
  13. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
  14. * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
  15. * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
  16. * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
  17. * TO BE LEGALLY INVALID. See the GNU General Public License for *
  18. * more details, a copy of which can be found in the file COPYING *
  19. * included with this package. *
  20. *******************************************************************/
  21. #include <linux/blkdev.h>
  22. #include <linux/pci.h>
  23. #include <linux/interrupt.h>
  24. #include <scsi/scsi_device.h>
  25. #include <scsi/scsi_transport_fc.h>
  26. #include <scsi/scsi.h>
  27. #include "lpfc_hw.h"
  28. #include "lpfc_sli.h"
  29. #include "lpfc_disc.h"
  30. #include "lpfc_scsi.h"
  31. #include "lpfc.h"
  32. #include "lpfc_logmsg.h"
  33. #include "lpfc_crtn.h"
  34. #include "lpfc_compat.h"
  35. /**********************************************/
  36. /* mailbox command */
  37. /**********************************************/
  38. void
  39. lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset)
  40. {
  41. MAILBOX_t *mb;
  42. void *ctx;
  43. mb = &pmb->mb;
  44. ctx = pmb->context2;
  45. /* Setup to dump VPD region */
  46. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  47. mb->mbxCommand = MBX_DUMP_MEMORY;
  48. mb->un.varDmp.cv = 1;
  49. mb->un.varDmp.type = DMP_NV_PARAMS;
  50. mb->un.varDmp.entry_index = offset;
  51. mb->un.varDmp.region_id = DMP_REGION_VPD;
  52. mb->un.varDmp.word_cnt = (DMP_RSP_SIZE / sizeof (uint32_t));
  53. mb->un.varDmp.co = 0;
  54. mb->un.varDmp.resp_offset = 0;
  55. pmb->context2 = ctx;
  56. mb->mbxOwner = OWN_HOST;
  57. return;
  58. }
  59. /**********************************************/
  60. /* lpfc_read_nv Issue a READ NVPARAM */
  61. /* mailbox command */
  62. /**********************************************/
  63. void
  64. lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
  65. {
  66. MAILBOX_t *mb;
  67. mb = &pmb->mb;
  68. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  69. mb->mbxCommand = MBX_READ_NV;
  70. mb->mbxOwner = OWN_HOST;
  71. return;
  72. }
  73. /**********************************************/
  74. /* lpfc_config_async Issue a */
  75. /* MBX_ASYNC_EVT_ENABLE mailbox command */
  76. /**********************************************/
  77. void
  78. lpfc_config_async(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb,
  79. uint32_t ring)
  80. {
  81. MAILBOX_t *mb;
  82. mb = &pmb->mb;
  83. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  84. mb->mbxCommand = MBX_ASYNCEVT_ENABLE;
  85. mb->un.varCfgAsyncEvent.ring = ring;
  86. mb->mbxOwner = OWN_HOST;
  87. return;
  88. }
  89. /**********************************************/
  90. /* lpfc_heart_beat Issue a HEART_BEAT */
  91. /* mailbox command */
  92. /**********************************************/
  93. void
  94. lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
  95. {
  96. MAILBOX_t *mb;
  97. mb = &pmb->mb;
  98. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  99. mb->mbxCommand = MBX_HEARTBEAT;
  100. mb->mbxOwner = OWN_HOST;
  101. return;
  102. }
  103. /**********************************************/
  104. /* lpfc_read_la Issue a READ LA */
  105. /* mailbox command */
  106. /**********************************************/
  107. int
  108. lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp)
  109. {
  110. MAILBOX_t *mb;
  111. struct lpfc_sli *psli;
  112. psli = &phba->sli;
  113. mb = &pmb->mb;
  114. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  115. INIT_LIST_HEAD(&mp->list);
  116. mb->mbxCommand = MBX_READ_LA64;
  117. mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128;
  118. mb->un.varReadLA.un.lilpBde64.addrHigh = putPaddrHigh(mp->phys);
  119. mb->un.varReadLA.un.lilpBde64.addrLow = putPaddrLow(mp->phys);
  120. /* Save address for later completion and set the owner to host so that
  121. * the FW knows this mailbox is available for processing.
  122. */
  123. pmb->context1 = (uint8_t *) mp;
  124. mb->mbxOwner = OWN_HOST;
  125. return (0);
  126. }
  127. /**********************************************/
  128. /* lpfc_clear_la Issue a CLEAR LA */
  129. /* mailbox command */
  130. /**********************************************/
  131. void
  132. lpfc_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
  133. {
  134. MAILBOX_t *mb;
  135. mb = &pmb->mb;
  136. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  137. mb->un.varClearLA.eventTag = phba->fc_eventTag;
  138. mb->mbxCommand = MBX_CLEAR_LA;
  139. mb->mbxOwner = OWN_HOST;
  140. return;
  141. }
  142. /**************************************************/
  143. /* lpfc_config_link Issue a CONFIG LINK */
  144. /* mailbox command */
  145. /**************************************************/
  146. void
  147. lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
  148. {
  149. struct lpfc_vport *vport = phba->pport;
  150. MAILBOX_t *mb = &pmb->mb;
  151. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  152. /* NEW_FEATURE
  153. * SLI-2, Coalescing Response Feature.
  154. */
  155. if (phba->cfg_cr_delay) {
  156. mb->un.varCfgLnk.cr = 1;
  157. mb->un.varCfgLnk.ci = 1;
  158. mb->un.varCfgLnk.cr_delay = phba->cfg_cr_delay;
  159. mb->un.varCfgLnk.cr_count = phba->cfg_cr_count;
  160. }
  161. mb->un.varCfgLnk.myId = vport->fc_myDID;
  162. mb->un.varCfgLnk.edtov = phba->fc_edtov;
  163. mb->un.varCfgLnk.arbtov = phba->fc_arbtov;
  164. mb->un.varCfgLnk.ratov = phba->fc_ratov;
  165. mb->un.varCfgLnk.rttov = phba->fc_rttov;
  166. mb->un.varCfgLnk.altov = phba->fc_altov;
  167. mb->un.varCfgLnk.crtov = phba->fc_crtov;
  168. mb->un.varCfgLnk.citov = phba->fc_citov;
  169. if (phba->cfg_ack0)
  170. mb->un.varCfgLnk.ack0_enable = 1;
  171. mb->mbxCommand = MBX_CONFIG_LINK;
  172. mb->mbxOwner = OWN_HOST;
  173. return;
  174. }
  175. /**********************************************/
  176. /* lpfc_init_link Issue an INIT LINK */
  177. /* mailbox command */
  178. /**********************************************/
  179. void
  180. lpfc_init_link(struct lpfc_hba * phba,
  181. LPFC_MBOXQ_t * pmb, uint32_t topology, uint32_t linkspeed)
  182. {
  183. lpfc_vpd_t *vpd;
  184. struct lpfc_sli *psli;
  185. MAILBOX_t *mb;
  186. mb = &pmb->mb;
  187. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  188. psli = &phba->sli;
  189. switch (topology) {
  190. case FLAGS_TOPOLOGY_MODE_LOOP_PT:
  191. mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
  192. mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
  193. break;
  194. case FLAGS_TOPOLOGY_MODE_PT_PT:
  195. mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
  196. break;
  197. case FLAGS_TOPOLOGY_MODE_LOOP:
  198. mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
  199. break;
  200. case FLAGS_TOPOLOGY_MODE_PT_LOOP:
  201. mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
  202. mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
  203. break;
  204. case FLAGS_LOCAL_LB:
  205. mb->un.varInitLnk.link_flags = FLAGS_LOCAL_LB;
  206. break;
  207. }
  208. /* Enable asynchronous ABTS responses from firmware */
  209. mb->un.varInitLnk.link_flags |= FLAGS_IMED_ABORT;
  210. /* NEW_FEATURE
  211. * Setting up the link speed
  212. */
  213. vpd = &phba->vpd;
  214. if (vpd->rev.feaLevelHigh >= 0x02){
  215. switch(linkspeed){
  216. case LINK_SPEED_1G:
  217. case LINK_SPEED_2G:
  218. case LINK_SPEED_4G:
  219. case LINK_SPEED_8G:
  220. mb->un.varInitLnk.link_flags |=
  221. FLAGS_LINK_SPEED;
  222. mb->un.varInitLnk.link_speed = linkspeed;
  223. break;
  224. case LINK_SPEED_AUTO:
  225. default:
  226. mb->un.varInitLnk.link_speed =
  227. LINK_SPEED_AUTO;
  228. break;
  229. }
  230. }
  231. else
  232. mb->un.varInitLnk.link_speed = LINK_SPEED_AUTO;
  233. mb->mbxCommand = (volatile uint8_t)MBX_INIT_LINK;
  234. mb->mbxOwner = OWN_HOST;
  235. mb->un.varInitLnk.fabric_AL_PA = phba->fc_pref_ALPA;
  236. return;
  237. }
  238. /**********************************************/
  239. /* lpfc_read_sparam Issue a READ SPARAM */
  240. /* mailbox command */
  241. /**********************************************/
  242. int
  243. lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi)
  244. {
  245. struct lpfc_dmabuf *mp;
  246. MAILBOX_t *mb;
  247. struct lpfc_sli *psli;
  248. psli = &phba->sli;
  249. mb = &pmb->mb;
  250. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  251. mb->mbxOwner = OWN_HOST;
  252. /* Get a buffer to hold the HBAs Service Parameters */
  253. mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
  254. if (mp)
  255. mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
  256. if (!mp || !mp->virt) {
  257. kfree(mp);
  258. mb->mbxCommand = MBX_READ_SPARM64;
  259. /* READ_SPARAM: no buffers */
  260. lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
  261. "0301 READ_SPARAM: no buffers\n");
  262. return (1);
  263. }
  264. INIT_LIST_HEAD(&mp->list);
  265. mb->mbxCommand = MBX_READ_SPARM64;
  266. mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm);
  267. mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys);
  268. mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys);
  269. mb->un.varRdSparm.vpi = vpi;
  270. /* save address for completion */
  271. pmb->context1 = mp;
  272. return (0);
  273. }
  274. /********************************************/
  275. /* lpfc_unreg_did Issue a UNREG_DID */
  276. /* mailbox command */
  277. /********************************************/
  278. void
  279. lpfc_unreg_did(struct lpfc_hba * phba, uint16_t vpi, uint32_t did,
  280. LPFC_MBOXQ_t * pmb)
  281. {
  282. MAILBOX_t *mb;
  283. mb = &pmb->mb;
  284. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  285. mb->un.varUnregDID.did = did;
  286. mb->un.varUnregDID.vpi = vpi;
  287. mb->mbxCommand = MBX_UNREG_D_ID;
  288. mb->mbxOwner = OWN_HOST;
  289. return;
  290. }
  291. /**********************************************/
  292. /* lpfc_read_nv Issue a READ CONFIG */
  293. /* mailbox command */
  294. /**********************************************/
  295. void
  296. lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
  297. {
  298. MAILBOX_t *mb;
  299. mb = &pmb->mb;
  300. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  301. mb->mbxCommand = MBX_READ_CONFIG;
  302. mb->mbxOwner = OWN_HOST;
  303. return;
  304. }
  305. /*************************************************/
  306. /* lpfc_read_lnk_stat Issue a READ LINK STATUS */
  307. /* mailbox command */
  308. /*************************************************/
  309. void
  310. lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
  311. {
  312. MAILBOX_t *mb;
  313. mb = &pmb->mb;
  314. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  315. mb->mbxCommand = MBX_READ_LNK_STAT;
  316. mb->mbxOwner = OWN_HOST;
  317. return;
  318. }
  319. /********************************************/
  320. /* lpfc_reg_login Issue a REG_LOGIN */
  321. /* mailbox command */
  322. /********************************************/
  323. int
  324. lpfc_reg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
  325. uint8_t *param, LPFC_MBOXQ_t *pmb, uint32_t flag)
  326. {
  327. MAILBOX_t *mb = &pmb->mb;
  328. uint8_t *sparam;
  329. struct lpfc_dmabuf *mp;
  330. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  331. mb->un.varRegLogin.rpi = 0;
  332. mb->un.varRegLogin.vpi = vpi;
  333. mb->un.varRegLogin.did = did;
  334. mb->un.varWords[30] = flag; /* Set flag to issue action on cmpl */
  335. mb->mbxOwner = OWN_HOST;
  336. /* Get a buffer to hold NPorts Service Parameters */
  337. mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
  338. if (mp)
  339. mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
  340. if (!mp || !mp->virt) {
  341. kfree(mp);
  342. mb->mbxCommand = MBX_REG_LOGIN64;
  343. /* REG_LOGIN: no buffers */
  344. lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
  345. "0302 REG_LOGIN: no buffers, VPI:%d DID:x%x, "
  346. "flag x%x\n", vpi, did, flag);
  347. return (1);
  348. }
  349. INIT_LIST_HEAD(&mp->list);
  350. sparam = mp->virt;
  351. /* Copy param's into a new buffer */
  352. memcpy(sparam, param, sizeof (struct serv_parm));
  353. /* save address for completion */
  354. pmb->context1 = (uint8_t *) mp;
  355. mb->mbxCommand = MBX_REG_LOGIN64;
  356. mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm);
  357. mb->un.varRegLogin.un.sp64.addrHigh = putPaddrHigh(mp->phys);
  358. mb->un.varRegLogin.un.sp64.addrLow = putPaddrLow(mp->phys);
  359. return (0);
  360. }
  361. /**********************************************/
  362. /* lpfc_unreg_login Issue a UNREG_LOGIN */
  363. /* mailbox command */
  364. /**********************************************/
  365. void
  366. lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi,
  367. LPFC_MBOXQ_t * pmb)
  368. {
  369. MAILBOX_t *mb;
  370. mb = &pmb->mb;
  371. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  372. mb->un.varUnregLogin.rpi = (uint16_t) rpi;
  373. mb->un.varUnregLogin.rsvd1 = 0;
  374. mb->un.varUnregLogin.vpi = vpi;
  375. mb->mbxCommand = MBX_UNREG_LOGIN;
  376. mb->mbxOwner = OWN_HOST;
  377. return;
  378. }
  379. /**************************************************/
  380. /* lpfc_reg_vpi Issue a REG_VPI */
  381. /* mailbox command */
  382. /**************************************************/
  383. void
  384. lpfc_reg_vpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t sid,
  385. LPFC_MBOXQ_t *pmb)
  386. {
  387. MAILBOX_t *mb = &pmb->mb;
  388. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  389. mb->un.varRegVpi.vpi = vpi;
  390. mb->un.varRegVpi.sid = sid;
  391. mb->mbxCommand = MBX_REG_VPI;
  392. mb->mbxOwner = OWN_HOST;
  393. return;
  394. }
  395. /**************************************************/
  396. /* lpfc_unreg_vpi Issue a UNREG_VNPI */
  397. /* mailbox command */
  398. /**************************************************/
  399. void
  400. lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb)
  401. {
  402. MAILBOX_t *mb = &pmb->mb;
  403. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  404. mb->un.varUnregVpi.vpi = vpi;
  405. mb->mbxCommand = MBX_UNREG_VPI;
  406. mb->mbxOwner = OWN_HOST;
  407. return;
  408. }
  409. static void
  410. lpfc_config_pcb_setup(struct lpfc_hba * phba)
  411. {
  412. struct lpfc_sli *psli = &phba->sli;
  413. struct lpfc_sli_ring *pring;
  414. PCB_t *pcbp = &phba->slim2p->pcb;
  415. dma_addr_t pdma_addr;
  416. uint32_t offset;
  417. uint32_t iocbCnt = 0;
  418. int i;
  419. pcbp->maxRing = (psli->num_rings - 1);
  420. for (i = 0; i < psli->num_rings; i++) {
  421. pring = &psli->ring[i];
  422. pring->sizeCiocb = phba->sli_rev == 3 ? SLI3_IOCB_CMD_SIZE:
  423. SLI2_IOCB_CMD_SIZE;
  424. pring->sizeRiocb = phba->sli_rev == 3 ? SLI3_IOCB_RSP_SIZE:
  425. SLI2_IOCB_RSP_SIZE;
  426. /* A ring MUST have both cmd and rsp entries defined to be
  427. valid */
  428. if ((pring->numCiocb == 0) || (pring->numRiocb == 0)) {
  429. pcbp->rdsc[i].cmdEntries = 0;
  430. pcbp->rdsc[i].rspEntries = 0;
  431. pcbp->rdsc[i].cmdAddrHigh = 0;
  432. pcbp->rdsc[i].rspAddrHigh = 0;
  433. pcbp->rdsc[i].cmdAddrLow = 0;
  434. pcbp->rdsc[i].rspAddrLow = 0;
  435. pring->cmdringaddr = NULL;
  436. pring->rspringaddr = NULL;
  437. continue;
  438. }
  439. /* Command ring setup for ring */
  440. pring->cmdringaddr = (void *) &phba->slim2p->IOCBs[iocbCnt];
  441. pcbp->rdsc[i].cmdEntries = pring->numCiocb;
  442. offset = (uint8_t *) &phba->slim2p->IOCBs[iocbCnt] -
  443. (uint8_t *) phba->slim2p;
  444. pdma_addr = phba->slim2p_mapping + offset;
  445. pcbp->rdsc[i].cmdAddrHigh = putPaddrHigh(pdma_addr);
  446. pcbp->rdsc[i].cmdAddrLow = putPaddrLow(pdma_addr);
  447. iocbCnt += pring->numCiocb;
  448. /* Response ring setup for ring */
  449. pring->rspringaddr = (void *) &phba->slim2p->IOCBs[iocbCnt];
  450. pcbp->rdsc[i].rspEntries = pring->numRiocb;
  451. offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
  452. (uint8_t *)phba->slim2p;
  453. pdma_addr = phba->slim2p_mapping + offset;
  454. pcbp->rdsc[i].rspAddrHigh = putPaddrHigh(pdma_addr);
  455. pcbp->rdsc[i].rspAddrLow = putPaddrLow(pdma_addr);
  456. iocbCnt += pring->numRiocb;
  457. }
  458. }
  459. void
  460. lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
  461. {
  462. MAILBOX_t *mb = &pmb->mb;
  463. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  464. mb->un.varRdRev.cv = 1;
  465. mb->un.varRdRev.v3req = 1; /* Request SLI3 info */
  466. mb->mbxCommand = MBX_READ_REV;
  467. mb->mbxOwner = OWN_HOST;
  468. return;
  469. }
  470. static void
  471. lpfc_build_hbq_profile2(struct config_hbq_var *hbqmb,
  472. struct lpfc_hbq_init *hbq_desc)
  473. {
  474. hbqmb->profiles.profile2.seqlenbcnt = hbq_desc->seqlenbcnt;
  475. hbqmb->profiles.profile2.maxlen = hbq_desc->maxlen;
  476. hbqmb->profiles.profile2.seqlenoff = hbq_desc->seqlenoff;
  477. }
  478. static void
  479. lpfc_build_hbq_profile3(struct config_hbq_var *hbqmb,
  480. struct lpfc_hbq_init *hbq_desc)
  481. {
  482. hbqmb->profiles.profile3.seqlenbcnt = hbq_desc->seqlenbcnt;
  483. hbqmb->profiles.profile3.maxlen = hbq_desc->maxlen;
  484. hbqmb->profiles.profile3.cmdcodeoff = hbq_desc->cmdcodeoff;
  485. hbqmb->profiles.profile3.seqlenoff = hbq_desc->seqlenoff;
  486. memcpy(&hbqmb->profiles.profile3.cmdmatch, hbq_desc->cmdmatch,
  487. sizeof(hbqmb->profiles.profile3.cmdmatch));
  488. }
  489. static void
  490. lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb,
  491. struct lpfc_hbq_init *hbq_desc)
  492. {
  493. hbqmb->profiles.profile5.seqlenbcnt = hbq_desc->seqlenbcnt;
  494. hbqmb->profiles.profile5.maxlen = hbq_desc->maxlen;
  495. hbqmb->profiles.profile5.cmdcodeoff = hbq_desc->cmdcodeoff;
  496. hbqmb->profiles.profile5.seqlenoff = hbq_desc->seqlenoff;
  497. memcpy(&hbqmb->profiles.profile5.cmdmatch, hbq_desc->cmdmatch,
  498. sizeof(hbqmb->profiles.profile5.cmdmatch));
  499. }
  500. void
  501. lpfc_config_hbq(struct lpfc_hba *phba, uint32_t id,
  502. struct lpfc_hbq_init *hbq_desc,
  503. uint32_t hbq_entry_index, LPFC_MBOXQ_t *pmb)
  504. {
  505. int i;
  506. MAILBOX_t *mb = &pmb->mb;
  507. struct config_hbq_var *hbqmb = &mb->un.varCfgHbq;
  508. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  509. hbqmb->hbqId = id;
  510. hbqmb->entry_count = hbq_desc->entry_count; /* # entries in HBQ */
  511. hbqmb->recvNotify = hbq_desc->rn; /* Receive
  512. * Notification */
  513. hbqmb->numMask = hbq_desc->mask_count; /* # R_CTL/TYPE masks
  514. * # in words 0-19 */
  515. hbqmb->profile = hbq_desc->profile; /* Selection profile:
  516. * 0 = all,
  517. * 7 = logentry */
  518. hbqmb->ringMask = hbq_desc->ring_mask; /* Binds HBQ to a ring
  519. * e.g. Ring0=b0001,
  520. * ring2=b0100 */
  521. hbqmb->headerLen = hbq_desc->headerLen; /* 0 if not profile 4
  522. * or 5 */
  523. hbqmb->logEntry = hbq_desc->logEntry; /* Set to 1 if this
  524. * HBQ will be used
  525. * for LogEntry
  526. * buffers */
  527. hbqmb->hbqaddrLow = putPaddrLow(phba->hbqslimp.phys) +
  528. hbq_entry_index * sizeof(struct lpfc_hbq_entry);
  529. hbqmb->hbqaddrHigh = putPaddrHigh(phba->hbqslimp.phys);
  530. mb->mbxCommand = MBX_CONFIG_HBQ;
  531. mb->mbxOwner = OWN_HOST;
  532. /* Copy info for profiles 2,3,5. Other
  533. * profiles this area is reserved
  534. */
  535. if (hbq_desc->profile == 2)
  536. lpfc_build_hbq_profile2(hbqmb, hbq_desc);
  537. else if (hbq_desc->profile == 3)
  538. lpfc_build_hbq_profile3(hbqmb, hbq_desc);
  539. else if (hbq_desc->profile == 5)
  540. lpfc_build_hbq_profile5(hbqmb, hbq_desc);
  541. /* Return if no rctl / type masks for this HBQ */
  542. if (!hbq_desc->mask_count)
  543. return;
  544. /* Otherwise we setup specific rctl / type masks for this HBQ */
  545. for (i = 0; i < hbq_desc->mask_count; i++) {
  546. hbqmb->hbqMasks[i].tmatch = hbq_desc->hbqMasks[i].tmatch;
  547. hbqmb->hbqMasks[i].tmask = hbq_desc->hbqMasks[i].tmask;
  548. hbqmb->hbqMasks[i].rctlmatch = hbq_desc->hbqMasks[i].rctlmatch;
  549. hbqmb->hbqMasks[i].rctlmask = hbq_desc->hbqMasks[i].rctlmask;
  550. }
  551. return;
  552. }
  553. void
  554. lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb)
  555. {
  556. int i;
  557. MAILBOX_t *mb = &pmb->mb;
  558. struct lpfc_sli *psli;
  559. struct lpfc_sli_ring *pring;
  560. memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
  561. mb->un.varCfgRing.ring = ring;
  562. mb->un.varCfgRing.maxOrigXchg = 0;
  563. mb->un.varCfgRing.maxRespXchg = 0;
  564. mb->un.varCfgRing.recvNotify = 1;
  565. psli = &phba->sli;
  566. pring = &psli->ring[ring];
  567. mb->un.varCfgRing.numMask = pring->num_mask;
  568. mb->mbxCommand = MBX_CONFIG_RING;
  569. mb->mbxOwner = OWN_HOST;
  570. /* Is this ring configured for a specific profile */
  571. if (pring->prt[0].profile) {
  572. mb->un.varCfgRing.profile = pring->prt[0].profile;
  573. return;
  574. }
  575. /* Otherwise we setup specific rctl / type masks for this ring */
  576. for (i = 0; i < pring->num_mask; i++) {
  577. mb->un.varCfgRing.rrRegs[i].rval = pring->prt[i].rctl;
  578. if (mb->un.varCfgRing.rrRegs[i].rval != FC_ELS_REQ)
  579. mb->un.varCfgRing.rrRegs[i].rmask = 0xff;
  580. else
  581. mb->un.varCfgRing.rrRegs[i].rmask = 0xfe;
  582. mb->un.varCfgRing.rrRegs[i].tval = pring->prt[i].type;
  583. mb->un.varCfgRing.rrRegs[i].tmask = 0xff;
  584. }
  585. return;
  586. }
  587. void
  588. lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
  589. {
  590. MAILBOX_t __iomem *mb_slim = (MAILBOX_t __iomem *) phba->MBslimaddr;
  591. MAILBOX_t *mb = &pmb->mb;
  592. dma_addr_t pdma_addr;
  593. uint32_t bar_low, bar_high;
  594. size_t offset;
  595. struct lpfc_hgp hgp;
  596. int i;
  597. uint32_t pgp_offset;
  598. memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
  599. mb->mbxCommand = MBX_CONFIG_PORT;
  600. mb->mbxOwner = OWN_HOST;
  601. mb->un.varCfgPort.pcbLen = sizeof(PCB_t);
  602. offset = (uint8_t *)&phba->slim2p->pcb - (uint8_t *)phba->slim2p;
  603. pdma_addr = phba->slim2p_mapping + offset;
  604. mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr);
  605. mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr);
  606. /* If HBA supports SLI=3 ask for it */
  607. if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) {
  608. mb->un.varCfgPort.cerbm = 1; /* Request HBQs */
  609. mb->un.varCfgPort.max_hbq = lpfc_sli_hbq_count();
  610. if (phba->max_vpi && phba->cfg_enable_npiv &&
  611. phba->vpd.sli3Feat.cmv) {
  612. mb->un.varCfgPort.max_vpi = phba->max_vpi;
  613. mb->un.varCfgPort.cmv = 1;
  614. phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED;
  615. } else
  616. mb->un.varCfgPort.max_vpi = phba->max_vpi = 0;
  617. } else
  618. phba->sli_rev = 2;
  619. mb->un.varCfgPort.sli_mode = phba->sli_rev;
  620. /* Now setup pcb */
  621. phba->slim2p->pcb.type = TYPE_NATIVE_SLI2;
  622. phba->slim2p->pcb.feature = FEATURE_INITIAL_SLI2;
  623. /* Setup Mailbox pointers */
  624. phba->slim2p->pcb.mailBoxSize = offsetof(MAILBOX_t, us) +
  625. sizeof(struct sli2_desc);
  626. offset = (uint8_t *)&phba->slim2p->mbx - (uint8_t *)phba->slim2p;
  627. pdma_addr = phba->slim2p_mapping + offset;
  628. phba->slim2p->pcb.mbAddrHigh = putPaddrHigh(pdma_addr);
  629. phba->slim2p->pcb.mbAddrLow = putPaddrLow(pdma_addr);
  630. /*
  631. * Setup Host Group ring pointer.
  632. *
  633. * For efficiency reasons, the ring get/put pointers can be
  634. * placed in adapter memory (SLIM) rather than in host memory.
  635. * This allows firmware to avoid PCI reads/writes when updating
  636. * and checking pointers.
  637. *
  638. * The firmware recognizes the use of SLIM memory by comparing
  639. * the address of the get/put pointers structure with that of
  640. * the SLIM BAR (BAR0).
  641. *
  642. * Caution: be sure to use the PCI config space value of BAR0/BAR1
  643. * (the hardware's view of the base address), not the OS's
  644. * value of pci_resource_start() as the OS value may be a cookie
  645. * for ioremap/iomap.
  646. */
  647. pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_0, &bar_low);
  648. pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_1, &bar_high);
  649. /*
  650. * Set up HGP - Port Memory
  651. *
  652. * The port expects the host get/put pointers to reside in memory
  653. * following the "non-diagnostic" mode mailbox (32 words, 0x80 bytes)
  654. * area of SLIM. In SLI-2 mode, there's an additional 16 reserved
  655. * words (0x40 bytes). This area is not reserved if HBQs are
  656. * configured in SLI-3.
  657. *
  658. * CR0Put - SLI2(no HBQs) = 0xc0, With HBQs = 0x80
  659. * RR0Get 0xc4 0x84
  660. * CR1Put 0xc8 0x88
  661. * RR1Get 0xcc 0x8c
  662. * CR2Put 0xd0 0x90
  663. * RR2Get 0xd4 0x94
  664. * CR3Put 0xd8 0x98
  665. * RR3Get 0xdc 0x9c
  666. *
  667. * Reserved 0xa0-0xbf
  668. * If HBQs configured:
  669. * HBQ 0 Put ptr 0xc0
  670. * HBQ 1 Put ptr 0xc4
  671. * HBQ 2 Put ptr 0xc8
  672. * ......
  673. * HBQ(M-1)Put Pointer 0xc0+(M-1)*4
  674. *
  675. */
  676. if (phba->sli_rev == 3) {
  677. phba->host_gp = &mb_slim->us.s3.host[0];
  678. phba->hbq_put = &mb_slim->us.s3.hbq_put[0];
  679. } else {
  680. phba->host_gp = &mb_slim->us.s2.host[0];
  681. phba->hbq_put = NULL;
  682. }
  683. /* mask off BAR0's flag bits 0 - 3 */
  684. phba->slim2p->pcb.hgpAddrLow = (bar_low & PCI_BASE_ADDRESS_MEM_MASK) +
  685. (void __iomem *) phba->host_gp -
  686. (void __iomem *)phba->MBslimaddr;
  687. if (bar_low & PCI_BASE_ADDRESS_MEM_TYPE_64)
  688. phba->slim2p->pcb.hgpAddrHigh = bar_high;
  689. else
  690. phba->slim2p->pcb.hgpAddrHigh = 0;
  691. /* write HGP data to SLIM at the required longword offset */
  692. memset(&hgp, 0, sizeof(struct lpfc_hgp));
  693. for (i=0; i < phba->sli.num_rings; i++) {
  694. lpfc_memcpy_to_slim(phba->host_gp + i, &hgp,
  695. sizeof(*phba->host_gp));
  696. }
  697. /* Setup Port Group ring pointer */
  698. if (phba->sli_rev == 3)
  699. pgp_offset = (uint8_t *)&phba->slim2p->mbx.us.s3_pgp.port -
  700. (uint8_t *)phba->slim2p;
  701. else
  702. pgp_offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port -
  703. (uint8_t *)phba->slim2p;
  704. pdma_addr = phba->slim2p_mapping + pgp_offset;
  705. phba->slim2p->pcb.pgpAddrHigh = putPaddrHigh(pdma_addr);
  706. phba->slim2p->pcb.pgpAddrLow = putPaddrLow(pdma_addr);
  707. phba->hbq_get = &phba->slim2p->mbx.us.s3_pgp.hbq_get[0];
  708. /* Use callback routine to setp rings in the pcb */
  709. lpfc_config_pcb_setup(phba);
  710. /* special handling for LC HBAs */
  711. if (lpfc_is_LC_HBA(phba->pcidev->device)) {
  712. uint32_t hbainit[5];
  713. lpfc_hba_init(phba, hbainit);
  714. memcpy(&mb->un.varCfgPort.hbainit, hbainit, 20);
  715. }
  716. /* Swap PCB if needed */
  717. lpfc_sli_pcimem_bcopy(&phba->slim2p->pcb, &phba->slim2p->pcb,
  718. sizeof(PCB_t));
  719. }
  720. void
  721. lpfc_kill_board(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
  722. {
  723. MAILBOX_t *mb = &pmb->mb;
  724. memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
  725. mb->mbxCommand = MBX_KILL_BOARD;
  726. mb->mbxOwner = OWN_HOST;
  727. return;
  728. }
  729. void
  730. lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
  731. {
  732. struct lpfc_sli *psli;
  733. psli = &phba->sli;
  734. list_add_tail(&mbq->list, &psli->mboxq);
  735. psli->mboxq_cnt++;
  736. return;
  737. }
  738. LPFC_MBOXQ_t *
  739. lpfc_mbox_get(struct lpfc_hba * phba)
  740. {
  741. LPFC_MBOXQ_t *mbq = NULL;
  742. struct lpfc_sli *psli = &phba->sli;
  743. list_remove_head((&psli->mboxq), mbq, LPFC_MBOXQ_t, list);
  744. if (mbq)
  745. psli->mboxq_cnt--;
  746. return mbq;
  747. }
  748. void
  749. lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
  750. {
  751. /* This function expects to be called from interupt context */
  752. spin_lock(&phba->hbalock);
  753. list_add_tail(&mbq->list, &phba->sli.mboxq_cmpl);
  754. spin_unlock(&phba->hbalock);
  755. return;
  756. }
  757. int
  758. lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd)
  759. {
  760. switch (cmd) {
  761. case MBX_WRITE_NV: /* 0x03 */
  762. case MBX_UPDATE_CFG: /* 0x1B */
  763. case MBX_DOWN_LOAD: /* 0x1C */
  764. case MBX_DEL_LD_ENTRY: /* 0x1D */
  765. case MBX_LOAD_AREA: /* 0x81 */
  766. case MBX_WRITE_WWN: /* 0x98 */
  767. case MBX_LOAD_EXP_ROM: /* 0x9C */
  768. return LPFC_MBOX_TMO_FLASH_CMD;
  769. }
  770. return LPFC_MBOX_TMO;
  771. }