mpt2sas_transport.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223
  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_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. * @msix_index: MSIX table index supplied by the OS
  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 1 meaning mf should be freed from _base_interrupt
  201. * 0 means the mf is freed from this function.
  202. */
  203. u8
  204. mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
  205. u32 reply)
  206. {
  207. MPI2DefaultReply_t *mpi_reply;
  208. mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
  209. if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED)
  210. return 1;
  211. if (ioc->transport_cmds.smid != smid)
  212. return 1;
  213. ioc->transport_cmds.status |= MPT2_CMD_COMPLETE;
  214. if (mpi_reply) {
  215. memcpy(ioc->transport_cmds.reply, mpi_reply,
  216. mpi_reply->MsgLength*4);
  217. ioc->transport_cmds.status |= MPT2_CMD_REPLY_VALID;
  218. }
  219. ioc->transport_cmds.status &= ~MPT2_CMD_PENDING;
  220. complete(&ioc->transport_cmds.done);
  221. return 1;
  222. }
  223. /* report manufacture request structure */
  224. struct rep_manu_request{
  225. u8 smp_frame_type;
  226. u8 function;
  227. u8 reserved;
  228. u8 request_length;
  229. };
  230. /* report manufacture reply structure */
  231. struct rep_manu_reply{
  232. u8 smp_frame_type; /* 0x41 */
  233. u8 function; /* 0x01 */
  234. u8 function_result;
  235. u8 response_length;
  236. u16 expander_change_count;
  237. u8 reserved0[2];
  238. u8 sas_format:1;
  239. u8 reserved1:7;
  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 = sizeof(struct rep_manu_request);
  344. psge = &mpi_request->SGL;
  345. /* WRITE sgel first */
  346. sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
  347. MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
  348. sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
  349. ioc->base_add_sg_single(psge, sgl_flags |
  350. sizeof(struct rep_manu_request), data_out_dma);
  351. /* incr sgel */
  352. psge += ioc->sge_size;
  353. /* READ sgel last */
  354. sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
  355. MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
  356. MPI2_SGE_FLAGS_END_OF_LIST);
  357. sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
  358. ioc->base_add_sg_single(psge, sgl_flags |
  359. sizeof(struct rep_manu_reply), data_out_dma +
  360. sizeof(struct rep_manu_request));
  361. dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - "
  362. "send to sas_addr(0x%016llx)\n", ioc->name,
  363. (unsigned long long)sas_address));
  364. mpt2sas_base_put_smid_default(ioc, smid);
  365. init_completion(&ioc->transport_cmds.done);
  366. timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
  367. 10*HZ);
  368. if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
  369. printk(MPT2SAS_ERR_FMT "%s: timeout\n",
  370. ioc->name, __func__);
  371. _debug_dump_mf(mpi_request,
  372. sizeof(Mpi2SmpPassthroughRequest_t)/4);
  373. if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
  374. issue_reset = 1;
  375. goto issue_host_reset;
  376. }
  377. dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - "
  378. "complete\n", ioc->name));
  379. if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
  380. u8 *tmp;
  381. mpi_reply = ioc->transport_cmds.reply;
  382. dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
  383. "report_manufacture - reply data transfer size(%d)\n",
  384. ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
  385. if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
  386. sizeof(struct rep_manu_reply))
  387. goto out;
  388. manufacture_reply = data_out + sizeof(struct rep_manu_request);
  389. strncpy(edev->vendor_id, manufacture_reply->vendor_id,
  390. SAS_EXPANDER_VENDOR_ID_LEN);
  391. strncpy(edev->product_id, manufacture_reply->product_id,
  392. SAS_EXPANDER_PRODUCT_ID_LEN);
  393. strncpy(edev->product_rev, manufacture_reply->product_rev,
  394. SAS_EXPANDER_PRODUCT_REV_LEN);
  395. edev->level = manufacture_reply->sas_format;
  396. if (manufacture_reply->sas_format) {
  397. strncpy(edev->component_vendor_id,
  398. manufacture_reply->component_vendor_id,
  399. SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
  400. tmp = (u8 *)&manufacture_reply->component_id;
  401. edev->component_id = tmp[0] << 8 | tmp[1];
  402. edev->component_revision_id =
  403. manufacture_reply->component_revision_id;
  404. }
  405. } else
  406. dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
  407. "report_manufacture - no reply\n", ioc->name));
  408. issue_host_reset:
  409. if (issue_reset)
  410. mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
  411. FORCE_BIG_HAMMER);
  412. out:
  413. ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
  414. if (data_out)
  415. pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
  416. mutex_unlock(&ioc->transport_cmds.mutex);
  417. return rc;
  418. }
  419. /**
  420. * mpt2sas_transport_port_add - insert port to the list
  421. * @ioc: per adapter object
  422. * @handle: handle of attached device
  423. * @parent_handle: parent handle(either hba or expander)
  424. * Context: This function will acquire ioc->sas_node_lock.
  425. *
  426. * Adding new port object to the sas_node->sas_port_list.
  427. *
  428. * Returns mpt2sas_port.
  429. */
  430. struct _sas_port *
  431. mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
  432. u16 parent_handle)
  433. {
  434. struct _sas_phy *mpt2sas_phy, *next;
  435. struct _sas_port *mpt2sas_port;
  436. unsigned long flags;
  437. struct _sas_node *sas_node;
  438. struct sas_rphy *rphy;
  439. int i;
  440. struct sas_port *port;
  441. if (!parent_handle)
  442. return NULL;
  443. mpt2sas_port = kzalloc(sizeof(struct _sas_port),
  444. GFP_KERNEL);
  445. if (!mpt2sas_port) {
  446. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  447. ioc->name, __FILE__, __LINE__, __func__);
  448. return NULL;
  449. }
  450. INIT_LIST_HEAD(&mpt2sas_port->port_list);
  451. INIT_LIST_HEAD(&mpt2sas_port->phy_list);
  452. spin_lock_irqsave(&ioc->sas_node_lock, flags);
  453. sas_node = _transport_sas_node_find_by_handle(ioc, parent_handle);
  454. spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
  455. if (!sas_node) {
  456. printk(MPT2SAS_ERR_FMT "%s: Could not find parent(0x%04x)!\n",
  457. ioc->name, __func__, parent_handle);
  458. goto out_fail;
  459. }
  460. mpt2sas_port->handle = parent_handle;
  461. mpt2sas_port->sas_address = sas_node->sas_address;
  462. if ((_transport_set_identify(ioc, handle,
  463. &mpt2sas_port->remote_identify))) {
  464. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  465. ioc->name, __FILE__, __LINE__, __func__);
  466. goto out_fail;
  467. }
  468. if (mpt2sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
  469. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  470. ioc->name, __FILE__, __LINE__, __func__);
  471. goto out_fail;
  472. }
  473. for (i = 0; i < sas_node->num_phys; i++) {
  474. if (sas_node->phy[i].remote_identify.sas_address !=
  475. mpt2sas_port->remote_identify.sas_address)
  476. continue;
  477. list_add_tail(&sas_node->phy[i].port_siblings,
  478. &mpt2sas_port->phy_list);
  479. mpt2sas_port->num_phys++;
  480. }
  481. if (!mpt2sas_port->num_phys) {
  482. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  483. ioc->name, __FILE__, __LINE__, __func__);
  484. goto out_fail;
  485. }
  486. port = sas_port_alloc_num(sas_node->parent_dev);
  487. if ((sas_port_add(port))) {
  488. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  489. ioc->name, __FILE__, __LINE__, __func__);
  490. goto out_fail;
  491. }
  492. list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
  493. port_siblings) {
  494. if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
  495. dev_printk(KERN_INFO, &port->dev, "add: handle(0x%04x)"
  496. ", sas_addr(0x%016llx), phy(%d)\n", handle,
  497. (unsigned long long)
  498. mpt2sas_port->remote_identify.sas_address,
  499. mpt2sas_phy->phy_id);
  500. sas_port_add_phy(port, mpt2sas_phy->phy);
  501. }
  502. mpt2sas_port->port = port;
  503. if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE)
  504. rphy = sas_end_device_alloc(port);
  505. else
  506. rphy = sas_expander_alloc(port,
  507. mpt2sas_port->remote_identify.device_type);
  508. rphy->identify = mpt2sas_port->remote_identify;
  509. if ((sas_rphy_add(rphy))) {
  510. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  511. ioc->name, __FILE__, __LINE__, __func__);
  512. }
  513. if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
  514. dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), "
  515. "sas_addr(0x%016llx)\n", handle,
  516. (unsigned long long)
  517. mpt2sas_port->remote_identify.sas_address);
  518. mpt2sas_port->rphy = rphy;
  519. spin_lock_irqsave(&ioc->sas_node_lock, flags);
  520. list_add_tail(&mpt2sas_port->port_list, &sas_node->sas_port_list);
  521. spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
  522. /* fill in report manufacture */
  523. if (mpt2sas_port->remote_identify.device_type ==
  524. MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
  525. mpt2sas_port->remote_identify.device_type ==
  526. MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
  527. _transport_expander_report_manufacture(ioc,
  528. mpt2sas_port->remote_identify.sas_address,
  529. rphy_to_expander_device(rphy));
  530. return mpt2sas_port;
  531. out_fail:
  532. list_for_each_entry_safe(mpt2sas_phy, next, &mpt2sas_port->phy_list,
  533. port_siblings)
  534. list_del(&mpt2sas_phy->port_siblings);
  535. kfree(mpt2sas_port);
  536. return NULL;
  537. }
  538. /**
  539. * mpt2sas_transport_port_remove - remove port from the list
  540. * @ioc: per adapter object
  541. * @sas_address: sas address of attached device
  542. * @parent_handle: handle to the upstream parent(either hba or expander)
  543. * Context: This function will acquire ioc->sas_node_lock.
  544. *
  545. * Removing object and freeing associated memory from the
  546. * ioc->sas_port_list.
  547. *
  548. * Return nothing.
  549. */
  550. void
  551. mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
  552. u16 parent_handle)
  553. {
  554. int i;
  555. unsigned long flags;
  556. struct _sas_port *mpt2sas_port, *next;
  557. struct _sas_node *sas_node;
  558. u8 found = 0;
  559. struct _sas_phy *mpt2sas_phy, *next_phy;
  560. spin_lock_irqsave(&ioc->sas_node_lock, flags);
  561. sas_node = _transport_sas_node_find_by_handle(ioc, parent_handle);
  562. spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
  563. if (!sas_node)
  564. return;
  565. list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
  566. port_list) {
  567. if (mpt2sas_port->remote_identify.sas_address != sas_address)
  568. continue;
  569. found = 1;
  570. list_del(&mpt2sas_port->port_list);
  571. goto out;
  572. }
  573. out:
  574. if (!found)
  575. return;
  576. for (i = 0; i < sas_node->num_phys; i++) {
  577. if (sas_node->phy[i].remote_identify.sas_address == sas_address)
  578. memset(&sas_node->phy[i].remote_identify, 0 ,
  579. sizeof(struct sas_identify));
  580. }
  581. list_for_each_entry_safe(mpt2sas_phy, next_phy,
  582. &mpt2sas_port->phy_list, port_siblings) {
  583. if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
  584. dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
  585. "remove: parent_handle(0x%04x), "
  586. "sas_addr(0x%016llx), phy(%d)\n", parent_handle,
  587. (unsigned long long)
  588. mpt2sas_port->remote_identify.sas_address,
  589. mpt2sas_phy->phy_id);
  590. sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
  591. list_del(&mpt2sas_phy->port_siblings);
  592. }
  593. sas_port_delete(mpt2sas_port->port);
  594. kfree(mpt2sas_port);
  595. }
  596. /**
  597. * mpt2sas_transport_add_host_phy - report sas_host phy to transport
  598. * @ioc: per adapter object
  599. * @mpt2sas_phy: mpt2sas per phy object
  600. * @phy_pg0: sas phy page 0
  601. * @parent_dev: parent device class object
  602. *
  603. * Returns 0 for success, non-zero for failure.
  604. */
  605. int
  606. mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
  607. *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
  608. {
  609. struct sas_phy *phy;
  610. int phy_index = mpt2sas_phy->phy_id;
  611. INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
  612. phy = sas_phy_alloc(parent_dev, phy_index);
  613. if (!phy) {
  614. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  615. ioc->name, __FILE__, __LINE__, __func__);
  616. return -1;
  617. }
  618. if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
  619. &mpt2sas_phy->identify))) {
  620. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  621. ioc->name, __FILE__, __LINE__, __func__);
  622. return -1;
  623. }
  624. phy->identify = mpt2sas_phy->identify;
  625. mpt2sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
  626. if (mpt2sas_phy->attached_handle)
  627. _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
  628. &mpt2sas_phy->remote_identify);
  629. phy->identify.phy_identifier = mpt2sas_phy->phy_id;
  630. phy->negotiated_linkrate = _transport_convert_phy_link_rate(
  631. phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
  632. phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
  633. phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
  634. phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
  635. phy_pg0.HwLinkRate >> 4);
  636. phy->minimum_linkrate = _transport_convert_phy_link_rate(
  637. phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
  638. phy->maximum_linkrate = _transport_convert_phy_link_rate(
  639. phy_pg0.ProgrammedLinkRate >> 4);
  640. if ((sas_phy_add(phy))) {
  641. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  642. ioc->name, __FILE__, __LINE__, __func__);
  643. sas_phy_free(phy);
  644. return -1;
  645. }
  646. if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
  647. dev_printk(KERN_INFO, &phy->dev,
  648. "add: handle(0x%04x), sas_addr(0x%016llx)\n"
  649. "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
  650. mpt2sas_phy->handle, (unsigned long long)
  651. mpt2sas_phy->identify.sas_address,
  652. mpt2sas_phy->attached_handle,
  653. (unsigned long long)
  654. mpt2sas_phy->remote_identify.sas_address);
  655. mpt2sas_phy->phy = phy;
  656. return 0;
  657. }
  658. /**
  659. * mpt2sas_transport_add_expander_phy - report expander phy to transport
  660. * @ioc: per adapter object
  661. * @mpt2sas_phy: mpt2sas per phy object
  662. * @expander_pg1: expander page 1
  663. * @parent_dev: parent device class object
  664. *
  665. * Returns 0 for success, non-zero for failure.
  666. */
  667. int
  668. mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
  669. *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev)
  670. {
  671. struct sas_phy *phy;
  672. int phy_index = mpt2sas_phy->phy_id;
  673. INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
  674. phy = sas_phy_alloc(parent_dev, phy_index);
  675. if (!phy) {
  676. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  677. ioc->name, __FILE__, __LINE__, __func__);
  678. return -1;
  679. }
  680. if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
  681. &mpt2sas_phy->identify))) {
  682. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  683. ioc->name, __FILE__, __LINE__, __func__);
  684. return -1;
  685. }
  686. phy->identify = mpt2sas_phy->identify;
  687. mpt2sas_phy->attached_handle =
  688. le16_to_cpu(expander_pg1.AttachedDevHandle);
  689. if (mpt2sas_phy->attached_handle)
  690. _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
  691. &mpt2sas_phy->remote_identify);
  692. phy->identify.phy_identifier = mpt2sas_phy->phy_id;
  693. phy->negotiated_linkrate = _transport_convert_phy_link_rate(
  694. expander_pg1.NegotiatedLinkRate &
  695. MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
  696. phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
  697. expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
  698. phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
  699. expander_pg1.HwLinkRate >> 4);
  700. phy->minimum_linkrate = _transport_convert_phy_link_rate(
  701. expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
  702. phy->maximum_linkrate = _transport_convert_phy_link_rate(
  703. expander_pg1.ProgrammedLinkRate >> 4);
  704. if ((sas_phy_add(phy))) {
  705. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  706. ioc->name, __FILE__, __LINE__, __func__);
  707. sas_phy_free(phy);
  708. return -1;
  709. }
  710. if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
  711. dev_printk(KERN_INFO, &phy->dev,
  712. "add: handle(0x%04x), sas_addr(0x%016llx)\n"
  713. "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
  714. mpt2sas_phy->handle, (unsigned long long)
  715. mpt2sas_phy->identify.sas_address,
  716. mpt2sas_phy->attached_handle,
  717. (unsigned long long)
  718. mpt2sas_phy->remote_identify.sas_address);
  719. mpt2sas_phy->phy = phy;
  720. return 0;
  721. }
  722. /**
  723. * mpt2sas_transport_update_links - refreshing phy link changes
  724. * @ioc: per adapter object
  725. * @handle: handle to sas_host or expander
  726. * @attached_handle: attached device handle
  727. * @phy_numberv: phy number
  728. * @link_rate: new link rate
  729. *
  730. * Returns nothing.
  731. */
  732. void
  733. mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
  734. u16 handle, u16 attached_handle, u8 phy_number, u8 link_rate)
  735. {
  736. unsigned long flags;
  737. struct _sas_node *sas_node;
  738. struct _sas_phy *mpt2sas_phy;
  739. if (ioc->shost_recovery) {
  740. printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
  741. __func__, ioc->name);
  742. return;
  743. }
  744. spin_lock_irqsave(&ioc->sas_node_lock, flags);
  745. sas_node = _transport_sas_node_find_by_handle(ioc, handle);
  746. spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
  747. if (!sas_node)
  748. return;
  749. mpt2sas_phy = &sas_node->phy[phy_number];
  750. mpt2sas_phy->attached_handle = attached_handle;
  751. if (attached_handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5))
  752. _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
  753. &mpt2sas_phy->remote_identify);
  754. else
  755. memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
  756. sas_identify));
  757. if (mpt2sas_phy->phy)
  758. mpt2sas_phy->phy->negotiated_linkrate =
  759. _transport_convert_phy_link_rate(link_rate);
  760. if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
  761. dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
  762. "refresh: handle(0x%04x), sas_addr(0x%016llx),\n"
  763. "\tlink_rate(0x%02x), phy(%d)\n"
  764. "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
  765. handle, (unsigned long long)
  766. mpt2sas_phy->identify.sas_address, link_rate,
  767. phy_number, attached_handle,
  768. (unsigned long long)
  769. mpt2sas_phy->remote_identify.sas_address);
  770. }
  771. static inline void *
  772. phy_to_ioc(struct sas_phy *phy)
  773. {
  774. struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
  775. return shost_priv(shost);
  776. }
  777. static inline void *
  778. rphy_to_ioc(struct sas_rphy *rphy)
  779. {
  780. struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
  781. return shost_priv(shost);
  782. }
  783. /**
  784. * _transport_get_linkerrors -
  785. * @phy: The sas phy object
  786. *
  787. * Only support sas_host direct attached phys.
  788. * Returns 0 for success, non-zero for failure.
  789. *
  790. */
  791. static int
  792. _transport_get_linkerrors(struct sas_phy *phy)
  793. {
  794. struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
  795. struct _sas_phy *mpt2sas_phy;
  796. Mpi2ConfigReply_t mpi_reply;
  797. Mpi2SasPhyPage1_t phy_pg1;
  798. int i;
  799. for (i = 0, mpt2sas_phy = NULL; i < ioc->sas_hba.num_phys &&
  800. !mpt2sas_phy; i++) {
  801. if (ioc->sas_hba.phy[i].phy != phy)
  802. continue;
  803. mpt2sas_phy = &ioc->sas_hba.phy[i];
  804. }
  805. if (!mpt2sas_phy) /* this phy not on sas_host */
  806. return -EINVAL;
  807. if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
  808. mpt2sas_phy->phy_id))) {
  809. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  810. ioc->name, __FILE__, __LINE__, __func__);
  811. return -ENXIO;
  812. }
  813. if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
  814. printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
  815. "(0x%04x), loginfo(0x%08x)\n", ioc->name,
  816. mpt2sas_phy->phy_id,
  817. le16_to_cpu(mpi_reply.IOCStatus),
  818. le32_to_cpu(mpi_reply.IOCLogInfo));
  819. phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
  820. phy->running_disparity_error_count =
  821. le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
  822. phy->loss_of_dword_sync_count =
  823. le32_to_cpu(phy_pg1.LossDwordSynchCount);
  824. phy->phy_reset_problem_count =
  825. le32_to_cpu(phy_pg1.PhyResetProblemCount);
  826. return 0;
  827. }
  828. /**
  829. * _transport_get_enclosure_identifier -
  830. * @phy: The sas phy object
  831. *
  832. * Obtain the enclosure logical id for an expander.
  833. * Returns 0 for success, non-zero for failure.
  834. */
  835. static int
  836. _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
  837. {
  838. struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
  839. struct _sas_node *sas_expander;
  840. unsigned long flags;
  841. spin_lock_irqsave(&ioc->sas_node_lock, flags);
  842. sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
  843. rphy->identify.sas_address);
  844. spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
  845. if (!sas_expander)
  846. return -ENXIO;
  847. *identifier = sas_expander->enclosure_logical_id;
  848. return 0;
  849. }
  850. /**
  851. * _transport_get_bay_identifier -
  852. * @phy: The sas phy object
  853. *
  854. * Returns the slot id for a device that resides inside an enclosure.
  855. */
  856. static int
  857. _transport_get_bay_identifier(struct sas_rphy *rphy)
  858. {
  859. struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
  860. struct _sas_device *sas_device;
  861. unsigned long flags;
  862. spin_lock_irqsave(&ioc->sas_device_lock, flags);
  863. sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
  864. rphy->identify.sas_address);
  865. spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
  866. if (!sas_device)
  867. return -ENXIO;
  868. return sas_device->slot;
  869. }
  870. /**
  871. * _transport_phy_reset -
  872. * @phy: The sas phy object
  873. * @hard_reset:
  874. *
  875. * Only support sas_host direct attached phys.
  876. * Returns 0 for success, non-zero for failure.
  877. */
  878. static int
  879. _transport_phy_reset(struct sas_phy *phy, int hard_reset)
  880. {
  881. struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
  882. struct _sas_phy *mpt2sas_phy;
  883. Mpi2SasIoUnitControlReply_t mpi_reply;
  884. Mpi2SasIoUnitControlRequest_t mpi_request;
  885. int i;
  886. for (i = 0, mpt2sas_phy = NULL; i < ioc->sas_hba.num_phys &&
  887. !mpt2sas_phy; i++) {
  888. if (ioc->sas_hba.phy[i].phy != phy)
  889. continue;
  890. mpt2sas_phy = &ioc->sas_hba.phy[i];
  891. }
  892. if (!mpt2sas_phy) /* this phy not on sas_host */
  893. return -EINVAL;
  894. memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
  895. mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
  896. mpi_request.Operation = hard_reset ?
  897. MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
  898. mpi_request.PhyNum = mpt2sas_phy->phy_id;
  899. if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
  900. printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
  901. ioc->name, __FILE__, __LINE__, __func__);
  902. return -ENXIO;
  903. }
  904. if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
  905. printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
  906. "(0x%04x), loginfo(0x%08x)\n", ioc->name,
  907. mpt2sas_phy->phy_id,
  908. le16_to_cpu(mpi_reply.IOCStatus),
  909. le32_to_cpu(mpi_reply.IOCLogInfo));
  910. return 0;
  911. }
  912. /**
  913. * _transport_smp_handler - transport portal for smp passthru
  914. * @shost: shost object
  915. * @rphy: sas transport rphy object
  916. * @req:
  917. *
  918. * This used primarily for smp_utils.
  919. * Example:
  920. * smp_rep_general /sys/class/bsg/expander-5:0
  921. */
  922. static int
  923. _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
  924. struct request *req)
  925. {
  926. struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
  927. Mpi2SmpPassthroughRequest_t *mpi_request;
  928. Mpi2SmpPassthroughReply_t *mpi_reply;
  929. int rc;
  930. u16 smid;
  931. u32 ioc_state;
  932. unsigned long timeleft;
  933. void *psge;
  934. u32 sgl_flags;
  935. u8 issue_reset = 0;
  936. dma_addr_t dma_addr_in = 0;
  937. dma_addr_t dma_addr_out = 0;
  938. u16 wait_state_count;
  939. struct request *rsp = req->next_rq;
  940. if (!rsp) {
  941. printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
  942. "missing\n", ioc->name, __func__);
  943. return -EINVAL;
  944. }
  945. /* do we need to support multiple segments? */
  946. if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
  947. printk(MPT2SAS_ERR_FMT "%s: multiple segments req %u %u, "
  948. "rsp %u %u\n", ioc->name, __func__, req->bio->bi_vcnt,
  949. blk_rq_bytes(req), rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
  950. return -EINVAL;
  951. }
  952. if (ioc->shost_recovery) {
  953. printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
  954. __func__, ioc->name);
  955. return -EFAULT;
  956. }
  957. rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
  958. if (rc)
  959. return rc;
  960. if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
  961. printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name,
  962. __func__);
  963. rc = -EAGAIN;
  964. goto out;
  965. }
  966. ioc->transport_cmds.status = MPT2_CMD_PENDING;
  967. wait_state_count = 0;
  968. ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
  969. while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
  970. if (wait_state_count++ == 10) {
  971. printk(MPT2SAS_ERR_FMT
  972. "%s: failed due to ioc not operational\n",
  973. ioc->name, __func__);
  974. rc = -EFAULT;
  975. goto out;
  976. }
  977. ssleep(1);
  978. ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
  979. printk(MPT2SAS_INFO_FMT "%s: waiting for "
  980. "operational state(count=%d)\n", ioc->name,
  981. __func__, wait_state_count);
  982. }
  983. if (wait_state_count)
  984. printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
  985. ioc->name, __func__);
  986. smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
  987. if (!smid) {
  988. printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
  989. ioc->name, __func__);
  990. rc = -EAGAIN;
  991. goto out;
  992. }
  993. rc = 0;
  994. mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
  995. ioc->transport_cmds.smid = smid;
  996. memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
  997. mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
  998. mpi_request->PhysicalPort = 0xFF;
  999. mpi_request->VF_ID = 0; /* TODO */
  1000. mpi_request->VP_ID = 0;
  1001. *((u64 *)&mpi_request->SASAddress) = (rphy) ?
  1002. cpu_to_le64(rphy->identify.sas_address) :
  1003. cpu_to_le64(ioc->sas_hba.sas_address);
  1004. mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
  1005. psge = &mpi_request->SGL;
  1006. /* WRITE sgel first */
  1007. sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
  1008. MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
  1009. sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
  1010. dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
  1011. blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
  1012. if (!dma_addr_out) {
  1013. mpt2sas_base_free_smid(ioc, le16_to_cpu(smid));
  1014. goto unmap;
  1015. }
  1016. ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(req) - 4),
  1017. dma_addr_out);
  1018. /* incr sgel */
  1019. psge += ioc->sge_size;
  1020. /* READ sgel last */
  1021. sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
  1022. MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
  1023. MPI2_SGE_FLAGS_END_OF_LIST);
  1024. sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
  1025. dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
  1026. blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
  1027. if (!dma_addr_in) {
  1028. mpt2sas_base_free_smid(ioc, le16_to_cpu(smid));
  1029. goto unmap;
  1030. }
  1031. ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(rsp) + 4),
  1032. dma_addr_in);
  1033. dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
  1034. "sending smp request\n", ioc->name, __func__));
  1035. mpt2sas_base_put_smid_default(ioc, smid);
  1036. init_completion(&ioc->transport_cmds.done);
  1037. timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
  1038. 10*HZ);
  1039. if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
  1040. printk(MPT2SAS_ERR_FMT "%s : timeout\n",
  1041. __func__, ioc->name);
  1042. _debug_dump_mf(mpi_request,
  1043. sizeof(Mpi2SmpPassthroughRequest_t)/4);
  1044. if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
  1045. issue_reset = 1;
  1046. goto issue_host_reset;
  1047. }
  1048. dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
  1049. "complete\n", ioc->name, __func__));
  1050. if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
  1051. mpi_reply = ioc->transport_cmds.reply;
  1052. dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
  1053. "%s - reply data transfer size(%d)\n",
  1054. ioc->name, __func__,
  1055. le16_to_cpu(mpi_reply->ResponseDataLength)));
  1056. memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
  1057. req->sense_len = sizeof(*mpi_reply);
  1058. req->resid_len = 0;
  1059. rsp->resid_len -= mpi_reply->ResponseDataLength;
  1060. } else {
  1061. dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
  1062. "%s - no reply\n", ioc->name, __func__));
  1063. rc = -ENXIO;
  1064. }
  1065. issue_host_reset:
  1066. if (issue_reset) {
  1067. mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
  1068. FORCE_BIG_HAMMER);
  1069. rc = -ETIMEDOUT;
  1070. }
  1071. unmap:
  1072. if (dma_addr_out)
  1073. pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req),
  1074. PCI_DMA_BIDIRECTIONAL);
  1075. if (dma_addr_in)
  1076. pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
  1077. PCI_DMA_BIDIRECTIONAL);
  1078. out:
  1079. ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
  1080. mutex_unlock(&ioc->transport_cmds.mutex);
  1081. return rc;
  1082. }
  1083. struct sas_function_template mpt2sas_transport_functions = {
  1084. .get_linkerrors = _transport_get_linkerrors,
  1085. .get_enclosure_identifier = _transport_get_enclosure_identifier,
  1086. .get_bay_identifier = _transport_get_bay_identifier,
  1087. .phy_reset = _transport_phy_reset,
  1088. .smp_handler = _transport_smp_handler,
  1089. };
  1090. struct scsi_transport_template *mpt2sas_transport_template;