mpt2sas_transport.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213
  1. /*
  2. * SAS Transport Layer for MPT (Message Passing Technology) based controllers
  3. *
  4. * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c
  5. * Copyright (C) 2007-2009 LSI Corporation
  6. * (mailto:DL-MPTFusionLinux@lsi.com)
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * NO WARRANTY
  19. * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
  20. * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
  21. * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
  22. * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
  23. * solely responsible for determining the appropriateness of using and
  24. * distributing the Program and assumes all risks associated with its
  25. * exercise of rights under this Agreement, including but not limited to
  26. * the risks and costs of program errors, damage to or loss of data,
  27. * programs or equipment, and unavailability or interruption of operations.
  28. * DISCLAIMER OF LIABILITY
  29. * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
  30. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31. * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
  32. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  33. * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  34. * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
  35. * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
  36. * You should have received a copy of the GNU General Public License
  37. * along with this program; if not, write to the Free Software
  38. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
  39. * USA.
  40. */
  41. #include <linux/module.h>
  42. #include <linux/kernel.h>
  43. #include <linux/init.h>
  44. #include <linux/errno.h>
  45. #include <linux/sched.h>
  46. #include <linux/workqueue.h>
  47. #include <linux/delay.h>
  48. #include <linux/pci.h>
  49. #include <scsi/scsi.h>
  50. #include <scsi/scsi_cmnd.h>
  51. #include <scsi/scsi_device.h>
  52. #include <scsi/scsi_host.h>
  53. #include <scsi/scsi_transport_sas.h>
  54. #include <scsi/scsi_dbg.h>
  55. #include "mpt2sas_base.h"
  56. /**
  57. * _transport_sas_node_find_by_sas_address - sas node search
  58. * @ioc: per adapter object
  59. * @sas_address: sas address of expander or sas host
  60. * Context: Calling function should acquire ioc->sas_node_lock.
  61. *
  62. * Search for either hba phys or expander device based on handle, then returns
  63. * the sas_node object.
  64. */
  65. static struct _sas_node *
  66. _transport_sas_node_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
  67. u64 sas_address)
  68. {
  69. if (ioc->sas_hba.sas_address == sas_address)
  70. return &ioc->sas_hba;
  71. else
  72. return mpt2sas_scsih_expander_find_by_sas_address(ioc,
  73. sas_address);
  74. }
  75. /**
  76. * _transport_convert_phy_link_rate -
  77. * @link_rate: link rate returned from mpt firmware
  78. *
  79. * Convert link_rate from mpi fusion into sas_transport form.
  80. */
  81. static enum sas_linkrate
  82. _transport_convert_phy_link_rate(u8 link_rate)
  83. {
  84. enum sas_linkrate rc;
  85. switch (link_rate) {
  86. case MPI2_SAS_NEG_LINK_RATE_1_5:
  87. rc = SAS_LINK_RATE_1_5_GBPS;
  88. break;
  89. case MPI2_SAS_NEG_LINK_RATE_3_0:
  90. rc = SAS_LINK_RATE_3_0_GBPS;
  91. break;
  92. case MPI2_SAS_NEG_LINK_RATE_6_0:
  93. rc = SAS_LINK_RATE_6_0_GBPS;
  94. break;
  95. case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED:
  96. rc = SAS_PHY_DISABLED;
  97. break;
  98. case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
  99. rc = SAS_LINK_RATE_FAILED;
  100. break;
  101. case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR:
  102. rc = SAS_SATA_PORT_SELECTOR;
  103. break;
  104. case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
  105. rc = SAS_PHY_RESET_IN_PROGRESS;
  106. break;
  107. default:
  108. case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
  109. case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
  110. rc = SAS_LINK_RATE_UNKNOWN;
  111. break;
  112. }
  113. return rc;
  114. }
  115. /**
  116. * _transport_set_identify - set identify for phys and end devices
  117. * @ioc: per adapter object
  118. * @handle: device handle
  119. * @identify: sas identify info
  120. *
  121. * Populates sas identify info.
  122. *
  123. * Returns 0 for success, non-zero for failure.
  124. */
  125. static int
  126. _transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
  127. struct sas_identify *identify)
  128. {
  129. Mpi2SasDevicePage0_t sas_device_pg0;
  130. Mpi2ConfigReply_t mpi_reply;
  131. u32 device_info;
  132. u32 ioc_status;
  133. if (ioc->shost_recovery) {
  134. printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
  135. __func__, ioc->name);
  136. return -EFAULT;
  137. }
  138. if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
  139. MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
  140. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  141. ioc->name, __FILE__, __LINE__, __func__);
  142. return -ENXIO;
  143. }
  144. ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
  145. MPI2_IOCSTATUS_MASK;
  146. if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  147. printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)"
  148. "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
  149. __FILE__, __LINE__, __func__);
  150. return -EIO;
  151. }
  152. memset(identify, 0, sizeof(identify));
  153. device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
  154. /* sas_address */
  155. identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
  156. /* device_type */
  157. switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
  158. case MPI2_SAS_DEVICE_INFO_NO_DEVICE:
  159. identify->device_type = SAS_PHY_UNUSED;
  160. break;
  161. case MPI2_SAS_DEVICE_INFO_END_DEVICE:
  162. identify->device_type = SAS_END_DEVICE;
  163. break;
  164. case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER:
  165. identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
  166. break;
  167. case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER:
  168. identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
  169. break;
  170. }
  171. /* initiator_port_protocols */
  172. if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR)
  173. identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
  174. if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR)
  175. identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
  176. if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR)
  177. identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
  178. if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST)
  179. identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
  180. /* target_port_protocols */
  181. if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)
  182. identify->target_port_protocols |= SAS_PROTOCOL_SSP;
  183. if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
  184. identify->target_port_protocols |= SAS_PROTOCOL_STP;
  185. if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET)
  186. identify->target_port_protocols |= SAS_PROTOCOL_SMP;
  187. if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
  188. identify->target_port_protocols |= SAS_PROTOCOL_SATA;
  189. return 0;
  190. }
  191. /**
  192. * mpt2sas_transport_done - internal transport layer callback handler.
  193. * @ioc: per adapter object
  194. * @smid: system request message index
  195. * @msix_index: MSIX table index supplied by the OS
  196. * @reply: reply message frame(lower 32bit addr)
  197. *
  198. * Callback handler when sending internal generated transport cmds.
  199. * The callback index passed is `ioc->transport_cb_idx`
  200. *
  201. * Return 1 meaning mf should be freed from _base_interrupt
  202. * 0 means the mf is freed from this function.
  203. */
  204. u8
  205. mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
  206. u32 reply)
  207. {
  208. MPI2DefaultReply_t *mpi_reply;
  209. mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
  210. if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED)
  211. return 1;
  212. if (ioc->transport_cmds.smid != smid)
  213. return 1;
  214. ioc->transport_cmds.status |= MPT2_CMD_COMPLETE;
  215. if (mpi_reply) {
  216. memcpy(ioc->transport_cmds.reply, mpi_reply,
  217. mpi_reply->MsgLength*4);
  218. ioc->transport_cmds.status |= MPT2_CMD_REPLY_VALID;
  219. }
  220. ioc->transport_cmds.status &= ~MPT2_CMD_PENDING;
  221. complete(&ioc->transport_cmds.done);
  222. return 1;
  223. }
  224. /* report manufacture request structure */
  225. struct rep_manu_request{
  226. u8 smp_frame_type;
  227. u8 function;
  228. u8 reserved;
  229. u8 request_length;
  230. };
  231. /* report manufacture reply structure */
  232. struct rep_manu_reply{
  233. u8 smp_frame_type; /* 0x41 */
  234. u8 function; /* 0x01 */
  235. u8 function_result;
  236. u8 response_length;
  237. u16 expander_change_count;
  238. u8 reserved0[2];
  239. u8 sas_format;
  240. u8 reserved2[3];
  241. u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
  242. u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
  243. u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
  244. u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
  245. u16 component_id;
  246. u8 component_revision_id;
  247. u8 reserved3;
  248. u8 vendor_specific[8];
  249. };
  250. /**
  251. * _transport_expander_report_manufacture - obtain SMP report_manufacture
  252. * @ioc: per adapter object
  253. * @sas_address: expander sas address
  254. * @edev: the sas_expander_device object
  255. *
  256. * Fills in the sas_expander_device object when SMP port is created.
  257. *
  258. * Returns 0 for success, non-zero for failure.
  259. */
  260. static int
  261. _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
  262. u64 sas_address, struct sas_expander_device *edev)
  263. {
  264. Mpi2SmpPassthroughRequest_t *mpi_request;
  265. Mpi2SmpPassthroughReply_t *mpi_reply;
  266. struct rep_manu_reply *manufacture_reply;
  267. struct rep_manu_request *manufacture_request;
  268. int rc;
  269. u16 smid;
  270. u32 ioc_state;
  271. unsigned long timeleft;
  272. void *psge;
  273. u32 sgl_flags;
  274. u8 issue_reset = 0;
  275. void *data_out = NULL;
  276. dma_addr_t data_out_dma;
  277. u32 sz;
  278. u64 *sas_address_le;
  279. u16 wait_state_count;
  280. if (ioc->shost_recovery) {
  281. printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
  282. __func__, ioc->name);
  283. return -EFAULT;
  284. }
  285. mutex_lock(&ioc->transport_cmds.mutex);
  286. if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
  287. printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
  288. ioc->name, __func__);
  289. rc = -EAGAIN;
  290. goto out;
  291. }
  292. ioc->transport_cmds.status = MPT2_CMD_PENDING;
  293. wait_state_count = 0;
  294. ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
  295. while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
  296. if (wait_state_count++ == 10) {
  297. printk(MPT2SAS_ERR_FMT
  298. "%s: failed due to ioc not operational\n",
  299. ioc->name, __func__);
  300. rc = -EFAULT;
  301. goto out;
  302. }
  303. ssleep(1);
  304. ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
  305. printk(MPT2SAS_INFO_FMT "%s: waiting for "
  306. "operational state(count=%d)\n", ioc->name,
  307. __func__, wait_state_count);
  308. }
  309. if (wait_state_count)
  310. printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
  311. ioc->name, __func__);
  312. smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
  313. if (!smid) {
  314. printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
  315. ioc->name, __func__);
  316. rc = -EAGAIN;
  317. goto out;
  318. }
  319. rc = 0;
  320. mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
  321. ioc->transport_cmds.smid = smid;
  322. sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
  323. data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
  324. if (!data_out) {
  325. printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
  326. __LINE__, __func__);
  327. rc = -ENOMEM;
  328. mpt2sas_base_free_smid(ioc, smid);
  329. goto out;
  330. }
  331. manufacture_request = data_out;
  332. manufacture_request->smp_frame_type = 0x40;
  333. manufacture_request->function = 1;
  334. manufacture_request->reserved = 0;
  335. manufacture_request->request_length = 0;
  336. memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
  337. mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
  338. mpi_request->PhysicalPort = 0xFF;
  339. mpi_request->VF_ID = 0; /* TODO */
  340. mpi_request->VP_ID = 0;
  341. sas_address_le = (u64 *)&mpi_request->SASAddress;
  342. *sas_address_le = cpu_to_le64(sas_address);
  343. mpi_request->RequestDataLength =
  344. cpu_to_le16(sizeof(struct rep_manu_request));
  345. psge = &mpi_request->SGL;
  346. /* WRITE sgel first */
  347. sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
  348. MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
  349. sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
  350. ioc->base_add_sg_single(psge, sgl_flags |
  351. sizeof(struct rep_manu_request), data_out_dma);
  352. /* incr sgel */
  353. psge += ioc->sge_size;
  354. /* READ sgel last */
  355. sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
  356. MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
  357. MPI2_SGE_FLAGS_END_OF_LIST);
  358. sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
  359. ioc->base_add_sg_single(psge, sgl_flags |
  360. sizeof(struct rep_manu_reply), data_out_dma +
  361. sizeof(struct rep_manu_request));
  362. dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - "
  363. "send to sas_addr(0x%016llx)\n", ioc->name,
  364. (unsigned long long)sas_address));
  365. mpt2sas_base_put_smid_default(ioc, smid);
  366. init_completion(&ioc->transport_cmds.done);
  367. timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
  368. 10*HZ);
  369. if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
  370. printk(MPT2SAS_ERR_FMT "%s: timeout\n",
  371. ioc->name, __func__);
  372. _debug_dump_mf(mpi_request,
  373. sizeof(Mpi2SmpPassthroughRequest_t)/4);
  374. if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
  375. issue_reset = 1;
  376. goto issue_host_reset;
  377. }
  378. dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - "
  379. "complete\n", ioc->name));
  380. if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
  381. u8 *tmp;
  382. mpi_reply = ioc->transport_cmds.reply;
  383. dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
  384. "report_manufacture - reply data transfer size(%d)\n",
  385. ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
  386. if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
  387. sizeof(struct rep_manu_reply))
  388. goto out;
  389. manufacture_reply = data_out + sizeof(struct rep_manu_request);
  390. strncpy(edev->vendor_id, manufacture_reply->vendor_id,
  391. SAS_EXPANDER_VENDOR_ID_LEN);
  392. strncpy(edev->product_id, manufacture_reply->product_id,
  393. SAS_EXPANDER_PRODUCT_ID_LEN);
  394. strncpy(edev->product_rev, manufacture_reply->product_rev,
  395. SAS_EXPANDER_PRODUCT_REV_LEN);
  396. edev->level = manufacture_reply->sas_format & 1;
  397. if (edev->level) {
  398. strncpy(edev->component_vendor_id,
  399. manufacture_reply->component_vendor_id,
  400. SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
  401. tmp = (u8 *)&manufacture_reply->component_id;
  402. edev->component_id = tmp[0] << 8 | tmp[1];
  403. edev->component_revision_id =
  404. manufacture_reply->component_revision_id;
  405. }
  406. } else
  407. dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
  408. "report_manufacture - no reply\n", ioc->name));
  409. issue_host_reset:
  410. if (issue_reset)
  411. mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
  412. FORCE_BIG_HAMMER);
  413. out:
  414. ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
  415. if (data_out)
  416. pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
  417. mutex_unlock(&ioc->transport_cmds.mutex);
  418. return rc;
  419. }
  420. /**
  421. * mpt2sas_transport_port_add - insert port to the list
  422. * @ioc: per adapter object
  423. * @handle: handle of attached device
  424. * @sas_address: sas address of parent expander or sas host
  425. * Context: This function will acquire ioc->sas_node_lock.
  426. *
  427. * Adding new port object to the sas_node->sas_port_list.
  428. *
  429. * Returns mpt2sas_port.
  430. */
  431. struct _sas_port *
  432. mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
  433. u64 sas_address)
  434. {
  435. struct _sas_phy *mpt2sas_phy, *next;
  436. struct _sas_port *mpt2sas_port;
  437. unsigned long flags;
  438. struct _sas_node *sas_node;
  439. struct sas_rphy *rphy;
  440. int i;
  441. struct sas_port *port;
  442. mpt2sas_port = kzalloc(sizeof(struct _sas_port),
  443. GFP_KERNEL);
  444. if (!mpt2sas_port) {
  445. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  446. ioc->name, __FILE__, __LINE__, __func__);
  447. return NULL;
  448. }
  449. INIT_LIST_HEAD(&mpt2sas_port->port_list);
  450. INIT_LIST_HEAD(&mpt2sas_port->phy_list);
  451. spin_lock_irqsave(&ioc->sas_node_lock, flags);
  452. sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
  453. spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
  454. if (!sas_node) {
  455. printk(MPT2SAS_ERR_FMT "%s: Could not find "
  456. "parent sas_address(0x%016llx)!\n", ioc->name,
  457. __func__, (unsigned long long)sas_address);
  458. goto out_fail;
  459. }
  460. if ((_transport_set_identify(ioc, handle,
  461. &mpt2sas_port->remote_identify))) {
  462. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  463. ioc->name, __FILE__, __LINE__, __func__);
  464. goto out_fail;
  465. }
  466. if (mpt2sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
  467. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  468. ioc->name, __FILE__, __LINE__, __func__);
  469. goto out_fail;
  470. }
  471. for (i = 0; i < sas_node->num_phys; i++) {
  472. if (sas_node->phy[i].remote_identify.sas_address !=
  473. mpt2sas_port->remote_identify.sas_address)
  474. continue;
  475. list_add_tail(&sas_node->phy[i].port_siblings,
  476. &mpt2sas_port->phy_list);
  477. mpt2sas_port->num_phys++;
  478. }
  479. if (!mpt2sas_port->num_phys) {
  480. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  481. ioc->name, __FILE__, __LINE__, __func__);
  482. goto out_fail;
  483. }
  484. port = sas_port_alloc_num(sas_node->parent_dev);
  485. if ((sas_port_add(port))) {
  486. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  487. ioc->name, __FILE__, __LINE__, __func__);
  488. goto out_fail;
  489. }
  490. list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
  491. port_siblings) {
  492. if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
  493. dev_printk(KERN_INFO, &port->dev, "add: handle(0x%04x)"
  494. ", sas_addr(0x%016llx), phy(%d)\n", handle,
  495. (unsigned long long)
  496. mpt2sas_port->remote_identify.sas_address,
  497. mpt2sas_phy->phy_id);
  498. sas_port_add_phy(port, mpt2sas_phy->phy);
  499. }
  500. mpt2sas_port->port = port;
  501. if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE)
  502. rphy = sas_end_device_alloc(port);
  503. else
  504. rphy = sas_expander_alloc(port,
  505. mpt2sas_port->remote_identify.device_type);
  506. rphy->identify = mpt2sas_port->remote_identify;
  507. if ((sas_rphy_add(rphy))) {
  508. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  509. ioc->name, __FILE__, __LINE__, __func__);
  510. }
  511. if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
  512. dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), "
  513. "sas_addr(0x%016llx)\n", handle,
  514. (unsigned long long)
  515. mpt2sas_port->remote_identify.sas_address);
  516. mpt2sas_port->rphy = rphy;
  517. spin_lock_irqsave(&ioc->sas_node_lock, flags);
  518. list_add_tail(&mpt2sas_port->port_list, &sas_node->sas_port_list);
  519. spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
  520. /* fill in report manufacture */
  521. if (mpt2sas_port->remote_identify.device_type ==
  522. MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
  523. mpt2sas_port->remote_identify.device_type ==
  524. MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
  525. _transport_expander_report_manufacture(ioc,
  526. mpt2sas_port->remote_identify.sas_address,
  527. rphy_to_expander_device(rphy));
  528. return mpt2sas_port;
  529. out_fail:
  530. list_for_each_entry_safe(mpt2sas_phy, next, &mpt2sas_port->phy_list,
  531. port_siblings)
  532. list_del(&mpt2sas_phy->port_siblings);
  533. kfree(mpt2sas_port);
  534. return NULL;
  535. }
  536. /**
  537. * mpt2sas_transport_port_remove - remove port from the list
  538. * @ioc: per adapter object
  539. * @sas_address: sas address of attached device
  540. * @sas_address_parent: sas address of parent expander or sas host
  541. * Context: This function will acquire ioc->sas_node_lock.
  542. *
  543. * Removing object and freeing associated memory from the
  544. * ioc->sas_port_list.
  545. *
  546. * Return nothing.
  547. */
  548. void
  549. mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
  550. u64 sas_address_parent)
  551. {
  552. int i;
  553. unsigned long flags;
  554. struct _sas_port *mpt2sas_port, *next;
  555. struct _sas_node *sas_node;
  556. u8 found = 0;
  557. struct _sas_phy *mpt2sas_phy, *next_phy;
  558. spin_lock_irqsave(&ioc->sas_node_lock, flags);
  559. sas_node = _transport_sas_node_find_by_sas_address(ioc,
  560. sas_address_parent);
  561. spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
  562. if (!sas_node)
  563. return;
  564. list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
  565. port_list) {
  566. if (mpt2sas_port->remote_identify.sas_address != sas_address)
  567. continue;
  568. found = 1;
  569. list_del(&mpt2sas_port->port_list);
  570. goto out;
  571. }
  572. out:
  573. if (!found)
  574. return;
  575. for (i = 0; i < sas_node->num_phys; i++) {
  576. if (sas_node->phy[i].remote_identify.sas_address == sas_address)
  577. memset(&sas_node->phy[i].remote_identify, 0 ,
  578. sizeof(struct sas_identify));
  579. }
  580. list_for_each_entry_safe(mpt2sas_phy, next_phy,
  581. &mpt2sas_port->phy_list, port_siblings) {
  582. if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
  583. dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
  584. "remove: sas_addr(0x%016llx), phy(%d)\n",
  585. (unsigned long long)
  586. mpt2sas_port->remote_identify.sas_address,
  587. mpt2sas_phy->phy_id);
  588. sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
  589. list_del(&mpt2sas_phy->port_siblings);
  590. }
  591. sas_port_delete(mpt2sas_port->port);
  592. kfree(mpt2sas_port);
  593. }
  594. /**
  595. * mpt2sas_transport_add_host_phy - report sas_host phy to transport
  596. * @ioc: per adapter object
  597. * @mpt2sas_phy: mpt2sas per phy object
  598. * @phy_pg0: sas phy page 0
  599. * @parent_dev: parent device class object
  600. *
  601. * Returns 0 for success, non-zero for failure.
  602. */
  603. int
  604. mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
  605. *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
  606. {
  607. struct sas_phy *phy;
  608. int phy_index = mpt2sas_phy->phy_id;
  609. INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
  610. phy = sas_phy_alloc(parent_dev, phy_index);
  611. if (!phy) {
  612. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  613. ioc->name, __FILE__, __LINE__, __func__);
  614. return -1;
  615. }
  616. if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
  617. &mpt2sas_phy->identify))) {
  618. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  619. ioc->name, __FILE__, __LINE__, __func__);
  620. return -1;
  621. }
  622. phy->identify = mpt2sas_phy->identify;
  623. mpt2sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
  624. if (mpt2sas_phy->attached_handle)
  625. _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
  626. &mpt2sas_phy->remote_identify);
  627. phy->identify.phy_identifier = mpt2sas_phy->phy_id;
  628. phy->negotiated_linkrate = _transport_convert_phy_link_rate(
  629. phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
  630. phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
  631. phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
  632. phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
  633. phy_pg0.HwLinkRate >> 4);
  634. phy->minimum_linkrate = _transport_convert_phy_link_rate(
  635. phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
  636. phy->maximum_linkrate = _transport_convert_phy_link_rate(
  637. phy_pg0.ProgrammedLinkRate >> 4);
  638. if ((sas_phy_add(phy))) {
  639. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  640. ioc->name, __FILE__, __LINE__, __func__);
  641. sas_phy_free(phy);
  642. return -1;
  643. }
  644. if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
  645. dev_printk(KERN_INFO, &phy->dev,
  646. "add: handle(0x%04x), sas_addr(0x%016llx)\n"
  647. "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
  648. mpt2sas_phy->handle, (unsigned long long)
  649. mpt2sas_phy->identify.sas_address,
  650. mpt2sas_phy->attached_handle,
  651. (unsigned long long)
  652. mpt2sas_phy->remote_identify.sas_address);
  653. mpt2sas_phy->phy = phy;
  654. return 0;
  655. }
  656. /**
  657. * mpt2sas_transport_add_expander_phy - report expander phy to transport
  658. * @ioc: per adapter object
  659. * @mpt2sas_phy: mpt2sas per phy object
  660. * @expander_pg1: expander page 1
  661. * @parent_dev: parent device class object
  662. *
  663. * Returns 0 for success, non-zero for failure.
  664. */
  665. int
  666. mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
  667. *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev)
  668. {
  669. struct sas_phy *phy;
  670. int phy_index = mpt2sas_phy->phy_id;
  671. INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
  672. phy = sas_phy_alloc(parent_dev, phy_index);
  673. if (!phy) {
  674. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  675. ioc->name, __FILE__, __LINE__, __func__);
  676. return -1;
  677. }
  678. if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
  679. &mpt2sas_phy->identify))) {
  680. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  681. ioc->name, __FILE__, __LINE__, __func__);
  682. return -1;
  683. }
  684. phy->identify = mpt2sas_phy->identify;
  685. mpt2sas_phy->attached_handle =
  686. le16_to_cpu(expander_pg1.AttachedDevHandle);
  687. if (mpt2sas_phy->attached_handle)
  688. _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
  689. &mpt2sas_phy->remote_identify);
  690. phy->identify.phy_identifier = mpt2sas_phy->phy_id;
  691. phy->negotiated_linkrate = _transport_convert_phy_link_rate(
  692. expander_pg1.NegotiatedLinkRate &
  693. MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
  694. phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
  695. expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
  696. phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
  697. expander_pg1.HwLinkRate >> 4);
  698. phy->minimum_linkrate = _transport_convert_phy_link_rate(
  699. expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
  700. phy->maximum_linkrate = _transport_convert_phy_link_rate(
  701. expander_pg1.ProgrammedLinkRate >> 4);
  702. if ((sas_phy_add(phy))) {
  703. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  704. ioc->name, __FILE__, __LINE__, __func__);
  705. sas_phy_free(phy);
  706. return -1;
  707. }
  708. if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
  709. dev_printk(KERN_INFO, &phy->dev,
  710. "add: handle(0x%04x), sas_addr(0x%016llx)\n"
  711. "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
  712. mpt2sas_phy->handle, (unsigned long long)
  713. mpt2sas_phy->identify.sas_address,
  714. mpt2sas_phy->attached_handle,
  715. (unsigned long long)
  716. mpt2sas_phy->remote_identify.sas_address);
  717. mpt2sas_phy->phy = phy;
  718. return 0;
  719. }
  720. /**
  721. * mpt2sas_transport_update_links - refreshing phy link changes
  722. * @ioc: per adapter object
  723. * @sas_address: sas address of parent expander or sas host
  724. * @handle: attached device handle
  725. * @phy_numberv: phy number
  726. * @link_rate: new link rate
  727. *
  728. * Returns nothing.
  729. */
  730. void
  731. mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
  732. u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
  733. {
  734. unsigned long flags;
  735. struct _sas_node *sas_node;
  736. struct _sas_phy *mpt2sas_phy;
  737. if (ioc->shost_recovery)
  738. return;
  739. spin_lock_irqsave(&ioc->sas_node_lock, flags);
  740. sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
  741. spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
  742. if (!sas_node)
  743. return;
  744. mpt2sas_phy = &sas_node->phy[phy_number];
  745. mpt2sas_phy->attached_handle = handle;
  746. if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5))
  747. _transport_set_identify(ioc, handle,
  748. &mpt2sas_phy->remote_identify);
  749. else
  750. memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
  751. sas_identify));
  752. if (mpt2sas_phy->phy)
  753. mpt2sas_phy->phy->negotiated_linkrate =
  754. _transport_convert_phy_link_rate(link_rate);
  755. if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
  756. dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
  757. "refresh: parent sas_addr(0x%016llx),\n"
  758. "\tlink_rate(0x%02x), phy(%d)\n"
  759. "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
  760. (unsigned long long)sas_address,
  761. link_rate, phy_number, handle, (unsigned long long)
  762. mpt2sas_phy->remote_identify.sas_address);
  763. }
  764. static inline void *
  765. phy_to_ioc(struct sas_phy *phy)
  766. {
  767. struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
  768. return shost_priv(shost);
  769. }
  770. static inline void *
  771. rphy_to_ioc(struct sas_rphy *rphy)
  772. {
  773. struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
  774. return shost_priv(shost);
  775. }
  776. /**
  777. * _transport_get_linkerrors -
  778. * @phy: The sas phy object
  779. *
  780. * Only support sas_host direct attached phys.
  781. * Returns 0 for success, non-zero for failure.
  782. *
  783. */
  784. static int
  785. _transport_get_linkerrors(struct sas_phy *phy)
  786. {
  787. struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
  788. struct _sas_phy *mpt2sas_phy;
  789. Mpi2ConfigReply_t mpi_reply;
  790. Mpi2SasPhyPage1_t phy_pg1;
  791. int i;
  792. for (i = 0, mpt2sas_phy = NULL; i < ioc->sas_hba.num_phys &&
  793. !mpt2sas_phy; i++) {
  794. if (ioc->sas_hba.phy[i].phy != phy)
  795. continue;
  796. mpt2sas_phy = &ioc->sas_hba.phy[i];
  797. }
  798. if (!mpt2sas_phy) /* this phy not on sas_host */
  799. return -EINVAL;
  800. if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
  801. mpt2sas_phy->phy_id))) {
  802. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  803. ioc->name, __FILE__, __LINE__, __func__);
  804. return -ENXIO;
  805. }
  806. if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
  807. printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
  808. "(0x%04x), loginfo(0x%08x)\n", ioc->name,
  809. mpt2sas_phy->phy_id,
  810. le16_to_cpu(mpi_reply.IOCStatus),
  811. le32_to_cpu(mpi_reply.IOCLogInfo));
  812. phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
  813. phy->running_disparity_error_count =
  814. le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
  815. phy->loss_of_dword_sync_count =
  816. le32_to_cpu(phy_pg1.LossDwordSynchCount);
  817. phy->phy_reset_problem_count =
  818. le32_to_cpu(phy_pg1.PhyResetProblemCount);
  819. return 0;
  820. }
  821. /**
  822. * _transport_get_enclosure_identifier -
  823. * @phy: The sas phy object
  824. *
  825. * Obtain the enclosure logical id for an expander.
  826. * Returns 0 for success, non-zero for failure.
  827. */
  828. static int
  829. _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
  830. {
  831. struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
  832. struct _sas_node *sas_expander;
  833. unsigned long flags;
  834. spin_lock_irqsave(&ioc->sas_node_lock, flags);
  835. sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
  836. rphy->identify.sas_address);
  837. spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
  838. if (!sas_expander)
  839. return -ENXIO;
  840. *identifier = sas_expander->enclosure_logical_id;
  841. return 0;
  842. }
  843. /**
  844. * _transport_get_bay_identifier -
  845. * @phy: The sas phy object
  846. *
  847. * Returns the slot id for a device that resides inside an enclosure.
  848. */
  849. static int
  850. _transport_get_bay_identifier(struct sas_rphy *rphy)
  851. {
  852. struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
  853. struct _sas_device *sas_device;
  854. unsigned long flags;
  855. spin_lock_irqsave(&ioc->sas_device_lock, flags);
  856. sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
  857. rphy->identify.sas_address);
  858. spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
  859. if (!sas_device)
  860. return -ENXIO;
  861. return sas_device->slot;
  862. }
  863. /**
  864. * _transport_phy_reset -
  865. * @phy: The sas phy object
  866. * @hard_reset:
  867. *
  868. * Only support sas_host direct attached phys.
  869. * Returns 0 for success, non-zero for failure.
  870. */
  871. static int
  872. _transport_phy_reset(struct sas_phy *phy, int hard_reset)
  873. {
  874. struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
  875. struct _sas_phy *mpt2sas_phy;
  876. Mpi2SasIoUnitControlReply_t mpi_reply;
  877. Mpi2SasIoUnitControlRequest_t mpi_request;
  878. int i;
  879. for (i = 0, mpt2sas_phy = NULL; i < ioc->sas_hba.num_phys &&
  880. !mpt2sas_phy; i++) {
  881. if (ioc->sas_hba.phy[i].phy != phy)
  882. continue;
  883. mpt2sas_phy = &ioc->sas_hba.phy[i];
  884. }
  885. if (!mpt2sas_phy) /* this phy not on sas_host */
  886. return -EINVAL;
  887. memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
  888. mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
  889. mpi_request.Operation = hard_reset ?
  890. MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
  891. mpi_request.PhyNum = mpt2sas_phy->phy_id;
  892. if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
  893. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  894. ioc->name, __FILE__, __LINE__, __func__);
  895. return -ENXIO;
  896. }
  897. if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
  898. printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
  899. "(0x%04x), loginfo(0x%08x)\n", ioc->name,
  900. mpt2sas_phy->phy_id,
  901. le16_to_cpu(mpi_reply.IOCStatus),
  902. le32_to_cpu(mpi_reply.IOCLogInfo));
  903. return 0;
  904. }
  905. /**
  906. * _transport_smp_handler - transport portal for smp passthru
  907. * @shost: shost object
  908. * @rphy: sas transport rphy object
  909. * @req:
  910. *
  911. * This used primarily for smp_utils.
  912. * Example:
  913. * smp_rep_general /sys/class/bsg/expander-5:0
  914. */
  915. static int
  916. _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
  917. struct request *req)
  918. {
  919. struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
  920. Mpi2SmpPassthroughRequest_t *mpi_request;
  921. Mpi2SmpPassthroughReply_t *mpi_reply;
  922. int rc;
  923. u16 smid;
  924. u32 ioc_state;
  925. unsigned long timeleft;
  926. void *psge;
  927. u32 sgl_flags;
  928. u8 issue_reset = 0;
  929. dma_addr_t dma_addr_in = 0;
  930. dma_addr_t dma_addr_out = 0;
  931. u16 wait_state_count;
  932. struct request *rsp = req->next_rq;
  933. if (!rsp) {
  934. printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
  935. "missing\n", ioc->name, __func__);
  936. return -EINVAL;
  937. }
  938. /* do we need to support multiple segments? */
  939. if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
  940. printk(MPT2SAS_ERR_FMT "%s: multiple segments req %u %u, "
  941. "rsp %u %u\n", ioc->name, __func__, req->bio->bi_vcnt,
  942. blk_rq_bytes(req), rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
  943. return -EINVAL;
  944. }
  945. if (ioc->shost_recovery) {
  946. printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
  947. __func__, ioc->name);
  948. return -EFAULT;
  949. }
  950. rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
  951. if (rc)
  952. return rc;
  953. if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
  954. printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name,
  955. __func__);
  956. rc = -EAGAIN;
  957. goto out;
  958. }
  959. ioc->transport_cmds.status = MPT2_CMD_PENDING;
  960. wait_state_count = 0;
  961. ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
  962. while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
  963. if (wait_state_count++ == 10) {
  964. printk(MPT2SAS_ERR_FMT
  965. "%s: failed due to ioc not operational\n",
  966. ioc->name, __func__);
  967. rc = -EFAULT;
  968. goto out;
  969. }
  970. ssleep(1);
  971. ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
  972. printk(MPT2SAS_INFO_FMT "%s: waiting for "
  973. "operational state(count=%d)\n", ioc->name,
  974. __func__, wait_state_count);
  975. }
  976. if (wait_state_count)
  977. printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
  978. ioc->name, __func__);
  979. smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
  980. if (!smid) {
  981. printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
  982. ioc->name, __func__);
  983. rc = -EAGAIN;
  984. goto out;
  985. }
  986. rc = 0;
  987. mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
  988. ioc->transport_cmds.smid = smid;
  989. memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
  990. mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
  991. mpi_request->PhysicalPort = 0xFF;
  992. mpi_request->VF_ID = 0; /* TODO */
  993. mpi_request->VP_ID = 0;
  994. *((u64 *)&mpi_request->SASAddress) = (rphy) ?
  995. cpu_to_le64(rphy->identify.sas_address) :
  996. cpu_to_le64(ioc->sas_hba.sas_address);
  997. mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
  998. psge = &mpi_request->SGL;
  999. /* WRITE sgel first */
  1000. sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
  1001. MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
  1002. sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
  1003. dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
  1004. blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
  1005. if (!dma_addr_out) {
  1006. mpt2sas_base_free_smid(ioc, smid);
  1007. goto unmap;
  1008. }
  1009. ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(req) - 4),
  1010. dma_addr_out);
  1011. /* incr sgel */
  1012. psge += ioc->sge_size;
  1013. /* READ sgel last */
  1014. sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
  1015. MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
  1016. MPI2_SGE_FLAGS_END_OF_LIST);
  1017. sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
  1018. dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
  1019. blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
  1020. if (!dma_addr_in) {
  1021. mpt2sas_base_free_smid(ioc, smid);
  1022. goto unmap;
  1023. }
  1024. ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(rsp) + 4),
  1025. dma_addr_in);
  1026. dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
  1027. "sending smp request\n", ioc->name, __func__));
  1028. mpt2sas_base_put_smid_default(ioc, smid);
  1029. init_completion(&ioc->transport_cmds.done);
  1030. timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
  1031. 10*HZ);
  1032. if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
  1033. printk(MPT2SAS_ERR_FMT "%s : timeout\n",
  1034. __func__, ioc->name);
  1035. _debug_dump_mf(mpi_request,
  1036. sizeof(Mpi2SmpPassthroughRequest_t)/4);
  1037. if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
  1038. issue_reset = 1;
  1039. goto issue_host_reset;
  1040. }
  1041. dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
  1042. "complete\n", ioc->name, __func__));
  1043. if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
  1044. mpi_reply = ioc->transport_cmds.reply;
  1045. dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
  1046. "%s - reply data transfer size(%d)\n",
  1047. ioc->name, __func__,
  1048. le16_to_cpu(mpi_reply->ResponseDataLength)));
  1049. memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
  1050. req->sense_len = sizeof(*mpi_reply);
  1051. req->resid_len = 0;
  1052. rsp->resid_len -= mpi_reply->ResponseDataLength;
  1053. } else {
  1054. dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
  1055. "%s - no reply\n", ioc->name, __func__));
  1056. rc = -ENXIO;
  1057. }
  1058. issue_host_reset:
  1059. if (issue_reset) {
  1060. mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
  1061. FORCE_BIG_HAMMER);
  1062. rc = -ETIMEDOUT;
  1063. }
  1064. unmap:
  1065. if (dma_addr_out)
  1066. pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req),
  1067. PCI_DMA_BIDIRECTIONAL);
  1068. if (dma_addr_in)
  1069. pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
  1070. PCI_DMA_BIDIRECTIONAL);
  1071. out:
  1072. ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
  1073. mutex_unlock(&ioc->transport_cmds.mutex);
  1074. return rc;
  1075. }
  1076. struct sas_function_template mpt2sas_transport_functions = {
  1077. .get_linkerrors = _transport_get_linkerrors,
  1078. .get_enclosure_identifier = _transport_get_enclosure_identifier,
  1079. .get_bay_identifier = _transport_get_bay_identifier,
  1080. .phy_reset = _transport_phy_reset,
  1081. .smp_handler = _transport_smp_handler,
  1082. };
  1083. struct scsi_transport_template *mpt2sas_transport_template;