mpt2sas_transport.c 37 KB

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