mpi3mr_transport.c 97 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Driver for Broadcom MPI3 Storage Controllers
  4. *
  5. * Copyright (C) 2017-2022 Broadcom Inc.
  6. * (mailto: [email protected])
  7. *
  8. */
  9. #include "mpi3mr.h"
  10. /**
  11. * mpi3mr_post_transport_req - Issue transport requests and wait
  12. * @mrioc: Adapter instance reference
  13. * @request: Properly populated MPI3 request
  14. * @request_sz: Size of the MPI3 request
  15. * @reply: Pointer to return MPI3 reply
  16. * @reply_sz: Size of the MPI3 reply buffer
  17. * @timeout: Timeout in seconds
  18. * @ioc_status: Pointer to return ioc status
  19. *
  20. * A generic function for posting MPI3 requests from the SAS
  21. * transport layer that uses transport command infrastructure.
  22. * This blocks for the completion of request for timeout seconds
  23. * and if the request times out this function faults the
  24. * controller with proper reason code.
  25. *
  26. * On successful completion of the request this function returns
  27. * appropriate ioc status from the firmware back to the caller.
  28. *
  29. * Return: 0 on success, non-zero on failure.
  30. */
  31. static int mpi3mr_post_transport_req(struct mpi3mr_ioc *mrioc, void *request,
  32. u16 request_sz, void *reply, u16 reply_sz, int timeout,
  33. u16 *ioc_status)
  34. {
  35. int retval = 0;
  36. mutex_lock(&mrioc->transport_cmds.mutex);
  37. if (mrioc->transport_cmds.state & MPI3MR_CMD_PENDING) {
  38. retval = -1;
  39. ioc_err(mrioc, "sending transport request failed due to command in use\n");
  40. mutex_unlock(&mrioc->transport_cmds.mutex);
  41. goto out;
  42. }
  43. mrioc->transport_cmds.state = MPI3MR_CMD_PENDING;
  44. mrioc->transport_cmds.is_waiting = 1;
  45. mrioc->transport_cmds.callback = NULL;
  46. mrioc->transport_cmds.ioc_status = 0;
  47. mrioc->transport_cmds.ioc_loginfo = 0;
  48. init_completion(&mrioc->transport_cmds.done);
  49. dprint_cfg_info(mrioc, "posting transport request\n");
  50. if (mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)
  51. dprint_dump(request, request_sz, "transport_req");
  52. retval = mpi3mr_admin_request_post(mrioc, request, request_sz, 1);
  53. if (retval) {
  54. ioc_err(mrioc, "posting transport request failed\n");
  55. goto out_unlock;
  56. }
  57. wait_for_completion_timeout(&mrioc->transport_cmds.done,
  58. (timeout * HZ));
  59. if (!(mrioc->transport_cmds.state & MPI3MR_CMD_COMPLETE)) {
  60. mpi3mr_check_rh_fault_ioc(mrioc,
  61. MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT);
  62. ioc_err(mrioc, "transport request timed out\n");
  63. retval = -1;
  64. goto out_unlock;
  65. }
  66. *ioc_status = mrioc->transport_cmds.ioc_status &
  67. MPI3_IOCSTATUS_STATUS_MASK;
  68. if ((*ioc_status) != MPI3_IOCSTATUS_SUCCESS)
  69. dprint_transport_err(mrioc,
  70. "transport request returned with ioc_status(0x%04x), log_info(0x%08x)\n",
  71. *ioc_status, mrioc->transport_cmds.ioc_loginfo);
  72. if ((reply) && (mrioc->transport_cmds.state & MPI3MR_CMD_REPLY_VALID))
  73. memcpy((u8 *)reply, mrioc->transport_cmds.reply, reply_sz);
  74. out_unlock:
  75. mrioc->transport_cmds.state = MPI3MR_CMD_NOTUSED;
  76. mutex_unlock(&mrioc->transport_cmds.mutex);
  77. out:
  78. return retval;
  79. }
  80. /* report manufacture request structure */
  81. struct rep_manu_request {
  82. u8 smp_frame_type;
  83. u8 function;
  84. u8 reserved;
  85. u8 request_length;
  86. };
  87. /* report manufacture reply structure */
  88. struct rep_manu_reply {
  89. u8 smp_frame_type; /* 0x41 */
  90. u8 function; /* 0x01 */
  91. u8 function_result;
  92. u8 response_length;
  93. u16 expander_change_count;
  94. u8 reserved0[2];
  95. u8 sas_format;
  96. u8 reserved2[3];
  97. u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
  98. u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
  99. u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
  100. u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
  101. u16 component_id;
  102. u8 component_revision_id;
  103. u8 reserved3;
  104. u8 vendor_specific[8];
  105. };
  106. /**
  107. * mpi3mr_report_manufacture - obtain SMP report_manufacture
  108. * @mrioc: Adapter instance reference
  109. * @sas_address: SAS address of the expander device
  110. * @edev: SAS transport layer sas_expander_device object
  111. * @port_id: ID of the HBA port
  112. *
  113. * Fills in the sas_expander_device with manufacturing info.
  114. *
  115. * Return: 0 for success, non-zero for failure.
  116. */
  117. static int mpi3mr_report_manufacture(struct mpi3mr_ioc *mrioc,
  118. u64 sas_address, struct sas_expander_device *edev, u8 port_id)
  119. {
  120. struct mpi3_smp_passthrough_request mpi_request;
  121. struct mpi3_smp_passthrough_reply mpi_reply;
  122. struct rep_manu_reply *manufacture_reply;
  123. struct rep_manu_request *manufacture_request;
  124. int rc = 0;
  125. void *psge;
  126. void *data_out = NULL;
  127. dma_addr_t data_out_dma;
  128. dma_addr_t data_in_dma;
  129. size_t data_in_sz;
  130. size_t data_out_sz;
  131. u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
  132. u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
  133. u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
  134. u16 ioc_status;
  135. u8 *tmp;
  136. if (mrioc->reset_in_progress) {
  137. ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
  138. return -EFAULT;
  139. }
  140. data_out_sz = sizeof(struct rep_manu_request);
  141. data_in_sz = sizeof(struct rep_manu_reply);
  142. data_out = dma_alloc_coherent(&mrioc->pdev->dev,
  143. data_out_sz + data_in_sz, &data_out_dma, GFP_KERNEL);
  144. if (!data_out) {
  145. rc = -ENOMEM;
  146. goto out;
  147. }
  148. data_in_dma = data_out_dma + data_out_sz;
  149. manufacture_reply = data_out + data_out_sz;
  150. manufacture_request = data_out;
  151. manufacture_request->smp_frame_type = 0x40;
  152. manufacture_request->function = 1;
  153. manufacture_request->reserved = 0;
  154. manufacture_request->request_length = 0;
  155. memset(&mpi_request, 0, request_sz);
  156. memset(&mpi_reply, 0, reply_sz);
  157. mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
  158. mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
  159. mpi_request.io_unit_port = (u8) port_id;
  160. mpi_request.sas_address = cpu_to_le64(sas_address);
  161. psge = &mpi_request.request_sge;
  162. mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
  163. psge = &mpi_request.response_sge;
  164. mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
  165. dprint_transport_info(mrioc,
  166. "sending report manufacturer SMP request to sas_address(0x%016llx), port(%d)\n",
  167. (unsigned long long)sas_address, port_id);
  168. rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
  169. &mpi_reply, reply_sz,
  170. MPI3MR_INTADMCMD_TIMEOUT, &ioc_status);
  171. if (rc)
  172. goto out;
  173. dprint_transport_info(mrioc,
  174. "report manufacturer SMP request completed with ioc_status(0x%04x)\n",
  175. ioc_status);
  176. if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
  177. rc = -EINVAL;
  178. goto out;
  179. }
  180. dprint_transport_info(mrioc,
  181. "report manufacturer - reply data transfer size(%d)\n",
  182. le16_to_cpu(mpi_reply.response_data_length));
  183. if (le16_to_cpu(mpi_reply.response_data_length) !=
  184. sizeof(struct rep_manu_reply)) {
  185. rc = -EINVAL;
  186. goto out;
  187. }
  188. strscpy(edev->vendor_id, manufacture_reply->vendor_id,
  189. SAS_EXPANDER_VENDOR_ID_LEN);
  190. strscpy(edev->product_id, manufacture_reply->product_id,
  191. SAS_EXPANDER_PRODUCT_ID_LEN);
  192. strscpy(edev->product_rev, manufacture_reply->product_rev,
  193. SAS_EXPANDER_PRODUCT_REV_LEN);
  194. edev->level = manufacture_reply->sas_format & 1;
  195. if (edev->level) {
  196. strscpy(edev->component_vendor_id,
  197. manufacture_reply->component_vendor_id,
  198. SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
  199. tmp = (u8 *)&manufacture_reply->component_id;
  200. edev->component_id = tmp[0] << 8 | tmp[1];
  201. edev->component_revision_id =
  202. manufacture_reply->component_revision_id;
  203. }
  204. out:
  205. if (data_out)
  206. dma_free_coherent(&mrioc->pdev->dev, data_out_sz + data_in_sz,
  207. data_out, data_out_dma);
  208. return rc;
  209. }
  210. /**
  211. * __mpi3mr_expander_find_by_handle - expander search by handle
  212. * @mrioc: Adapter instance reference
  213. * @handle: Firmware device handle of the expander
  214. *
  215. * Context: The caller should acquire sas_node_lock
  216. *
  217. * This searches for expander device based on handle, then
  218. * returns the sas_node object.
  219. *
  220. * Return: Expander sas_node object reference or NULL
  221. */
  222. struct mpi3mr_sas_node *__mpi3mr_expander_find_by_handle(struct mpi3mr_ioc
  223. *mrioc, u16 handle)
  224. {
  225. struct mpi3mr_sas_node *sas_expander, *r;
  226. r = NULL;
  227. list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
  228. if (sas_expander->handle != handle)
  229. continue;
  230. r = sas_expander;
  231. goto out;
  232. }
  233. out:
  234. return r;
  235. }
  236. /**
  237. * mpi3mr_is_expander_device - if device is an expander
  238. * @device_info: Bitfield providing information about the device
  239. *
  240. * Return: 1 if the device is expander device, else 0.
  241. */
  242. u8 mpi3mr_is_expander_device(u16 device_info)
  243. {
  244. if ((device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) ==
  245. MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER)
  246. return 1;
  247. else
  248. return 0;
  249. }
  250. /**
  251. * mpi3mr_get_sas_address - retrieve sas_address for handle
  252. * @mrioc: Adapter instance reference
  253. * @handle: Firmware device handle
  254. * @sas_address: Address to hold sas address
  255. *
  256. * This function issues device page0 read for a given device
  257. * handle and gets the SAS address and return it back
  258. *
  259. * Return: 0 for success, non-zero for failure
  260. */
  261. static int mpi3mr_get_sas_address(struct mpi3mr_ioc *mrioc, u16 handle,
  262. u64 *sas_address)
  263. {
  264. struct mpi3_device_page0 dev_pg0;
  265. u16 ioc_status;
  266. struct mpi3_device0_sas_sata_format *sasinf;
  267. *sas_address = 0;
  268. if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
  269. sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
  270. handle))) {
  271. ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
  272. return -ENXIO;
  273. }
  274. if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
  275. ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
  276. handle, ioc_status, __FILE__, __LINE__, __func__);
  277. return -ENXIO;
  278. }
  279. if (le16_to_cpu(dev_pg0.flags) &
  280. MPI3_DEVICE0_FLAGS_CONTROLLER_DEV_HANDLE)
  281. *sas_address = mrioc->sas_hba.sas_address;
  282. else if (dev_pg0.device_form == MPI3_DEVICE_DEVFORM_SAS_SATA) {
  283. sasinf = &dev_pg0.device_specific.sas_sata_format;
  284. *sas_address = le64_to_cpu(sasinf->sas_address);
  285. } else {
  286. ioc_err(mrioc, "%s: device_form(%d) is not SAS_SATA\n",
  287. __func__, dev_pg0.device_form);
  288. return -ENXIO;
  289. }
  290. return 0;
  291. }
  292. /**
  293. * __mpi3mr_get_tgtdev_by_addr - target device search
  294. * @mrioc: Adapter instance reference
  295. * @sas_address: SAS address of the device
  296. * @hba_port: HBA port entry
  297. *
  298. * This searches for target device from sas address and hba port
  299. * pointer then return mpi3mr_tgt_dev object.
  300. *
  301. * Return: Valid tget_dev or NULL
  302. */
  303. static struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc,
  304. u64 sas_address, struct mpi3mr_hba_port *hba_port)
  305. {
  306. struct mpi3mr_tgt_dev *tgtdev;
  307. assert_spin_locked(&mrioc->tgtdev_lock);
  308. list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list)
  309. if ((tgtdev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA) &&
  310. (tgtdev->dev_spec.sas_sata_inf.sas_address == sas_address)
  311. && (tgtdev->dev_spec.sas_sata_inf.hba_port == hba_port))
  312. goto found_device;
  313. return NULL;
  314. found_device:
  315. mpi3mr_tgtdev_get(tgtdev);
  316. return tgtdev;
  317. }
  318. /**
  319. * mpi3mr_get_tgtdev_by_addr - target device search
  320. * @mrioc: Adapter instance reference
  321. * @sas_address: SAS address of the device
  322. * @hba_port: HBA port entry
  323. *
  324. * This searches for target device from sas address and hba port
  325. * pointer then return mpi3mr_tgt_dev object.
  326. *
  327. * Context: This function will acquire tgtdev_lock and will
  328. * release before returning the mpi3mr_tgt_dev object.
  329. *
  330. * Return: Valid tget_dev or NULL
  331. */
  332. static struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc,
  333. u64 sas_address, struct mpi3mr_hba_port *hba_port)
  334. {
  335. struct mpi3mr_tgt_dev *tgtdev = NULL;
  336. unsigned long flags;
  337. if (!hba_port)
  338. goto out;
  339. spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
  340. tgtdev = __mpi3mr_get_tgtdev_by_addr(mrioc, sas_address, hba_port);
  341. spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
  342. out:
  343. return tgtdev;
  344. }
  345. /**
  346. * mpi3mr_remove_device_by_sas_address - remove the device
  347. * @mrioc: Adapter instance reference
  348. * @sas_address: SAS address of the device
  349. * @hba_port: HBA port entry
  350. *
  351. * This searches for target device using sas address and hba
  352. * port pointer then removes it from the OS.
  353. *
  354. * Return: None
  355. */
  356. static void mpi3mr_remove_device_by_sas_address(struct mpi3mr_ioc *mrioc,
  357. u64 sas_address, struct mpi3mr_hba_port *hba_port)
  358. {
  359. struct mpi3mr_tgt_dev *tgtdev = NULL;
  360. unsigned long flags;
  361. u8 was_on_tgtdev_list = 0;
  362. if (!hba_port)
  363. return;
  364. spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
  365. tgtdev = __mpi3mr_get_tgtdev_by_addr(mrioc,
  366. sas_address, hba_port);
  367. if (tgtdev) {
  368. if (!list_empty(&tgtdev->list)) {
  369. list_del_init(&tgtdev->list);
  370. was_on_tgtdev_list = 1;
  371. mpi3mr_tgtdev_put(tgtdev);
  372. }
  373. }
  374. spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
  375. if (was_on_tgtdev_list) {
  376. if (tgtdev->host_exposed)
  377. mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev);
  378. mpi3mr_tgtdev_put(tgtdev);
  379. }
  380. }
  381. /**
  382. * __mpi3mr_get_tgtdev_by_addr_and_rphy - target device search
  383. * @mrioc: Adapter instance reference
  384. * @sas_address: SAS address of the device
  385. * @rphy: SAS transport layer rphy object
  386. *
  387. * This searches for target device from sas address and rphy
  388. * pointer then return mpi3mr_tgt_dev object.
  389. *
  390. * Return: Valid tget_dev or NULL
  391. */
  392. struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr_and_rphy(
  393. struct mpi3mr_ioc *mrioc, u64 sas_address, struct sas_rphy *rphy)
  394. {
  395. struct mpi3mr_tgt_dev *tgtdev;
  396. assert_spin_locked(&mrioc->tgtdev_lock);
  397. list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list)
  398. if ((tgtdev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA) &&
  399. (tgtdev->dev_spec.sas_sata_inf.sas_address == sas_address)
  400. && (tgtdev->dev_spec.sas_sata_inf.rphy == rphy))
  401. goto found_device;
  402. return NULL;
  403. found_device:
  404. mpi3mr_tgtdev_get(tgtdev);
  405. return tgtdev;
  406. }
  407. /**
  408. * mpi3mr_expander_find_by_sas_address - sas expander search
  409. * @mrioc: Adapter instance reference
  410. * @sas_address: SAS address of expander
  411. * @hba_port: HBA port entry
  412. *
  413. * Return: A valid SAS expander node or NULL.
  414. *
  415. */
  416. static struct mpi3mr_sas_node *mpi3mr_expander_find_by_sas_address(
  417. struct mpi3mr_ioc *mrioc, u64 sas_address,
  418. struct mpi3mr_hba_port *hba_port)
  419. {
  420. struct mpi3mr_sas_node *sas_expander, *r = NULL;
  421. if (!hba_port)
  422. goto out;
  423. list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
  424. if ((sas_expander->sas_address != sas_address) ||
  425. (sas_expander->hba_port != hba_port))
  426. continue;
  427. r = sas_expander;
  428. goto out;
  429. }
  430. out:
  431. return r;
  432. }
  433. /**
  434. * __mpi3mr_sas_node_find_by_sas_address - sas node search
  435. * @mrioc: Adapter instance reference
  436. * @sas_address: SAS address of expander or sas host
  437. * @hba_port: HBA port entry
  438. * Context: Caller should acquire mrioc->sas_node_lock.
  439. *
  440. * If the SAS address indicates the device is direct attached to
  441. * the controller (controller's SAS address) then the SAS node
  442. * associated with the controller is returned back else the SAS
  443. * address and hba port are used to identify the exact expander
  444. * and the associated sas_node object is returned. If there is
  445. * no match NULL is returned.
  446. *
  447. * Return: A valid SAS node or NULL.
  448. *
  449. */
  450. static struct mpi3mr_sas_node *__mpi3mr_sas_node_find_by_sas_address(
  451. struct mpi3mr_ioc *mrioc, u64 sas_address,
  452. struct mpi3mr_hba_port *hba_port)
  453. {
  454. if (mrioc->sas_hba.sas_address == sas_address)
  455. return &mrioc->sas_hba;
  456. return mpi3mr_expander_find_by_sas_address(mrioc, sas_address,
  457. hba_port);
  458. }
  459. /**
  460. * mpi3mr_parent_present - Is parent present for a phy
  461. * @mrioc: Adapter instance reference
  462. * @phy: SAS transport layer phy object
  463. *
  464. * Return: 0 if parent is present else non-zero
  465. */
  466. static int mpi3mr_parent_present(struct mpi3mr_ioc *mrioc, struct sas_phy *phy)
  467. {
  468. unsigned long flags;
  469. struct mpi3mr_hba_port *hba_port = phy->hostdata;
  470. spin_lock_irqsave(&mrioc->sas_node_lock, flags);
  471. if (__mpi3mr_sas_node_find_by_sas_address(mrioc,
  472. phy->identify.sas_address,
  473. hba_port) == NULL) {
  474. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  475. return -1;
  476. }
  477. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  478. return 0;
  479. }
  480. /**
  481. * mpi3mr_convert_phy_link_rate -
  482. * @link_rate: link rate as defined in the MPI header
  483. *
  484. * Convert link_rate from mpi format into sas_transport layer
  485. * form.
  486. *
  487. * Return: A valid SAS transport layer defined link rate
  488. */
  489. static enum sas_linkrate mpi3mr_convert_phy_link_rate(u8 link_rate)
  490. {
  491. enum sas_linkrate rc;
  492. switch (link_rate) {
  493. case MPI3_SAS_NEG_LINK_RATE_1_5:
  494. rc = SAS_LINK_RATE_1_5_GBPS;
  495. break;
  496. case MPI3_SAS_NEG_LINK_RATE_3_0:
  497. rc = SAS_LINK_RATE_3_0_GBPS;
  498. break;
  499. case MPI3_SAS_NEG_LINK_RATE_6_0:
  500. rc = SAS_LINK_RATE_6_0_GBPS;
  501. break;
  502. case MPI3_SAS_NEG_LINK_RATE_12_0:
  503. rc = SAS_LINK_RATE_12_0_GBPS;
  504. break;
  505. case MPI3_SAS_NEG_LINK_RATE_22_5:
  506. rc = SAS_LINK_RATE_22_5_GBPS;
  507. break;
  508. case MPI3_SAS_NEG_LINK_RATE_PHY_DISABLED:
  509. rc = SAS_PHY_DISABLED;
  510. break;
  511. case MPI3_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
  512. rc = SAS_LINK_RATE_FAILED;
  513. break;
  514. case MPI3_SAS_NEG_LINK_RATE_PORT_SELECTOR:
  515. rc = SAS_SATA_PORT_SELECTOR;
  516. break;
  517. case MPI3_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
  518. rc = SAS_PHY_RESET_IN_PROGRESS;
  519. break;
  520. case MPI3_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
  521. case MPI3_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
  522. default:
  523. rc = SAS_LINK_RATE_UNKNOWN;
  524. break;
  525. }
  526. return rc;
  527. }
  528. /**
  529. * mpi3mr_delete_sas_phy - Remove a single phy from port
  530. * @mrioc: Adapter instance reference
  531. * @mr_sas_port: Internal Port object
  532. * @mr_sas_phy: Internal Phy object
  533. *
  534. * Return: None.
  535. */
  536. static void mpi3mr_delete_sas_phy(struct mpi3mr_ioc *mrioc,
  537. struct mpi3mr_sas_port *mr_sas_port,
  538. struct mpi3mr_sas_phy *mr_sas_phy)
  539. {
  540. u64 sas_address = mr_sas_port->remote_identify.sas_address;
  541. dev_info(&mr_sas_phy->phy->dev,
  542. "remove: sas_address(0x%016llx), phy(%d)\n",
  543. (unsigned long long) sas_address, mr_sas_phy->phy_id);
  544. list_del(&mr_sas_phy->port_siblings);
  545. mr_sas_port->num_phys--;
  546. mr_sas_port->phy_mask &= ~(1 << mr_sas_phy->phy_id);
  547. if (mr_sas_port->lowest_phy == mr_sas_phy->phy_id)
  548. mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
  549. sas_port_delete_phy(mr_sas_port->port, mr_sas_phy->phy);
  550. mr_sas_phy->phy_belongs_to_port = 0;
  551. }
  552. /**
  553. * mpi3mr_add_sas_phy - Adding a single phy to a port
  554. * @mrioc: Adapter instance reference
  555. * @mr_sas_port: Internal Port object
  556. * @mr_sas_phy: Internal Phy object
  557. *
  558. * Return: None.
  559. */
  560. static void mpi3mr_add_sas_phy(struct mpi3mr_ioc *mrioc,
  561. struct mpi3mr_sas_port *mr_sas_port,
  562. struct mpi3mr_sas_phy *mr_sas_phy)
  563. {
  564. u64 sas_address = mr_sas_port->remote_identify.sas_address;
  565. dev_info(&mr_sas_phy->phy->dev,
  566. "add: sas_address(0x%016llx), phy(%d)\n", (unsigned long long)
  567. sas_address, mr_sas_phy->phy_id);
  568. list_add_tail(&mr_sas_phy->port_siblings, &mr_sas_port->phy_list);
  569. mr_sas_port->num_phys++;
  570. mr_sas_port->phy_mask |= (1 << mr_sas_phy->phy_id);
  571. if (mr_sas_phy->phy_id < mr_sas_port->lowest_phy)
  572. mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
  573. sas_port_add_phy(mr_sas_port->port, mr_sas_phy->phy);
  574. mr_sas_phy->phy_belongs_to_port = 1;
  575. }
  576. /**
  577. * mpi3mr_add_phy_to_an_existing_port - add phy to existing port
  578. * @mrioc: Adapter instance reference
  579. * @mr_sas_node: Internal sas node object (expander or host)
  580. * @mr_sas_phy: Internal Phy object *
  581. * @sas_address: SAS address of device/expander were phy needs
  582. * to be added to
  583. * @hba_port: HBA port entry
  584. *
  585. * Return: None.
  586. */
  587. static void mpi3mr_add_phy_to_an_existing_port(struct mpi3mr_ioc *mrioc,
  588. struct mpi3mr_sas_node *mr_sas_node, struct mpi3mr_sas_phy *mr_sas_phy,
  589. u64 sas_address, struct mpi3mr_hba_port *hba_port)
  590. {
  591. struct mpi3mr_sas_port *mr_sas_port;
  592. struct mpi3mr_sas_phy *srch_phy;
  593. if (mr_sas_phy->phy_belongs_to_port == 1)
  594. return;
  595. if (!hba_port)
  596. return;
  597. list_for_each_entry(mr_sas_port, &mr_sas_node->sas_port_list,
  598. port_list) {
  599. if (mr_sas_port->remote_identify.sas_address !=
  600. sas_address)
  601. continue;
  602. if (mr_sas_port->hba_port != hba_port)
  603. continue;
  604. list_for_each_entry(srch_phy, &mr_sas_port->phy_list,
  605. port_siblings) {
  606. if (srch_phy == mr_sas_phy)
  607. return;
  608. }
  609. mpi3mr_add_sas_phy(mrioc, mr_sas_port, mr_sas_phy);
  610. return;
  611. }
  612. }
  613. /**
  614. * mpi3mr_delete_sas_port - helper function to removing a port
  615. * @mrioc: Adapter instance reference
  616. * @mr_sas_port: Internal Port object
  617. *
  618. * Return: None.
  619. */
  620. static void mpi3mr_delete_sas_port(struct mpi3mr_ioc *mrioc,
  621. struct mpi3mr_sas_port *mr_sas_port)
  622. {
  623. u64 sas_address = mr_sas_port->remote_identify.sas_address;
  624. struct mpi3mr_hba_port *hba_port = mr_sas_port->hba_port;
  625. enum sas_device_type device_type =
  626. mr_sas_port->remote_identify.device_type;
  627. dev_info(&mr_sas_port->port->dev,
  628. "remove: sas_address(0x%016llx)\n",
  629. (unsigned long long) sas_address);
  630. if (device_type == SAS_END_DEVICE)
  631. mpi3mr_remove_device_by_sas_address(mrioc, sas_address,
  632. hba_port);
  633. else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
  634. device_type == SAS_FANOUT_EXPANDER_DEVICE)
  635. mpi3mr_expander_remove(mrioc, sas_address, hba_port);
  636. }
  637. /**
  638. * mpi3mr_del_phy_from_an_existing_port - del phy from a port
  639. * @mrioc: Adapter instance reference
  640. * @mr_sas_node: Internal sas node object (expander or host)
  641. * @mr_sas_phy: Internal Phy object
  642. *
  643. * Return: None.
  644. */
  645. static void mpi3mr_del_phy_from_an_existing_port(struct mpi3mr_ioc *mrioc,
  646. struct mpi3mr_sas_node *mr_sas_node, struct mpi3mr_sas_phy *mr_sas_phy)
  647. {
  648. struct mpi3mr_sas_port *mr_sas_port, *next;
  649. struct mpi3mr_sas_phy *srch_phy;
  650. if (mr_sas_phy->phy_belongs_to_port == 0)
  651. return;
  652. list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list,
  653. port_list) {
  654. list_for_each_entry(srch_phy, &mr_sas_port->phy_list,
  655. port_siblings) {
  656. if (srch_phy != mr_sas_phy)
  657. continue;
  658. if ((mr_sas_port->num_phys == 1) &&
  659. !mrioc->reset_in_progress)
  660. mpi3mr_delete_sas_port(mrioc, mr_sas_port);
  661. else
  662. mpi3mr_delete_sas_phy(mrioc, mr_sas_port,
  663. mr_sas_phy);
  664. return;
  665. }
  666. }
  667. }
  668. /**
  669. * mpi3mr_sas_port_sanity_check - sanity check while adding port
  670. * @mrioc: Adapter instance reference
  671. * @mr_sas_node: Internal sas node object (expander or host)
  672. * @sas_address: SAS address of device/expander
  673. * @hba_port: HBA port entry
  674. *
  675. * Verifies whether the Phys attached to a device with the given
  676. * SAS address already belongs to an existing sas port if so
  677. * will remove those phys from the sas port
  678. *
  679. * Return: None.
  680. */
  681. static void mpi3mr_sas_port_sanity_check(struct mpi3mr_ioc *mrioc,
  682. struct mpi3mr_sas_node *mr_sas_node, u64 sas_address,
  683. struct mpi3mr_hba_port *hba_port)
  684. {
  685. int i;
  686. for (i = 0; i < mr_sas_node->num_phys; i++) {
  687. if ((mr_sas_node->phy[i].remote_identify.sas_address !=
  688. sas_address) || (mr_sas_node->phy[i].hba_port != hba_port))
  689. continue;
  690. if (mr_sas_node->phy[i].phy_belongs_to_port == 1)
  691. mpi3mr_del_phy_from_an_existing_port(mrioc,
  692. mr_sas_node, &mr_sas_node->phy[i]);
  693. }
  694. }
  695. /**
  696. * mpi3mr_set_identify - set identify for phys and end devices
  697. * @mrioc: Adapter instance reference
  698. * @handle: Firmware device handle
  699. * @identify: SAS transport layer's identify info
  700. *
  701. * Populates sas identify info for a specific device.
  702. *
  703. * Return: 0 for success, non-zero for failure.
  704. */
  705. static int mpi3mr_set_identify(struct mpi3mr_ioc *mrioc, u16 handle,
  706. struct sas_identify *identify)
  707. {
  708. struct mpi3_device_page0 device_pg0;
  709. struct mpi3_device0_sas_sata_format *sasinf;
  710. u16 device_info;
  711. u16 ioc_status;
  712. if (mrioc->reset_in_progress) {
  713. ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
  714. return -EFAULT;
  715. }
  716. if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &device_pg0,
  717. sizeof(device_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, handle))) {
  718. ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
  719. return -ENXIO;
  720. }
  721. if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
  722. ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
  723. handle, ioc_status, __FILE__, __LINE__, __func__);
  724. return -EIO;
  725. }
  726. memset(identify, 0, sizeof(struct sas_identify));
  727. sasinf = &device_pg0.device_specific.sas_sata_format;
  728. device_info = le16_to_cpu(sasinf->device_info);
  729. /* sas_address */
  730. identify->sas_address = le64_to_cpu(sasinf->sas_address);
  731. /* phy number of the parent device this device is linked to */
  732. identify->phy_identifier = sasinf->phy_num;
  733. /* device_type */
  734. switch (device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) {
  735. case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_NO_DEVICE:
  736. identify->device_type = SAS_PHY_UNUSED;
  737. break;
  738. case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE:
  739. identify->device_type = SAS_END_DEVICE;
  740. break;
  741. case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER:
  742. identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
  743. break;
  744. }
  745. /* initiator_port_protocols */
  746. if (device_info & MPI3_SAS_DEVICE_INFO_SSP_INITIATOR)
  747. identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
  748. /* MPI3.0 doesn't have define for SATA INIT so setting both here*/
  749. if (device_info & MPI3_SAS_DEVICE_INFO_STP_INITIATOR)
  750. identify->initiator_port_protocols |= (SAS_PROTOCOL_STP |
  751. SAS_PROTOCOL_SATA);
  752. if (device_info & MPI3_SAS_DEVICE_INFO_SMP_INITIATOR)
  753. identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
  754. /* target_port_protocols */
  755. if (device_info & MPI3_SAS_DEVICE_INFO_SSP_TARGET)
  756. identify->target_port_protocols |= SAS_PROTOCOL_SSP;
  757. /* MPI3.0 doesn't have define for STP Target so setting both here*/
  758. if (device_info & MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET)
  759. identify->target_port_protocols |= (SAS_PROTOCOL_STP |
  760. SAS_PROTOCOL_SATA);
  761. if (device_info & MPI3_SAS_DEVICE_INFO_SMP_TARGET)
  762. identify->target_port_protocols |= SAS_PROTOCOL_SMP;
  763. return 0;
  764. }
  765. /**
  766. * mpi3mr_add_host_phy - report sas_host phy to SAS transport
  767. * @mrioc: Adapter instance reference
  768. * @mr_sas_phy: Internal Phy object
  769. * @phy_pg0: SAS phy page 0
  770. * @parent_dev: Prent device class object
  771. *
  772. * Return: 0 for success, non-zero for failure.
  773. */
  774. static int mpi3mr_add_host_phy(struct mpi3mr_ioc *mrioc,
  775. struct mpi3mr_sas_phy *mr_sas_phy, struct mpi3_sas_phy_page0 phy_pg0,
  776. struct device *parent_dev)
  777. {
  778. struct sas_phy *phy;
  779. int phy_index = mr_sas_phy->phy_id;
  780. INIT_LIST_HEAD(&mr_sas_phy->port_siblings);
  781. phy = sas_phy_alloc(parent_dev, phy_index);
  782. if (!phy) {
  783. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  784. __FILE__, __LINE__, __func__);
  785. return -1;
  786. }
  787. if ((mpi3mr_set_identify(mrioc, mr_sas_phy->handle,
  788. &mr_sas_phy->identify))) {
  789. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  790. __FILE__, __LINE__, __func__);
  791. sas_phy_free(phy);
  792. return -1;
  793. }
  794. phy->identify = mr_sas_phy->identify;
  795. mr_sas_phy->attached_handle = le16_to_cpu(phy_pg0.attached_dev_handle);
  796. if (mr_sas_phy->attached_handle)
  797. mpi3mr_set_identify(mrioc, mr_sas_phy->attached_handle,
  798. &mr_sas_phy->remote_identify);
  799. phy->identify.phy_identifier = mr_sas_phy->phy_id;
  800. phy->negotiated_linkrate = mpi3mr_convert_phy_link_rate(
  801. (phy_pg0.negotiated_link_rate &
  802. MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
  803. MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
  804. phy->minimum_linkrate_hw = mpi3mr_convert_phy_link_rate(
  805. phy_pg0.hw_link_rate & MPI3_SAS_HWRATE_MIN_RATE_MASK);
  806. phy->maximum_linkrate_hw = mpi3mr_convert_phy_link_rate(
  807. phy_pg0.hw_link_rate >> 4);
  808. phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
  809. phy_pg0.programmed_link_rate & MPI3_SAS_PRATE_MIN_RATE_MASK);
  810. phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
  811. phy_pg0.programmed_link_rate >> 4);
  812. phy->hostdata = mr_sas_phy->hba_port;
  813. if ((sas_phy_add(phy))) {
  814. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  815. __FILE__, __LINE__, __func__);
  816. sas_phy_free(phy);
  817. return -1;
  818. }
  819. if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
  820. dev_info(&phy->dev,
  821. "add: handle(0x%04x), sas_address(0x%016llx)\n"
  822. "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
  823. mr_sas_phy->handle, (unsigned long long)
  824. mr_sas_phy->identify.sas_address,
  825. mr_sas_phy->attached_handle,
  826. (unsigned long long)
  827. mr_sas_phy->remote_identify.sas_address);
  828. mr_sas_phy->phy = phy;
  829. return 0;
  830. }
  831. /**
  832. * mpi3mr_add_expander_phy - report expander phy to transport
  833. * @mrioc: Adapter instance reference
  834. * @mr_sas_phy: Internal Phy object
  835. * @expander_pg1: SAS Expander page 1
  836. * @parent_dev: Parent device class object
  837. *
  838. * Return: 0 for success, non-zero for failure.
  839. */
  840. static int mpi3mr_add_expander_phy(struct mpi3mr_ioc *mrioc,
  841. struct mpi3mr_sas_phy *mr_sas_phy,
  842. struct mpi3_sas_expander_page1 expander_pg1,
  843. struct device *parent_dev)
  844. {
  845. struct sas_phy *phy;
  846. int phy_index = mr_sas_phy->phy_id;
  847. INIT_LIST_HEAD(&mr_sas_phy->port_siblings);
  848. phy = sas_phy_alloc(parent_dev, phy_index);
  849. if (!phy) {
  850. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  851. __FILE__, __LINE__, __func__);
  852. return -1;
  853. }
  854. if ((mpi3mr_set_identify(mrioc, mr_sas_phy->handle,
  855. &mr_sas_phy->identify))) {
  856. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  857. __FILE__, __LINE__, __func__);
  858. sas_phy_free(phy);
  859. return -1;
  860. }
  861. phy->identify = mr_sas_phy->identify;
  862. mr_sas_phy->attached_handle =
  863. le16_to_cpu(expander_pg1.attached_dev_handle);
  864. if (mr_sas_phy->attached_handle)
  865. mpi3mr_set_identify(mrioc, mr_sas_phy->attached_handle,
  866. &mr_sas_phy->remote_identify);
  867. phy->identify.phy_identifier = mr_sas_phy->phy_id;
  868. phy->negotiated_linkrate = mpi3mr_convert_phy_link_rate(
  869. (expander_pg1.negotiated_link_rate &
  870. MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
  871. MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
  872. phy->minimum_linkrate_hw = mpi3mr_convert_phy_link_rate(
  873. expander_pg1.hw_link_rate & MPI3_SAS_HWRATE_MIN_RATE_MASK);
  874. phy->maximum_linkrate_hw = mpi3mr_convert_phy_link_rate(
  875. expander_pg1.hw_link_rate >> 4);
  876. phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
  877. expander_pg1.programmed_link_rate & MPI3_SAS_PRATE_MIN_RATE_MASK);
  878. phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
  879. expander_pg1.programmed_link_rate >> 4);
  880. phy->hostdata = mr_sas_phy->hba_port;
  881. if ((sas_phy_add(phy))) {
  882. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  883. __FILE__, __LINE__, __func__);
  884. sas_phy_free(phy);
  885. return -1;
  886. }
  887. if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
  888. dev_info(&phy->dev,
  889. "add: handle(0x%04x), sas_address(0x%016llx)\n"
  890. "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
  891. mr_sas_phy->handle, (unsigned long long)
  892. mr_sas_phy->identify.sas_address,
  893. mr_sas_phy->attached_handle,
  894. (unsigned long long)
  895. mr_sas_phy->remote_identify.sas_address);
  896. mr_sas_phy->phy = phy;
  897. return 0;
  898. }
  899. /**
  900. * mpi3mr_alloc_hba_port - alloc hba port object
  901. * @mrioc: Adapter instance reference
  902. * @port_id: Port number
  903. *
  904. * Alloc memory for hba port object.
  905. */
  906. static struct mpi3mr_hba_port *
  907. mpi3mr_alloc_hba_port(struct mpi3mr_ioc *mrioc, u16 port_id)
  908. {
  909. struct mpi3mr_hba_port *hba_port;
  910. hba_port = kzalloc(sizeof(struct mpi3mr_hba_port),
  911. GFP_KERNEL);
  912. if (!hba_port)
  913. return NULL;
  914. hba_port->port_id = port_id;
  915. ioc_info(mrioc, "hba_port entry: %p, port: %d is added to hba_port list\n",
  916. hba_port, hba_port->port_id);
  917. list_add_tail(&hba_port->list, &mrioc->hba_port_table_list);
  918. return hba_port;
  919. }
  920. /**
  921. * mpi3mr_get_hba_port_by_id - find hba port by id
  922. * @mrioc: Adapter instance reference
  923. * @port_id - Port ID to search
  924. *
  925. * Return: mpi3mr_hba_port reference for the matched port
  926. */
  927. struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc,
  928. u8 port_id)
  929. {
  930. struct mpi3mr_hba_port *port, *port_next;
  931. list_for_each_entry_safe(port, port_next,
  932. &mrioc->hba_port_table_list, list) {
  933. if (port->port_id != port_id)
  934. continue;
  935. if (port->flags & MPI3MR_HBA_PORT_FLAG_DIRTY)
  936. continue;
  937. return port;
  938. }
  939. return NULL;
  940. }
  941. /**
  942. * mpi3mr_update_links - refreshing SAS phy link changes
  943. * @mrioc: Adapter instance reference
  944. * @sas_address_parent: SAS address of parent expander or host
  945. * @handle: Firmware device handle of attached device
  946. * @phy_number: Phy number
  947. * @link_rate: New link rate
  948. * @hba_port: HBA port entry
  949. *
  950. * Return: None.
  951. */
  952. void mpi3mr_update_links(struct mpi3mr_ioc *mrioc,
  953. u64 sas_address_parent, u16 handle, u8 phy_number, u8 link_rate,
  954. struct mpi3mr_hba_port *hba_port)
  955. {
  956. unsigned long flags;
  957. struct mpi3mr_sas_node *mr_sas_node;
  958. struct mpi3mr_sas_phy *mr_sas_phy;
  959. if (mrioc->reset_in_progress)
  960. return;
  961. spin_lock_irqsave(&mrioc->sas_node_lock, flags);
  962. mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
  963. sas_address_parent, hba_port);
  964. if (!mr_sas_node) {
  965. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  966. return;
  967. }
  968. mr_sas_phy = &mr_sas_node->phy[phy_number];
  969. mr_sas_phy->attached_handle = handle;
  970. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  971. if (handle && (link_rate >= MPI3_SAS_NEG_LINK_RATE_1_5)) {
  972. mpi3mr_set_identify(mrioc, handle,
  973. &mr_sas_phy->remote_identify);
  974. mpi3mr_add_phy_to_an_existing_port(mrioc, mr_sas_node,
  975. mr_sas_phy, mr_sas_phy->remote_identify.sas_address,
  976. hba_port);
  977. } else
  978. memset(&mr_sas_phy->remote_identify, 0, sizeof(struct
  979. sas_identify));
  980. if (mr_sas_phy->phy)
  981. mr_sas_phy->phy->negotiated_linkrate =
  982. mpi3mr_convert_phy_link_rate(link_rate);
  983. if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
  984. dev_info(&mr_sas_phy->phy->dev,
  985. "refresh: parent sas_address(0x%016llx),\n"
  986. "\tlink_rate(0x%02x), phy(%d)\n"
  987. "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
  988. (unsigned long long)sas_address_parent,
  989. link_rate, phy_number, handle, (unsigned long long)
  990. mr_sas_phy->remote_identify.sas_address);
  991. }
  992. /**
  993. * mpi3mr_sas_host_refresh - refreshing sas host object contents
  994. * @mrioc: Adapter instance reference
  995. *
  996. * This function refreshes the controllers phy information and
  997. * updates the SAS transport layer with updated information,
  998. * this is executed for each device addition or device info
  999. * change events
  1000. *
  1001. * Return: None.
  1002. */
  1003. void mpi3mr_sas_host_refresh(struct mpi3mr_ioc *mrioc)
  1004. {
  1005. int i;
  1006. u8 link_rate;
  1007. u16 sz, port_id, attached_handle;
  1008. struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
  1009. dprint_transport_info(mrioc,
  1010. "updating handles for sas_host(0x%016llx)\n",
  1011. (unsigned long long)mrioc->sas_hba.sas_address);
  1012. sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
  1013. (mrioc->sas_hba.num_phys *
  1014. sizeof(struct mpi3_sas_io_unit0_phy_data));
  1015. sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
  1016. if (!sas_io_unit_pg0)
  1017. return;
  1018. if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
  1019. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1020. __FILE__, __LINE__, __func__);
  1021. goto out;
  1022. }
  1023. mrioc->sas_hba.handle = 0;
  1024. for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
  1025. if (sas_io_unit_pg0->phy_data[i].phy_flags &
  1026. (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
  1027. MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))
  1028. continue;
  1029. link_rate =
  1030. sas_io_unit_pg0->phy_data[i].negotiated_link_rate >> 4;
  1031. if (!mrioc->sas_hba.handle)
  1032. mrioc->sas_hba.handle = le16_to_cpu(
  1033. sas_io_unit_pg0->phy_data[i].controller_dev_handle);
  1034. port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
  1035. if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id)))
  1036. if (!mpi3mr_alloc_hba_port(mrioc, port_id))
  1037. goto out;
  1038. mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle;
  1039. attached_handle = le16_to_cpu(
  1040. sas_io_unit_pg0->phy_data[i].attached_dev_handle);
  1041. if (attached_handle && link_rate < MPI3_SAS_NEG_LINK_RATE_1_5)
  1042. link_rate = MPI3_SAS_NEG_LINK_RATE_1_5;
  1043. mrioc->sas_hba.phy[i].hba_port =
  1044. mpi3mr_get_hba_port_by_id(mrioc, port_id);
  1045. mpi3mr_update_links(mrioc, mrioc->sas_hba.sas_address,
  1046. attached_handle, i, link_rate,
  1047. mrioc->sas_hba.phy[i].hba_port);
  1048. }
  1049. out:
  1050. kfree(sas_io_unit_pg0);
  1051. }
  1052. /**
  1053. * mpi3mr_sas_host_add - create sas host object
  1054. * @mrioc: Adapter instance reference
  1055. *
  1056. * This function creates the controllers phy information and
  1057. * updates the SAS transport layer with updated information,
  1058. * this is executed for first device addition or device info
  1059. * change event.
  1060. *
  1061. * Return: None.
  1062. */
  1063. void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc)
  1064. {
  1065. int i;
  1066. u16 sz, num_phys = 1, port_id, ioc_status;
  1067. struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
  1068. struct mpi3_sas_phy_page0 phy_pg0;
  1069. struct mpi3_device_page0 dev_pg0;
  1070. struct mpi3_enclosure_page0 encl_pg0;
  1071. struct mpi3_device0_sas_sata_format *sasinf;
  1072. sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
  1073. (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data));
  1074. sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
  1075. if (!sas_io_unit_pg0)
  1076. return;
  1077. if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
  1078. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1079. __FILE__, __LINE__, __func__);
  1080. goto out;
  1081. }
  1082. num_phys = sas_io_unit_pg0->num_phys;
  1083. kfree(sas_io_unit_pg0);
  1084. mrioc->sas_hba.host_node = 1;
  1085. INIT_LIST_HEAD(&mrioc->sas_hba.sas_port_list);
  1086. mrioc->sas_hba.parent_dev = &mrioc->shost->shost_gendev;
  1087. mrioc->sas_hba.phy = kcalloc(num_phys,
  1088. sizeof(struct mpi3mr_sas_phy), GFP_KERNEL);
  1089. if (!mrioc->sas_hba.phy)
  1090. return;
  1091. mrioc->sas_hba.num_phys = num_phys;
  1092. sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
  1093. (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data));
  1094. sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
  1095. if (!sas_io_unit_pg0)
  1096. return;
  1097. if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
  1098. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1099. __FILE__, __LINE__, __func__);
  1100. goto out;
  1101. }
  1102. mrioc->sas_hba.handle = 0;
  1103. for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
  1104. if (sas_io_unit_pg0->phy_data[i].phy_flags &
  1105. (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
  1106. MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))
  1107. continue;
  1108. if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
  1109. sizeof(struct mpi3_sas_phy_page0),
  1110. MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, i)) {
  1111. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1112. __FILE__, __LINE__, __func__);
  1113. goto out;
  1114. }
  1115. if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
  1116. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1117. __FILE__, __LINE__, __func__);
  1118. goto out;
  1119. }
  1120. if (!mrioc->sas_hba.handle)
  1121. mrioc->sas_hba.handle = le16_to_cpu(
  1122. sas_io_unit_pg0->phy_data[i].controller_dev_handle);
  1123. port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
  1124. if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id)))
  1125. if (!mpi3mr_alloc_hba_port(mrioc, port_id))
  1126. goto out;
  1127. mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle;
  1128. mrioc->sas_hba.phy[i].phy_id = i;
  1129. mrioc->sas_hba.phy[i].hba_port =
  1130. mpi3mr_get_hba_port_by_id(mrioc, port_id);
  1131. mpi3mr_add_host_phy(mrioc, &mrioc->sas_hba.phy[i],
  1132. phy_pg0, mrioc->sas_hba.parent_dev);
  1133. }
  1134. if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
  1135. sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
  1136. mrioc->sas_hba.handle))) {
  1137. ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
  1138. goto out;
  1139. }
  1140. if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
  1141. ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
  1142. mrioc->sas_hba.handle, ioc_status, __FILE__, __LINE__,
  1143. __func__);
  1144. goto out;
  1145. }
  1146. mrioc->sas_hba.enclosure_handle =
  1147. le16_to_cpu(dev_pg0.enclosure_handle);
  1148. sasinf = &dev_pg0.device_specific.sas_sata_format;
  1149. mrioc->sas_hba.sas_address =
  1150. le64_to_cpu(sasinf->sas_address);
  1151. ioc_info(mrioc,
  1152. "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
  1153. mrioc->sas_hba.handle,
  1154. (unsigned long long) mrioc->sas_hba.sas_address,
  1155. mrioc->sas_hba.num_phys);
  1156. if (mrioc->sas_hba.enclosure_handle) {
  1157. if (!(mpi3mr_cfg_get_enclosure_pg0(mrioc, &ioc_status,
  1158. &encl_pg0, sizeof(encl_pg0),
  1159. MPI3_ENCLOS_PGAD_FORM_HANDLE,
  1160. mrioc->sas_hba.enclosure_handle)) &&
  1161. (ioc_status == MPI3_IOCSTATUS_SUCCESS))
  1162. mrioc->sas_hba.enclosure_logical_id =
  1163. le64_to_cpu(encl_pg0.enclosure_logical_id);
  1164. }
  1165. out:
  1166. kfree(sas_io_unit_pg0);
  1167. }
  1168. /**
  1169. * mpi3mr_sas_port_add - Expose the SAS device to the SAS TL
  1170. * @mrioc: Adapter instance reference
  1171. * @handle: Firmware device handle of the attached device
  1172. * @sas_address_parent: sas address of parent expander or host
  1173. * @hba_port: HBA port entry
  1174. *
  1175. * This function creates a new sas port object for the given end
  1176. * device matching sas address and hba_port and adds it to the
  1177. * sas_node's sas_port_list and expose the attached sas device
  1178. * to the SAS transport layer through sas_rphy_add.
  1179. *
  1180. * Returns a valid mpi3mr_sas_port reference or NULL.
  1181. */
  1182. static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
  1183. u16 handle, u64 sas_address_parent, struct mpi3mr_hba_port *hba_port)
  1184. {
  1185. struct mpi3mr_sas_phy *mr_sas_phy, *next;
  1186. struct mpi3mr_sas_port *mr_sas_port;
  1187. unsigned long flags;
  1188. struct mpi3mr_sas_node *mr_sas_node;
  1189. struct sas_rphy *rphy;
  1190. struct mpi3mr_tgt_dev *tgtdev = NULL;
  1191. int i;
  1192. struct sas_port *port;
  1193. if (!hba_port) {
  1194. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1195. __FILE__, __LINE__, __func__);
  1196. return NULL;
  1197. }
  1198. mr_sas_port = kzalloc(sizeof(struct mpi3mr_sas_port), GFP_KERNEL);
  1199. if (!mr_sas_port)
  1200. return NULL;
  1201. INIT_LIST_HEAD(&mr_sas_port->port_list);
  1202. INIT_LIST_HEAD(&mr_sas_port->phy_list);
  1203. spin_lock_irqsave(&mrioc->sas_node_lock, flags);
  1204. mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
  1205. sas_address_parent, hba_port);
  1206. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  1207. if (!mr_sas_node) {
  1208. ioc_err(mrioc, "%s:could not find parent sas_address(0x%016llx)!\n",
  1209. __func__, (unsigned long long)sas_address_parent);
  1210. goto out_fail;
  1211. }
  1212. if ((mpi3mr_set_identify(mrioc, handle,
  1213. &mr_sas_port->remote_identify))) {
  1214. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1215. __FILE__, __LINE__, __func__);
  1216. goto out_fail;
  1217. }
  1218. if (mr_sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
  1219. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1220. __FILE__, __LINE__, __func__);
  1221. goto out_fail;
  1222. }
  1223. mr_sas_port->hba_port = hba_port;
  1224. mpi3mr_sas_port_sanity_check(mrioc, mr_sas_node,
  1225. mr_sas_port->remote_identify.sas_address, hba_port);
  1226. for (i = 0; i < mr_sas_node->num_phys; i++) {
  1227. if ((mr_sas_node->phy[i].remote_identify.sas_address !=
  1228. mr_sas_port->remote_identify.sas_address) ||
  1229. (mr_sas_node->phy[i].hba_port != hba_port))
  1230. continue;
  1231. list_add_tail(&mr_sas_node->phy[i].port_siblings,
  1232. &mr_sas_port->phy_list);
  1233. mr_sas_port->num_phys++;
  1234. mr_sas_port->phy_mask |= (1 << i);
  1235. }
  1236. if (!mr_sas_port->num_phys) {
  1237. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1238. __FILE__, __LINE__, __func__);
  1239. goto out_fail;
  1240. }
  1241. mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
  1242. if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
  1243. tgtdev = mpi3mr_get_tgtdev_by_addr(mrioc,
  1244. mr_sas_port->remote_identify.sas_address,
  1245. mr_sas_port->hba_port);
  1246. if (!tgtdev) {
  1247. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1248. __FILE__, __LINE__, __func__);
  1249. goto out_fail;
  1250. }
  1251. tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 1;
  1252. }
  1253. if (!mr_sas_node->parent_dev) {
  1254. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1255. __FILE__, __LINE__, __func__);
  1256. goto out_fail;
  1257. }
  1258. port = sas_port_alloc_num(mr_sas_node->parent_dev);
  1259. if ((sas_port_add(port))) {
  1260. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1261. __FILE__, __LINE__, __func__);
  1262. goto out_fail;
  1263. }
  1264. list_for_each_entry(mr_sas_phy, &mr_sas_port->phy_list,
  1265. port_siblings) {
  1266. if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
  1267. dev_info(&port->dev,
  1268. "add: handle(0x%04x), sas_address(0x%016llx), phy(%d)\n",
  1269. handle, (unsigned long long)
  1270. mr_sas_port->remote_identify.sas_address,
  1271. mr_sas_phy->phy_id);
  1272. sas_port_add_phy(port, mr_sas_phy->phy);
  1273. mr_sas_phy->phy_belongs_to_port = 1;
  1274. mr_sas_phy->hba_port = hba_port;
  1275. }
  1276. mr_sas_port->port = port;
  1277. if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
  1278. rphy = sas_end_device_alloc(port);
  1279. tgtdev->dev_spec.sas_sata_inf.rphy = rphy;
  1280. } else {
  1281. rphy = sas_expander_alloc(port,
  1282. mr_sas_port->remote_identify.device_type);
  1283. }
  1284. rphy->identify = mr_sas_port->remote_identify;
  1285. if (mrioc->current_event)
  1286. mrioc->current_event->pending_at_sml = 1;
  1287. if ((sas_rphy_add(rphy))) {
  1288. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1289. __FILE__, __LINE__, __func__);
  1290. }
  1291. if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
  1292. tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 0;
  1293. tgtdev->dev_spec.sas_sata_inf.sas_transport_attached = 1;
  1294. mpi3mr_tgtdev_put(tgtdev);
  1295. }
  1296. dev_info(&rphy->dev,
  1297. "%s: added: handle(0x%04x), sas_address(0x%016llx)\n",
  1298. __func__, handle, (unsigned long long)
  1299. mr_sas_port->remote_identify.sas_address);
  1300. mr_sas_port->rphy = rphy;
  1301. spin_lock_irqsave(&mrioc->sas_node_lock, flags);
  1302. list_add_tail(&mr_sas_port->port_list, &mr_sas_node->sas_port_list);
  1303. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  1304. if (mrioc->current_event) {
  1305. mrioc->current_event->pending_at_sml = 0;
  1306. if (mrioc->current_event->discard)
  1307. mpi3mr_print_device_event_notice(mrioc, true);
  1308. }
  1309. /* fill in report manufacture */
  1310. if (mr_sas_port->remote_identify.device_type ==
  1311. SAS_EDGE_EXPANDER_DEVICE ||
  1312. mr_sas_port->remote_identify.device_type ==
  1313. SAS_FANOUT_EXPANDER_DEVICE)
  1314. mpi3mr_report_manufacture(mrioc,
  1315. mr_sas_port->remote_identify.sas_address,
  1316. rphy_to_expander_device(rphy), hba_port->port_id);
  1317. return mr_sas_port;
  1318. out_fail:
  1319. list_for_each_entry_safe(mr_sas_phy, next, &mr_sas_port->phy_list,
  1320. port_siblings)
  1321. list_del(&mr_sas_phy->port_siblings);
  1322. kfree(mr_sas_port);
  1323. return NULL;
  1324. }
  1325. /**
  1326. * mpi3mr_sas_port_remove - remove port from the list
  1327. * @mrioc: Adapter instance reference
  1328. * @sas_address: SAS address of attached device
  1329. * @sas_address_parent: SAS address of parent expander or host
  1330. * @hba_port: HBA port entry
  1331. *
  1332. * Removing object and freeing associated memory from the
  1333. * sas_port_list.
  1334. *
  1335. * Return: None
  1336. */
  1337. static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
  1338. u64 sas_address_parent, struct mpi3mr_hba_port *hba_port)
  1339. {
  1340. int i;
  1341. unsigned long flags;
  1342. struct mpi3mr_sas_port *mr_sas_port, *next;
  1343. struct mpi3mr_sas_node *mr_sas_node;
  1344. u8 found = 0;
  1345. struct mpi3mr_sas_phy *mr_sas_phy, *next_phy;
  1346. struct mpi3mr_hba_port *srch_port, *hba_port_next = NULL;
  1347. if (!hba_port)
  1348. return;
  1349. spin_lock_irqsave(&mrioc->sas_node_lock, flags);
  1350. mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
  1351. sas_address_parent, hba_port);
  1352. if (!mr_sas_node) {
  1353. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  1354. return;
  1355. }
  1356. list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list,
  1357. port_list) {
  1358. if (mr_sas_port->remote_identify.sas_address != sas_address)
  1359. continue;
  1360. if (mr_sas_port->hba_port != hba_port)
  1361. continue;
  1362. found = 1;
  1363. list_del(&mr_sas_port->port_list);
  1364. goto out;
  1365. }
  1366. out:
  1367. if (!found) {
  1368. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  1369. return;
  1370. }
  1371. if (mr_sas_node->host_node) {
  1372. list_for_each_entry_safe(srch_port, hba_port_next,
  1373. &mrioc->hba_port_table_list, list) {
  1374. if (srch_port != hba_port)
  1375. continue;
  1376. ioc_info(mrioc,
  1377. "removing hba_port entry: %p port: %d from hba_port list\n",
  1378. srch_port, srch_port->port_id);
  1379. list_del(&hba_port->list);
  1380. kfree(hba_port);
  1381. break;
  1382. }
  1383. }
  1384. for (i = 0; i < mr_sas_node->num_phys; i++) {
  1385. if (mr_sas_node->phy[i].remote_identify.sas_address ==
  1386. sas_address)
  1387. memset(&mr_sas_node->phy[i].remote_identify, 0,
  1388. sizeof(struct sas_identify));
  1389. }
  1390. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  1391. if (mrioc->current_event)
  1392. mrioc->current_event->pending_at_sml = 1;
  1393. list_for_each_entry_safe(mr_sas_phy, next_phy,
  1394. &mr_sas_port->phy_list, port_siblings) {
  1395. if ((!mrioc->stop_drv_processing) &&
  1396. (mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
  1397. dev_info(&mr_sas_port->port->dev,
  1398. "remove: sas_address(0x%016llx), phy(%d)\n",
  1399. (unsigned long long)
  1400. mr_sas_port->remote_identify.sas_address,
  1401. mr_sas_phy->phy_id);
  1402. mr_sas_phy->phy_belongs_to_port = 0;
  1403. if (!mrioc->stop_drv_processing)
  1404. sas_port_delete_phy(mr_sas_port->port,
  1405. mr_sas_phy->phy);
  1406. list_del(&mr_sas_phy->port_siblings);
  1407. }
  1408. if (!mrioc->stop_drv_processing)
  1409. sas_port_delete(mr_sas_port->port);
  1410. ioc_info(mrioc, "%s: removed sas_address(0x%016llx)\n",
  1411. __func__, (unsigned long long)sas_address);
  1412. if (mrioc->current_event) {
  1413. mrioc->current_event->pending_at_sml = 0;
  1414. if (mrioc->current_event->discard)
  1415. mpi3mr_print_device_event_notice(mrioc, false);
  1416. }
  1417. kfree(mr_sas_port);
  1418. }
  1419. /**
  1420. * struct host_port - host port details
  1421. * @sas_address: SAS Address of the attached device
  1422. * @phy_mask: phy mask of host port
  1423. * @handle: Device Handle of attached device
  1424. * @iounit_port_id: port ID
  1425. * @used: host port is already matched with sas port from sas_port_list
  1426. * @lowest_phy: lowest phy ID of host port
  1427. */
  1428. struct host_port {
  1429. u64 sas_address;
  1430. u32 phy_mask;
  1431. u16 handle;
  1432. u8 iounit_port_id;
  1433. u8 used;
  1434. u8 lowest_phy;
  1435. };
  1436. /**
  1437. * mpi3mr_update_mr_sas_port - update sas port objects during reset
  1438. * @mrioc: Adapter instance reference
  1439. * @h_port: host_port object
  1440. * @mr_sas_port: sas_port objects which needs to be updated
  1441. *
  1442. * Update the port ID of sas port object. Also add the phys if new phys got
  1443. * added to current sas port and remove the phys if some phys are moved
  1444. * out of the current sas port.
  1445. *
  1446. * Return: Nothing.
  1447. */
  1448. static void
  1449. mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
  1450. struct mpi3mr_sas_port *mr_sas_port)
  1451. {
  1452. struct mpi3mr_sas_phy *mr_sas_phy;
  1453. u32 phy_mask_xor;
  1454. u64 phys_to_be_added, phys_to_be_removed;
  1455. int i;
  1456. h_port->used = 1;
  1457. mr_sas_port->marked_responding = 1;
  1458. dev_info(&mr_sas_port->port->dev,
  1459. "sas_address(0x%016llx), old: port_id %d phy_mask 0x%x, new: port_id %d phy_mask:0x%x\n",
  1460. mr_sas_port->remote_identify.sas_address,
  1461. mr_sas_port->hba_port->port_id, mr_sas_port->phy_mask,
  1462. h_port->iounit_port_id, h_port->phy_mask);
  1463. mr_sas_port->hba_port->port_id = h_port->iounit_port_id;
  1464. mr_sas_port->hba_port->flags &= ~MPI3MR_HBA_PORT_FLAG_DIRTY;
  1465. /* Get the newly added phys bit map & removed phys bit map */
  1466. phy_mask_xor = mr_sas_port->phy_mask ^ h_port->phy_mask;
  1467. phys_to_be_added = h_port->phy_mask & phy_mask_xor;
  1468. phys_to_be_removed = mr_sas_port->phy_mask & phy_mask_xor;
  1469. /*
  1470. * Register these new phys to current mr_sas_port's port.
  1471. * if these phys are previously registered with another port
  1472. * then delete these phys from that port first.
  1473. */
  1474. for_each_set_bit(i, (ulong *) &phys_to_be_added, BITS_PER_TYPE(u32)) {
  1475. mr_sas_phy = &mrioc->sas_hba.phy[i];
  1476. if (mr_sas_phy->phy_belongs_to_port)
  1477. mpi3mr_del_phy_from_an_existing_port(mrioc,
  1478. &mrioc->sas_hba, mr_sas_phy);
  1479. mpi3mr_add_phy_to_an_existing_port(mrioc,
  1480. &mrioc->sas_hba, mr_sas_phy,
  1481. mr_sas_port->remote_identify.sas_address,
  1482. mr_sas_port->hba_port);
  1483. }
  1484. /* Delete the phys which are not part of current mr_sas_port's port. */
  1485. for_each_set_bit(i, (ulong *) &phys_to_be_removed, BITS_PER_TYPE(u32)) {
  1486. mr_sas_phy = &mrioc->sas_hba.phy[i];
  1487. if (mr_sas_phy->phy_belongs_to_port)
  1488. mpi3mr_del_phy_from_an_existing_port(mrioc,
  1489. &mrioc->sas_hba, mr_sas_phy);
  1490. }
  1491. }
  1492. /**
  1493. * mpi3mr_refresh_sas_ports - update host's sas ports during reset
  1494. * @mrioc: Adapter instance reference
  1495. *
  1496. * Update the host's sas ports during reset by checking whether
  1497. * sas ports are still intact or not. Add/remove phys if any hba
  1498. * phys are (moved in)/(moved out) of sas port. Also update
  1499. * io_unit_port if it got changed during reset.
  1500. *
  1501. * Return: Nothing.
  1502. */
  1503. void
  1504. mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
  1505. {
  1506. struct host_port h_port[32];
  1507. int i, j, found, host_port_count = 0, port_idx;
  1508. u16 sz, attached_handle, ioc_status;
  1509. struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
  1510. struct mpi3_device_page0 dev_pg0;
  1511. struct mpi3_device0_sas_sata_format *sasinf;
  1512. struct mpi3mr_sas_port *mr_sas_port;
  1513. sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
  1514. (mrioc->sas_hba.num_phys *
  1515. sizeof(struct mpi3_sas_io_unit0_phy_data));
  1516. sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
  1517. if (!sas_io_unit_pg0)
  1518. return;
  1519. if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
  1520. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1521. __FILE__, __LINE__, __func__);
  1522. goto out;
  1523. }
  1524. /* Create a new expander port table */
  1525. for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
  1526. attached_handle = le16_to_cpu(
  1527. sas_io_unit_pg0->phy_data[i].attached_dev_handle);
  1528. if (!attached_handle)
  1529. continue;
  1530. found = 0;
  1531. for (j = 0; j < host_port_count; j++) {
  1532. if (h_port[j].handle == attached_handle) {
  1533. h_port[j].phy_mask |= (1 << i);
  1534. found = 1;
  1535. break;
  1536. }
  1537. }
  1538. if (found)
  1539. continue;
  1540. if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
  1541. sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
  1542. attached_handle))) {
  1543. dprint_reset(mrioc,
  1544. "failed to read dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
  1545. attached_handle, __FILE__, __LINE__, __func__);
  1546. continue;
  1547. }
  1548. if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
  1549. dprint_reset(mrioc,
  1550. "ioc_status(0x%x) while reading dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
  1551. ioc_status, attached_handle,
  1552. __FILE__, __LINE__, __func__);
  1553. continue;
  1554. }
  1555. sasinf = &dev_pg0.device_specific.sas_sata_format;
  1556. port_idx = host_port_count;
  1557. h_port[port_idx].sas_address = le64_to_cpu(sasinf->sas_address);
  1558. h_port[port_idx].handle = attached_handle;
  1559. h_port[port_idx].phy_mask = (1 << i);
  1560. h_port[port_idx].iounit_port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
  1561. h_port[port_idx].lowest_phy = sasinf->phy_num;
  1562. h_port[port_idx].used = 0;
  1563. host_port_count++;
  1564. }
  1565. if (!host_port_count)
  1566. goto out;
  1567. if (mrioc->logging_level & MPI3_DEBUG_RESET) {
  1568. ioc_info(mrioc, "Host port details before reset\n");
  1569. list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
  1570. port_list) {
  1571. ioc_info(mrioc,
  1572. "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%x), lowest phy id:%d\n",
  1573. mr_sas_port->hba_port->port_id,
  1574. mr_sas_port->remote_identify.sas_address,
  1575. mr_sas_port->phy_mask, mr_sas_port->lowest_phy);
  1576. }
  1577. mr_sas_port = NULL;
  1578. ioc_info(mrioc, "Host port details after reset\n");
  1579. for (i = 0; i < host_port_count; i++) {
  1580. ioc_info(mrioc,
  1581. "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%x), lowest phy id:%d\n",
  1582. h_port[i].iounit_port_id, h_port[i].sas_address,
  1583. h_port[i].phy_mask, h_port[i].lowest_phy);
  1584. }
  1585. }
  1586. /* mark all host sas port entries as dirty */
  1587. list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
  1588. port_list) {
  1589. mr_sas_port->marked_responding = 0;
  1590. mr_sas_port->hba_port->flags |= MPI3MR_HBA_PORT_FLAG_DIRTY;
  1591. }
  1592. /* First check for matching lowest phy */
  1593. for (i = 0; i < host_port_count; i++) {
  1594. mr_sas_port = NULL;
  1595. list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
  1596. port_list) {
  1597. if (mr_sas_port->marked_responding)
  1598. continue;
  1599. if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
  1600. continue;
  1601. if (h_port[i].lowest_phy == mr_sas_port->lowest_phy) {
  1602. mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
  1603. break;
  1604. }
  1605. }
  1606. }
  1607. /* In case if lowest phy is got enabled or disabled during reset */
  1608. for (i = 0; i < host_port_count; i++) {
  1609. if (h_port[i].used)
  1610. continue;
  1611. mr_sas_port = NULL;
  1612. list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
  1613. port_list) {
  1614. if (mr_sas_port->marked_responding)
  1615. continue;
  1616. if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
  1617. continue;
  1618. if (h_port[i].phy_mask & mr_sas_port->phy_mask) {
  1619. mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
  1620. break;
  1621. }
  1622. }
  1623. }
  1624. /* In case if expander cable is removed & connected to another HBA port during reset */
  1625. for (i = 0; i < host_port_count; i++) {
  1626. if (h_port[i].used)
  1627. continue;
  1628. mr_sas_port = NULL;
  1629. list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
  1630. port_list) {
  1631. if (mr_sas_port->marked_responding)
  1632. continue;
  1633. if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
  1634. continue;
  1635. mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
  1636. break;
  1637. }
  1638. }
  1639. out:
  1640. kfree(sas_io_unit_pg0);
  1641. }
  1642. /**
  1643. * mpi3mr_refresh_expanders - Refresh expander device exposure
  1644. * @mrioc: Adapter instance reference
  1645. *
  1646. * This is executed post controller reset to identify any
  1647. * missing expander devices during reset and remove from the upper layers
  1648. * or expose any newly detected expander device to the upper layers.
  1649. *
  1650. * Return: Nothing.
  1651. */
  1652. void
  1653. mpi3mr_refresh_expanders(struct mpi3mr_ioc *mrioc)
  1654. {
  1655. struct mpi3mr_sas_node *sas_expander, *sas_expander_next;
  1656. struct mpi3_sas_expander_page0 expander_pg0;
  1657. u16 ioc_status, handle;
  1658. u64 sas_address;
  1659. int i;
  1660. unsigned long flags;
  1661. struct mpi3mr_hba_port *hba_port;
  1662. spin_lock_irqsave(&mrioc->sas_node_lock, flags);
  1663. list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
  1664. sas_expander->non_responding = 1;
  1665. }
  1666. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  1667. sas_expander = NULL;
  1668. handle = 0xffff;
  1669. /* Search for responding expander devices and add them if they are newly got added */
  1670. while (true) {
  1671. if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
  1672. sizeof(struct mpi3_sas_expander_page0),
  1673. MPI3_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
  1674. dprint_reset(mrioc,
  1675. "failed to read exp pg0 for handle(0x%04x) at %s:%d/%s()!\n",
  1676. handle, __FILE__, __LINE__, __func__);
  1677. break;
  1678. }
  1679. if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
  1680. dprint_reset(mrioc,
  1681. "ioc_status(0x%x) while reading exp pg0 for handle:(0x%04x), %s:%d/%s()!\n",
  1682. ioc_status, handle, __FILE__, __LINE__, __func__);
  1683. break;
  1684. }
  1685. handle = le16_to_cpu(expander_pg0.dev_handle);
  1686. sas_address = le64_to_cpu(expander_pg0.sas_address);
  1687. hba_port = mpi3mr_get_hba_port_by_id(mrioc, expander_pg0.io_unit_port);
  1688. if (!hba_port) {
  1689. mpi3mr_sas_host_refresh(mrioc);
  1690. mpi3mr_expander_add(mrioc, handle);
  1691. continue;
  1692. }
  1693. spin_lock_irqsave(&mrioc->sas_node_lock, flags);
  1694. sas_expander =
  1695. mpi3mr_expander_find_by_sas_address(mrioc,
  1696. sas_address, hba_port);
  1697. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  1698. if (!sas_expander) {
  1699. mpi3mr_sas_host_refresh(mrioc);
  1700. mpi3mr_expander_add(mrioc, handle);
  1701. continue;
  1702. }
  1703. sas_expander->non_responding = 0;
  1704. if (sas_expander->handle == handle)
  1705. continue;
  1706. sas_expander->handle = handle;
  1707. for (i = 0 ; i < sas_expander->num_phys ; i++)
  1708. sas_expander->phy[i].handle = handle;
  1709. }
  1710. /*
  1711. * Delete non responding expander devices and the corresponding
  1712. * hba_port if the non responding expander device's parent device
  1713. * is a host node.
  1714. */
  1715. sas_expander = NULL;
  1716. spin_lock_irqsave(&mrioc->sas_node_lock, flags);
  1717. list_for_each_entry_safe_reverse(sas_expander, sas_expander_next,
  1718. &mrioc->sas_expander_list, list) {
  1719. if (sas_expander->non_responding) {
  1720. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  1721. mpi3mr_expander_node_remove(mrioc, sas_expander);
  1722. spin_lock_irqsave(&mrioc->sas_node_lock, flags);
  1723. }
  1724. }
  1725. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  1726. }
  1727. /**
  1728. * mpi3mr_expander_node_add - insert an expander to the list.
  1729. * @mrioc: Adapter instance reference
  1730. * @sas_expander: Expander sas node
  1731. * Context: This function will acquire sas_node_lock.
  1732. *
  1733. * Adding new object to the ioc->sas_expander_list.
  1734. *
  1735. * Return: None.
  1736. */
  1737. static void mpi3mr_expander_node_add(struct mpi3mr_ioc *mrioc,
  1738. struct mpi3mr_sas_node *sas_expander)
  1739. {
  1740. unsigned long flags;
  1741. spin_lock_irqsave(&mrioc->sas_node_lock, flags);
  1742. list_add_tail(&sas_expander->list, &mrioc->sas_expander_list);
  1743. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  1744. }
  1745. /**
  1746. * mpi3mr_expander_add - Create expander object
  1747. * @mrioc: Adapter instance reference
  1748. * @handle: Expander firmware device handle
  1749. *
  1750. * This function creating expander object, stored in
  1751. * sas_expander_list and expose it to the SAS transport
  1752. * layer.
  1753. *
  1754. * Return: 0 for success, non-zero for failure.
  1755. */
  1756. int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle)
  1757. {
  1758. struct mpi3mr_sas_node *sas_expander;
  1759. struct mpi3mr_enclosure_node *enclosure_dev;
  1760. struct mpi3_sas_expander_page0 expander_pg0;
  1761. struct mpi3_sas_expander_page1 expander_pg1;
  1762. u16 ioc_status, parent_handle, temp_handle;
  1763. u64 sas_address, sas_address_parent = 0;
  1764. int i;
  1765. unsigned long flags;
  1766. u8 port_id, link_rate;
  1767. struct mpi3mr_sas_port *mr_sas_port = NULL;
  1768. struct mpi3mr_hba_port *hba_port;
  1769. u32 phynum_handle;
  1770. int rc = 0;
  1771. if (!handle)
  1772. return -1;
  1773. if (mrioc->reset_in_progress)
  1774. return -1;
  1775. if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
  1776. sizeof(expander_pg0), MPI3_SAS_EXPAND_PGAD_FORM_HANDLE, handle))) {
  1777. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1778. __FILE__, __LINE__, __func__);
  1779. return -1;
  1780. }
  1781. if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
  1782. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1783. __FILE__, __LINE__, __func__);
  1784. return -1;
  1785. }
  1786. parent_handle = le16_to_cpu(expander_pg0.parent_dev_handle);
  1787. if (mpi3mr_get_sas_address(mrioc, parent_handle, &sas_address_parent)
  1788. != 0) {
  1789. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1790. __FILE__, __LINE__, __func__);
  1791. return -1;
  1792. }
  1793. port_id = expander_pg0.io_unit_port;
  1794. hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id);
  1795. if (!hba_port) {
  1796. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1797. __FILE__, __LINE__, __func__);
  1798. return -1;
  1799. }
  1800. if (sas_address_parent != mrioc->sas_hba.sas_address) {
  1801. spin_lock_irqsave(&mrioc->sas_node_lock, flags);
  1802. sas_expander =
  1803. mpi3mr_expander_find_by_sas_address(mrioc,
  1804. sas_address_parent, hba_port);
  1805. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  1806. if (!sas_expander) {
  1807. rc = mpi3mr_expander_add(mrioc, parent_handle);
  1808. if (rc != 0)
  1809. return rc;
  1810. } else {
  1811. /*
  1812. * When there is a parent expander present, update it's
  1813. * phys where child expander is connected with the link
  1814. * speed, attached dev handle and sas address.
  1815. */
  1816. for (i = 0 ; i < sas_expander->num_phys ; i++) {
  1817. phynum_handle =
  1818. (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) |
  1819. parent_handle;
  1820. if (mpi3mr_cfg_get_sas_exp_pg1(mrioc,
  1821. &ioc_status, &expander_pg1,
  1822. sizeof(expander_pg1),
  1823. MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
  1824. phynum_handle)) {
  1825. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1826. __FILE__, __LINE__, __func__);
  1827. rc = -1;
  1828. return rc;
  1829. }
  1830. if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
  1831. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1832. __FILE__, __LINE__, __func__);
  1833. rc = -1;
  1834. return rc;
  1835. }
  1836. temp_handle = le16_to_cpu(
  1837. expander_pg1.attached_dev_handle);
  1838. if (temp_handle != handle)
  1839. continue;
  1840. link_rate = (expander_pg1.negotiated_link_rate &
  1841. MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
  1842. MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
  1843. mpi3mr_update_links(mrioc, sas_address_parent,
  1844. handle, i, link_rate, hba_port);
  1845. }
  1846. }
  1847. }
  1848. spin_lock_irqsave(&mrioc->sas_node_lock, flags);
  1849. sas_address = le64_to_cpu(expander_pg0.sas_address);
  1850. sas_expander = mpi3mr_expander_find_by_sas_address(mrioc,
  1851. sas_address, hba_port);
  1852. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  1853. if (sas_expander)
  1854. return 0;
  1855. sas_expander = kzalloc(sizeof(struct mpi3mr_sas_node),
  1856. GFP_KERNEL);
  1857. if (!sas_expander)
  1858. return -1;
  1859. sas_expander->handle = handle;
  1860. sas_expander->num_phys = expander_pg0.num_phys;
  1861. sas_expander->sas_address_parent = sas_address_parent;
  1862. sas_expander->sas_address = sas_address;
  1863. sas_expander->hba_port = hba_port;
  1864. ioc_info(mrioc,
  1865. "expander_add: handle(0x%04x), parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
  1866. handle, parent_handle, (unsigned long long)
  1867. sas_expander->sas_address, sas_expander->num_phys);
  1868. if (!sas_expander->num_phys) {
  1869. rc = -1;
  1870. goto out_fail;
  1871. }
  1872. sas_expander->phy = kcalloc(sas_expander->num_phys,
  1873. sizeof(struct mpi3mr_sas_phy), GFP_KERNEL);
  1874. if (!sas_expander->phy) {
  1875. rc = -1;
  1876. goto out_fail;
  1877. }
  1878. INIT_LIST_HEAD(&sas_expander->sas_port_list);
  1879. mr_sas_port = mpi3mr_sas_port_add(mrioc, handle, sas_address_parent,
  1880. sas_expander->hba_port);
  1881. if (!mr_sas_port) {
  1882. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1883. __FILE__, __LINE__, __func__);
  1884. rc = -1;
  1885. goto out_fail;
  1886. }
  1887. sas_expander->parent_dev = &mr_sas_port->rphy->dev;
  1888. sas_expander->rphy = mr_sas_port->rphy;
  1889. for (i = 0 ; i < sas_expander->num_phys ; i++) {
  1890. phynum_handle = (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) |
  1891. handle;
  1892. if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status,
  1893. &expander_pg1, sizeof(expander_pg1),
  1894. MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
  1895. phynum_handle)) {
  1896. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1897. __FILE__, __LINE__, __func__);
  1898. rc = -1;
  1899. goto out_fail;
  1900. }
  1901. if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
  1902. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1903. __FILE__, __LINE__, __func__);
  1904. rc = -1;
  1905. goto out_fail;
  1906. }
  1907. sas_expander->phy[i].handle = handle;
  1908. sas_expander->phy[i].phy_id = i;
  1909. sas_expander->phy[i].hba_port = hba_port;
  1910. if ((mpi3mr_add_expander_phy(mrioc, &sas_expander->phy[i],
  1911. expander_pg1, sas_expander->parent_dev))) {
  1912. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  1913. __FILE__, __LINE__, __func__);
  1914. rc = -1;
  1915. goto out_fail;
  1916. }
  1917. }
  1918. if (sas_expander->enclosure_handle) {
  1919. enclosure_dev =
  1920. mpi3mr_enclosure_find_by_handle(mrioc,
  1921. sas_expander->enclosure_handle);
  1922. if (enclosure_dev)
  1923. sas_expander->enclosure_logical_id = le64_to_cpu(
  1924. enclosure_dev->pg0.enclosure_logical_id);
  1925. }
  1926. mpi3mr_expander_node_add(mrioc, sas_expander);
  1927. return 0;
  1928. out_fail:
  1929. if (mr_sas_port)
  1930. mpi3mr_sas_port_remove(mrioc,
  1931. sas_expander->sas_address,
  1932. sas_address_parent, sas_expander->hba_port);
  1933. kfree(sas_expander->phy);
  1934. kfree(sas_expander);
  1935. return rc;
  1936. }
  1937. /**
  1938. * mpi3mr_expander_node_remove - recursive removal of expander.
  1939. * @mrioc: Adapter instance reference
  1940. * @sas_expander: Expander device object
  1941. *
  1942. * Removes expander object and freeing associated memory from
  1943. * the sas_expander_list and removes the same from SAS TL, if
  1944. * one of the attached device is an expander then it recursively
  1945. * removes the expander device too.
  1946. *
  1947. * Return nothing.
  1948. */
  1949. void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc,
  1950. struct mpi3mr_sas_node *sas_expander)
  1951. {
  1952. struct mpi3mr_sas_port *mr_sas_port, *next;
  1953. unsigned long flags;
  1954. u8 port_id;
  1955. /* remove sibling ports attached to this expander */
  1956. list_for_each_entry_safe(mr_sas_port, next,
  1957. &sas_expander->sas_port_list, port_list) {
  1958. if (mrioc->reset_in_progress)
  1959. return;
  1960. if (mr_sas_port->remote_identify.device_type ==
  1961. SAS_END_DEVICE)
  1962. mpi3mr_remove_device_by_sas_address(mrioc,
  1963. mr_sas_port->remote_identify.sas_address,
  1964. mr_sas_port->hba_port);
  1965. else if (mr_sas_port->remote_identify.device_type ==
  1966. SAS_EDGE_EXPANDER_DEVICE ||
  1967. mr_sas_port->remote_identify.device_type ==
  1968. SAS_FANOUT_EXPANDER_DEVICE)
  1969. mpi3mr_expander_remove(mrioc,
  1970. mr_sas_port->remote_identify.sas_address,
  1971. mr_sas_port->hba_port);
  1972. }
  1973. port_id = sas_expander->hba_port->port_id;
  1974. mpi3mr_sas_port_remove(mrioc, sas_expander->sas_address,
  1975. sas_expander->sas_address_parent, sas_expander->hba_port);
  1976. ioc_info(mrioc, "expander_remove: handle(0x%04x), sas_addr(0x%016llx), port:%d\n",
  1977. sas_expander->handle, (unsigned long long)
  1978. sas_expander->sas_address, port_id);
  1979. spin_lock_irqsave(&mrioc->sas_node_lock, flags);
  1980. list_del(&sas_expander->list);
  1981. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  1982. kfree(sas_expander->phy);
  1983. kfree(sas_expander);
  1984. }
  1985. /**
  1986. * mpi3mr_expander_remove - Remove expander object
  1987. * @mrioc: Adapter instance reference
  1988. * @sas_address: Remove expander sas_address
  1989. * @hba_port: HBA port reference
  1990. *
  1991. * This function remove expander object, stored in
  1992. * mrioc->sas_expander_list and removes it from the SAS TL by
  1993. * calling mpi3mr_expander_node_remove().
  1994. *
  1995. * Return: None
  1996. */
  1997. void mpi3mr_expander_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
  1998. struct mpi3mr_hba_port *hba_port)
  1999. {
  2000. struct mpi3mr_sas_node *sas_expander;
  2001. unsigned long flags;
  2002. if (mrioc->reset_in_progress)
  2003. return;
  2004. if (!hba_port)
  2005. return;
  2006. spin_lock_irqsave(&mrioc->sas_node_lock, flags);
  2007. sas_expander = mpi3mr_expander_find_by_sas_address(mrioc, sas_address,
  2008. hba_port);
  2009. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  2010. if (sas_expander)
  2011. mpi3mr_expander_node_remove(mrioc, sas_expander);
  2012. }
  2013. /**
  2014. * mpi3mr_get_sas_negotiated_logical_linkrate - get linkrate
  2015. * @mrioc: Adapter instance reference
  2016. * @tgtdev: Target device
  2017. *
  2018. * This function identifies whether the target device is
  2019. * attached directly or through expander and issues sas phy
  2020. * page0 or expander phy page1 and gets the link rate, if there
  2021. * is any failure in reading the pages then this returns link
  2022. * rate of 1.5.
  2023. *
  2024. * Return: logical link rate.
  2025. */
  2026. static u8 mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc *mrioc,
  2027. struct mpi3mr_tgt_dev *tgtdev)
  2028. {
  2029. u8 link_rate = MPI3_SAS_NEG_LINK_RATE_1_5, phy_number;
  2030. struct mpi3_sas_expander_page1 expander_pg1;
  2031. struct mpi3_sas_phy_page0 phy_pg0;
  2032. u32 phynum_handle;
  2033. u16 ioc_status;
  2034. phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
  2035. if (!(tgtdev->devpg0_flag & MPI3_DEVICE0_FLAGS_ATT_METHOD_DIR_ATTACHED)) {
  2036. phynum_handle = ((phy_number<<MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT)
  2037. | tgtdev->parent_handle);
  2038. if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status,
  2039. &expander_pg1, sizeof(expander_pg1),
  2040. MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
  2041. phynum_handle)) {
  2042. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  2043. __FILE__, __LINE__, __func__);
  2044. goto out;
  2045. }
  2046. if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
  2047. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  2048. __FILE__, __LINE__, __func__);
  2049. goto out;
  2050. }
  2051. link_rate = (expander_pg1.negotiated_link_rate &
  2052. MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
  2053. MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
  2054. goto out;
  2055. }
  2056. if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
  2057. sizeof(struct mpi3_sas_phy_page0),
  2058. MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy_number)) {
  2059. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  2060. __FILE__, __LINE__, __func__);
  2061. goto out;
  2062. }
  2063. if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
  2064. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  2065. __FILE__, __LINE__, __func__);
  2066. goto out;
  2067. }
  2068. link_rate = (phy_pg0.negotiated_link_rate &
  2069. MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
  2070. MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
  2071. out:
  2072. return link_rate;
  2073. }
  2074. /**
  2075. * mpi3mr_report_tgtdev_to_sas_transport - expose dev to SAS TL
  2076. * @mrioc: Adapter instance reference
  2077. * @tgtdev: Target device
  2078. *
  2079. * This function exposes the target device after
  2080. * preparing host_phy, setting up link rate etc.
  2081. *
  2082. * Return: 0 on success, non-zero for failure.
  2083. */
  2084. int mpi3mr_report_tgtdev_to_sas_transport(struct mpi3mr_ioc *mrioc,
  2085. struct mpi3mr_tgt_dev *tgtdev)
  2086. {
  2087. int retval = 0;
  2088. u8 link_rate, parent_phy_number;
  2089. u64 sas_address_parent, sas_address;
  2090. struct mpi3mr_hba_port *hba_port;
  2091. u8 port_id;
  2092. if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) ||
  2093. !mrioc->sas_transport_enabled)
  2094. return -1;
  2095. sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address;
  2096. if (!mrioc->sas_hba.num_phys)
  2097. mpi3mr_sas_host_add(mrioc);
  2098. else
  2099. mpi3mr_sas_host_refresh(mrioc);
  2100. if (mpi3mr_get_sas_address(mrioc, tgtdev->parent_handle,
  2101. &sas_address_parent) != 0) {
  2102. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  2103. __FILE__, __LINE__, __func__);
  2104. return -1;
  2105. }
  2106. tgtdev->dev_spec.sas_sata_inf.sas_address_parent = sas_address_parent;
  2107. parent_phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
  2108. port_id = tgtdev->io_unit_port;
  2109. hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id);
  2110. if (!hba_port) {
  2111. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  2112. __FILE__, __LINE__, __func__);
  2113. return -1;
  2114. }
  2115. tgtdev->dev_spec.sas_sata_inf.hba_port = hba_port;
  2116. link_rate = mpi3mr_get_sas_negotiated_logical_linkrate(mrioc, tgtdev);
  2117. mpi3mr_update_links(mrioc, sas_address_parent, tgtdev->dev_handle,
  2118. parent_phy_number, link_rate, hba_port);
  2119. tgtdev->host_exposed = 1;
  2120. if (!mpi3mr_sas_port_add(mrioc, tgtdev->dev_handle,
  2121. sas_address_parent, hba_port)) {
  2122. retval = -1;
  2123. } else if ((!tgtdev->starget) && (!mrioc->is_driver_loading)) {
  2124. mpi3mr_sas_port_remove(mrioc, sas_address,
  2125. sas_address_parent, hba_port);
  2126. retval = -1;
  2127. }
  2128. if (retval) {
  2129. tgtdev->dev_spec.sas_sata_inf.hba_port = NULL;
  2130. tgtdev->host_exposed = 0;
  2131. }
  2132. return retval;
  2133. }
  2134. /**
  2135. * mpi3mr_remove_tgtdev_from_sas_transport - remove from SAS TL
  2136. * @mrioc: Adapter instance reference
  2137. * @tgtdev: Target device
  2138. *
  2139. * This function removes the target device
  2140. *
  2141. * Return: None.
  2142. */
  2143. void mpi3mr_remove_tgtdev_from_sas_transport(struct mpi3mr_ioc *mrioc,
  2144. struct mpi3mr_tgt_dev *tgtdev)
  2145. {
  2146. u64 sas_address_parent, sas_address;
  2147. struct mpi3mr_hba_port *hba_port;
  2148. if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) ||
  2149. !mrioc->sas_transport_enabled)
  2150. return;
  2151. hba_port = tgtdev->dev_spec.sas_sata_inf.hba_port;
  2152. sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address;
  2153. sas_address_parent = tgtdev->dev_spec.sas_sata_inf.sas_address_parent;
  2154. mpi3mr_sas_port_remove(mrioc, sas_address, sas_address_parent,
  2155. hba_port);
  2156. tgtdev->host_exposed = 0;
  2157. tgtdev->dev_spec.sas_sata_inf.hba_port = NULL;
  2158. }
  2159. /**
  2160. * mpi3mr_get_port_id_by_sas_phy - Get port ID of the given phy
  2161. * @phy: SAS transport layer phy object
  2162. *
  2163. * Return: Port number for valid ID else 0xFFFF
  2164. */
  2165. static inline u8 mpi3mr_get_port_id_by_sas_phy(struct sas_phy *phy)
  2166. {
  2167. u8 port_id = 0xFF;
  2168. struct mpi3mr_hba_port *hba_port = phy->hostdata;
  2169. if (hba_port)
  2170. port_id = hba_port->port_id;
  2171. return port_id;
  2172. }
  2173. /**
  2174. * mpi3mr_get_port_id_by_rphy - Get Port number from SAS rphy
  2175. *
  2176. * @mrioc: Adapter instance reference
  2177. * @rphy: SAS transport layer remote phy object
  2178. *
  2179. * Retrieves HBA port number in which the device pointed by the
  2180. * rphy object is attached with.
  2181. *
  2182. * Return: Valid port number on success else OxFFFF.
  2183. */
  2184. static u8 mpi3mr_get_port_id_by_rphy(struct mpi3mr_ioc *mrioc, struct sas_rphy *rphy)
  2185. {
  2186. struct mpi3mr_sas_node *sas_expander;
  2187. struct mpi3mr_tgt_dev *tgtdev;
  2188. unsigned long flags;
  2189. u8 port_id = 0xFF;
  2190. if (!rphy)
  2191. return port_id;
  2192. if (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
  2193. rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) {
  2194. spin_lock_irqsave(&mrioc->sas_node_lock, flags);
  2195. list_for_each_entry(sas_expander, &mrioc->sas_expander_list,
  2196. list) {
  2197. if (sas_expander->rphy == rphy) {
  2198. port_id = sas_expander->hba_port->port_id;
  2199. break;
  2200. }
  2201. }
  2202. spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
  2203. } else if (rphy->identify.device_type == SAS_END_DEVICE) {
  2204. spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
  2205. tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
  2206. rphy->identify.sas_address, rphy);
  2207. if (tgtdev && tgtdev->dev_spec.sas_sata_inf.hba_port) {
  2208. port_id =
  2209. tgtdev->dev_spec.sas_sata_inf.hba_port->port_id;
  2210. mpi3mr_tgtdev_put(tgtdev);
  2211. }
  2212. spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
  2213. }
  2214. return port_id;
  2215. }
  2216. static inline struct mpi3mr_ioc *phy_to_mrioc(struct sas_phy *phy)
  2217. {
  2218. struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
  2219. return shost_priv(shost);
  2220. }
  2221. static inline struct mpi3mr_ioc *rphy_to_mrioc(struct sas_rphy *rphy)
  2222. {
  2223. struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
  2224. return shost_priv(shost);
  2225. }
  2226. /* report phy error log structure */
  2227. struct phy_error_log_request {
  2228. u8 smp_frame_type; /* 0x40 */
  2229. u8 function; /* 0x11 */
  2230. u8 allocated_response_length;
  2231. u8 request_length; /* 02 */
  2232. u8 reserved_1[5];
  2233. u8 phy_identifier;
  2234. u8 reserved_2[2];
  2235. };
  2236. /* report phy error log reply structure */
  2237. struct phy_error_log_reply {
  2238. u8 smp_frame_type; /* 0x41 */
  2239. u8 function; /* 0x11 */
  2240. u8 function_result;
  2241. u8 response_length;
  2242. __be16 expander_change_count;
  2243. u8 reserved_1[3];
  2244. u8 phy_identifier;
  2245. u8 reserved_2[2];
  2246. __be32 invalid_dword;
  2247. __be32 running_disparity_error;
  2248. __be32 loss_of_dword_sync;
  2249. __be32 phy_reset_problem;
  2250. };
  2251. /**
  2252. * mpi3mr_get_expander_phy_error_log - return expander counters:
  2253. * @mrioc: Adapter instance reference
  2254. * @phy: The SAS transport layer phy object
  2255. *
  2256. * Return: 0 for success, non-zero for failure.
  2257. *
  2258. */
  2259. static int mpi3mr_get_expander_phy_error_log(struct mpi3mr_ioc *mrioc,
  2260. struct sas_phy *phy)
  2261. {
  2262. struct mpi3_smp_passthrough_request mpi_request;
  2263. struct mpi3_smp_passthrough_reply mpi_reply;
  2264. struct phy_error_log_request *phy_error_log_request;
  2265. struct phy_error_log_reply *phy_error_log_reply;
  2266. int rc;
  2267. void *psge;
  2268. void *data_out = NULL;
  2269. dma_addr_t data_out_dma, data_in_dma;
  2270. u32 data_out_sz, data_in_sz, sz;
  2271. u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
  2272. u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
  2273. u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
  2274. u16 ioc_status;
  2275. if (mrioc->reset_in_progress) {
  2276. ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
  2277. return -EFAULT;
  2278. }
  2279. data_out_sz = sizeof(struct phy_error_log_request);
  2280. data_in_sz = sizeof(struct phy_error_log_reply);
  2281. sz = data_out_sz + data_in_sz;
  2282. data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma,
  2283. GFP_KERNEL);
  2284. if (!data_out) {
  2285. rc = -ENOMEM;
  2286. goto out;
  2287. }
  2288. data_in_dma = data_out_dma + data_out_sz;
  2289. phy_error_log_reply = data_out + data_out_sz;
  2290. rc = -EINVAL;
  2291. memset(data_out, 0, sz);
  2292. phy_error_log_request = data_out;
  2293. phy_error_log_request->smp_frame_type = 0x40;
  2294. phy_error_log_request->function = 0x11;
  2295. phy_error_log_request->request_length = 2;
  2296. phy_error_log_request->allocated_response_length = 0;
  2297. phy_error_log_request->phy_identifier = phy->number;
  2298. memset(&mpi_request, 0, request_sz);
  2299. memset(&mpi_reply, 0, reply_sz);
  2300. mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
  2301. mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
  2302. mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy);
  2303. mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address);
  2304. psge = &mpi_request.request_sge;
  2305. mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
  2306. psge = &mpi_request.response_sge;
  2307. mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
  2308. dprint_transport_info(mrioc,
  2309. "sending phy error log SMP request to sas_address(0x%016llx), phy_id(%d)\n",
  2310. (unsigned long long)phy->identify.sas_address, phy->number);
  2311. if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
  2312. &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status))
  2313. goto out;
  2314. dprint_transport_info(mrioc,
  2315. "phy error log SMP request completed with ioc_status(0x%04x)\n",
  2316. ioc_status);
  2317. if (ioc_status == MPI3_IOCSTATUS_SUCCESS) {
  2318. dprint_transport_info(mrioc,
  2319. "phy error log - reply data transfer size(%d)\n",
  2320. le16_to_cpu(mpi_reply.response_data_length));
  2321. if (le16_to_cpu(mpi_reply.response_data_length) !=
  2322. sizeof(struct phy_error_log_reply))
  2323. goto out;
  2324. dprint_transport_info(mrioc,
  2325. "phy error log - function_result(%d)\n",
  2326. phy_error_log_reply->function_result);
  2327. phy->invalid_dword_count =
  2328. be32_to_cpu(phy_error_log_reply->invalid_dword);
  2329. phy->running_disparity_error_count =
  2330. be32_to_cpu(phy_error_log_reply->running_disparity_error);
  2331. phy->loss_of_dword_sync_count =
  2332. be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
  2333. phy->phy_reset_problem_count =
  2334. be32_to_cpu(phy_error_log_reply->phy_reset_problem);
  2335. rc = 0;
  2336. }
  2337. out:
  2338. if (data_out)
  2339. dma_free_coherent(&mrioc->pdev->dev, sz, data_out,
  2340. data_out_dma);
  2341. return rc;
  2342. }
  2343. /**
  2344. * mpi3mr_transport_get_linkerrors - return phy error counters
  2345. * @phy: The SAS transport layer phy object
  2346. *
  2347. * This function retrieves the phy error log information of the
  2348. * HBA or expander for which the phy belongs to
  2349. *
  2350. * Return: 0 for success, non-zero for failure.
  2351. */
  2352. static int mpi3mr_transport_get_linkerrors(struct sas_phy *phy)
  2353. {
  2354. struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
  2355. struct mpi3_sas_phy_page1 phy_pg1;
  2356. int rc = 0;
  2357. u16 ioc_status;
  2358. rc = mpi3mr_parent_present(mrioc, phy);
  2359. if (rc)
  2360. return rc;
  2361. if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
  2362. return mpi3mr_get_expander_phy_error_log(mrioc, phy);
  2363. memset(&phy_pg1, 0, sizeof(struct mpi3_sas_phy_page1));
  2364. /* get hba phy error logs */
  2365. if ((mpi3mr_cfg_get_sas_phy_pg1(mrioc, &ioc_status, &phy_pg1,
  2366. sizeof(struct mpi3_sas_phy_page1),
  2367. MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number))) {
  2368. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  2369. __FILE__, __LINE__, __func__);
  2370. return -ENXIO;
  2371. }
  2372. if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
  2373. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  2374. __FILE__, __LINE__, __func__);
  2375. return -ENXIO;
  2376. }
  2377. phy->invalid_dword_count = le32_to_cpu(phy_pg1.invalid_dword_count);
  2378. phy->running_disparity_error_count =
  2379. le32_to_cpu(phy_pg1.running_disparity_error_count);
  2380. phy->loss_of_dword_sync_count =
  2381. le32_to_cpu(phy_pg1.loss_dword_synch_count);
  2382. phy->phy_reset_problem_count =
  2383. le32_to_cpu(phy_pg1.phy_reset_problem_count);
  2384. return 0;
  2385. }
  2386. /**
  2387. * mpi3mr_transport_get_enclosure_identifier - Get Enclosure ID
  2388. * @rphy: The SAS transport layer remote phy object
  2389. * @identifier: Enclosure identifier to be returned
  2390. *
  2391. * Returns the enclosure id for the device pointed by the remote
  2392. * phy object.
  2393. *
  2394. * Return: 0 on success or -ENXIO
  2395. */
  2396. static int
  2397. mpi3mr_transport_get_enclosure_identifier(struct sas_rphy *rphy,
  2398. u64 *identifier)
  2399. {
  2400. struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy);
  2401. struct mpi3mr_tgt_dev *tgtdev = NULL;
  2402. unsigned long flags;
  2403. int rc;
  2404. spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
  2405. tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
  2406. rphy->identify.sas_address, rphy);
  2407. if (tgtdev) {
  2408. *identifier =
  2409. tgtdev->enclosure_logical_id;
  2410. rc = 0;
  2411. mpi3mr_tgtdev_put(tgtdev);
  2412. } else {
  2413. *identifier = 0;
  2414. rc = -ENXIO;
  2415. }
  2416. spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
  2417. return rc;
  2418. }
  2419. /**
  2420. * mpi3mr_transport_get_bay_identifier - Get bay ID
  2421. * @rphy: The SAS transport layer remote phy object
  2422. *
  2423. * Returns the slot id for the device pointed by the remote phy
  2424. * object.
  2425. *
  2426. * Return: Valid slot ID on success or -ENXIO
  2427. */
  2428. static int
  2429. mpi3mr_transport_get_bay_identifier(struct sas_rphy *rphy)
  2430. {
  2431. struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy);
  2432. struct mpi3mr_tgt_dev *tgtdev = NULL;
  2433. unsigned long flags;
  2434. int rc;
  2435. spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
  2436. tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
  2437. rphy->identify.sas_address, rphy);
  2438. if (tgtdev) {
  2439. rc = tgtdev->slot;
  2440. mpi3mr_tgtdev_put(tgtdev);
  2441. } else
  2442. rc = -ENXIO;
  2443. spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
  2444. return rc;
  2445. }
  2446. /* phy control request structure */
  2447. struct phy_control_request {
  2448. u8 smp_frame_type; /* 0x40 */
  2449. u8 function; /* 0x91 */
  2450. u8 allocated_response_length;
  2451. u8 request_length; /* 0x09 */
  2452. u16 expander_change_count;
  2453. u8 reserved_1[3];
  2454. u8 phy_identifier;
  2455. u8 phy_operation;
  2456. u8 reserved_2[13];
  2457. u64 attached_device_name;
  2458. u8 programmed_min_physical_link_rate;
  2459. u8 programmed_max_physical_link_rate;
  2460. u8 reserved_3[6];
  2461. };
  2462. /* phy control reply structure */
  2463. struct phy_control_reply {
  2464. u8 smp_frame_type; /* 0x41 */
  2465. u8 function; /* 0x11 */
  2466. u8 function_result;
  2467. u8 response_length;
  2468. };
  2469. #define SMP_PHY_CONTROL_LINK_RESET (0x01)
  2470. #define SMP_PHY_CONTROL_HARD_RESET (0x02)
  2471. #define SMP_PHY_CONTROL_DISABLE (0x03)
  2472. /**
  2473. * mpi3mr_expander_phy_control - expander phy control
  2474. * @mrioc: Adapter instance reference
  2475. * @phy: The SAS transport layer phy object
  2476. * @phy_operation: The phy operation to be executed
  2477. *
  2478. * Issues SMP passthru phy control request to execute a specific
  2479. * phy operation for a given expander device.
  2480. *
  2481. * Return: 0 for success, non-zero for failure.
  2482. */
  2483. static int
  2484. mpi3mr_expander_phy_control(struct mpi3mr_ioc *mrioc,
  2485. struct sas_phy *phy, u8 phy_operation)
  2486. {
  2487. struct mpi3_smp_passthrough_request mpi_request;
  2488. struct mpi3_smp_passthrough_reply mpi_reply;
  2489. struct phy_control_request *phy_control_request;
  2490. struct phy_control_reply *phy_control_reply;
  2491. int rc;
  2492. void *psge;
  2493. void *data_out = NULL;
  2494. dma_addr_t data_out_dma;
  2495. dma_addr_t data_in_dma;
  2496. size_t data_in_sz;
  2497. size_t data_out_sz;
  2498. u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
  2499. u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
  2500. u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
  2501. u16 ioc_status;
  2502. u16 sz;
  2503. if (mrioc->reset_in_progress) {
  2504. ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
  2505. return -EFAULT;
  2506. }
  2507. data_out_sz = sizeof(struct phy_control_request);
  2508. data_in_sz = sizeof(struct phy_control_reply);
  2509. sz = data_out_sz + data_in_sz;
  2510. data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma,
  2511. GFP_KERNEL);
  2512. if (!data_out) {
  2513. rc = -ENOMEM;
  2514. goto out;
  2515. }
  2516. data_in_dma = data_out_dma + data_out_sz;
  2517. phy_control_reply = data_out + data_out_sz;
  2518. rc = -EINVAL;
  2519. memset(data_out, 0, sz);
  2520. phy_control_request = data_out;
  2521. phy_control_request->smp_frame_type = 0x40;
  2522. phy_control_request->function = 0x91;
  2523. phy_control_request->request_length = 9;
  2524. phy_control_request->allocated_response_length = 0;
  2525. phy_control_request->phy_identifier = phy->number;
  2526. phy_control_request->phy_operation = phy_operation;
  2527. phy_control_request->programmed_min_physical_link_rate =
  2528. phy->minimum_linkrate << 4;
  2529. phy_control_request->programmed_max_physical_link_rate =
  2530. phy->maximum_linkrate << 4;
  2531. memset(&mpi_request, 0, request_sz);
  2532. memset(&mpi_reply, 0, reply_sz);
  2533. mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
  2534. mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
  2535. mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy);
  2536. mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address);
  2537. psge = &mpi_request.request_sge;
  2538. mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
  2539. psge = &mpi_request.response_sge;
  2540. mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
  2541. dprint_transport_info(mrioc,
  2542. "sending phy control SMP request to sas_address(0x%016llx), phy_id(%d) opcode(%d)\n",
  2543. (unsigned long long)phy->identify.sas_address, phy->number,
  2544. phy_operation);
  2545. if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
  2546. &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status))
  2547. goto out;
  2548. dprint_transport_info(mrioc,
  2549. "phy control SMP request completed with ioc_status(0x%04x)\n",
  2550. ioc_status);
  2551. if (ioc_status == MPI3_IOCSTATUS_SUCCESS) {
  2552. dprint_transport_info(mrioc,
  2553. "phy control - reply data transfer size(%d)\n",
  2554. le16_to_cpu(mpi_reply.response_data_length));
  2555. if (le16_to_cpu(mpi_reply.response_data_length) !=
  2556. sizeof(struct phy_control_reply))
  2557. goto out;
  2558. dprint_transport_info(mrioc,
  2559. "phy control - function_result(%d)\n",
  2560. phy_control_reply->function_result);
  2561. rc = 0;
  2562. }
  2563. out:
  2564. if (data_out)
  2565. dma_free_coherent(&mrioc->pdev->dev, sz, data_out,
  2566. data_out_dma);
  2567. return rc;
  2568. }
  2569. /**
  2570. * mpi3mr_transport_phy_reset - Reset a given phy
  2571. * @phy: The SAS transport layer phy object
  2572. * @hard_reset: Flag to indicate the type of reset
  2573. *
  2574. * Return: 0 for success, non-zero for failure.
  2575. */
  2576. static int
  2577. mpi3mr_transport_phy_reset(struct sas_phy *phy, int hard_reset)
  2578. {
  2579. struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
  2580. struct mpi3_iounit_control_request mpi_request;
  2581. struct mpi3_iounit_control_reply mpi_reply;
  2582. u16 request_sz = sizeof(struct mpi3_iounit_control_request);
  2583. u16 reply_sz = sizeof(struct mpi3_iounit_control_reply);
  2584. int rc = 0;
  2585. u16 ioc_status;
  2586. rc = mpi3mr_parent_present(mrioc, phy);
  2587. if (rc)
  2588. return rc;
  2589. /* handle expander phys */
  2590. if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
  2591. return mpi3mr_expander_phy_control(mrioc, phy,
  2592. (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
  2593. SMP_PHY_CONTROL_LINK_RESET);
  2594. /* handle hba phys */
  2595. memset(&mpi_request, 0, request_sz);
  2596. mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
  2597. mpi_request.function = MPI3_FUNCTION_IO_UNIT_CONTROL;
  2598. mpi_request.operation = MPI3_CTRL_OP_SAS_PHY_CONTROL;
  2599. mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_ACTION_INDEX] =
  2600. (hard_reset ? MPI3_CTRL_ACTION_HARD_RESET :
  2601. MPI3_CTRL_ACTION_LINK_RESET);
  2602. mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_PHY_INDEX] =
  2603. phy->number;
  2604. dprint_transport_info(mrioc,
  2605. "sending phy reset request to sas_address(0x%016llx), phy_id(%d) hard_reset(%d)\n",
  2606. (unsigned long long)phy->identify.sas_address, phy->number,
  2607. hard_reset);
  2608. if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
  2609. &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status)) {
  2610. rc = -EAGAIN;
  2611. goto out;
  2612. }
  2613. dprint_transport_info(mrioc,
  2614. "phy reset request completed with ioc_status(0x%04x)\n",
  2615. ioc_status);
  2616. out:
  2617. return rc;
  2618. }
  2619. /**
  2620. * mpi3mr_transport_phy_enable - enable/disable phys
  2621. * @phy: The SAS transport layer phy object
  2622. * @enable: flag to enable/disable, enable phy when true
  2623. *
  2624. * This function enables/disables a given by executing required
  2625. * configuration page changes or expander phy control command
  2626. *
  2627. * Return: 0 for success, non-zero for failure.
  2628. */
  2629. static int
  2630. mpi3mr_transport_phy_enable(struct sas_phy *phy, int enable)
  2631. {
  2632. struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
  2633. struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
  2634. struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL;
  2635. u16 sz;
  2636. int rc = 0;
  2637. int i, discovery_active;
  2638. rc = mpi3mr_parent_present(mrioc, phy);
  2639. if (rc)
  2640. return rc;
  2641. /* handle expander phys */
  2642. if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
  2643. return mpi3mr_expander_phy_control(mrioc, phy,
  2644. (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
  2645. SMP_PHY_CONTROL_DISABLE);
  2646. /* handle hba phys */
  2647. sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
  2648. (mrioc->sas_hba.num_phys *
  2649. sizeof(struct mpi3_sas_io_unit0_phy_data));
  2650. sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
  2651. if (!sas_io_unit_pg0) {
  2652. rc = -ENOMEM;
  2653. goto out;
  2654. }
  2655. if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
  2656. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  2657. __FILE__, __LINE__, __func__);
  2658. rc = -ENXIO;
  2659. goto out;
  2660. }
  2661. /* unable to enable/disable phys when discovery is active */
  2662. for (i = 0, discovery_active = 0; i < mrioc->sas_hba.num_phys ; i++) {
  2663. if (sas_io_unit_pg0->phy_data[i].port_flags &
  2664. MPI3_SASIOUNIT0_PORTFLAGS_DISC_IN_PROGRESS) {
  2665. ioc_err(mrioc,
  2666. "discovery is active on port = %d, phy = %d\n"
  2667. "\tunable to enable/disable phys, try again later!\n",
  2668. sas_io_unit_pg0->phy_data[i].io_unit_port, i);
  2669. discovery_active = 1;
  2670. }
  2671. }
  2672. if (discovery_active) {
  2673. rc = -EAGAIN;
  2674. goto out;
  2675. }
  2676. if ((sas_io_unit_pg0->phy_data[phy->number].phy_flags &
  2677. (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
  2678. MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))) {
  2679. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  2680. __FILE__, __LINE__, __func__);
  2681. rc = -ENXIO;
  2682. goto out;
  2683. }
  2684. /* read sas_iounit page 1 */
  2685. sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) +
  2686. (mrioc->sas_hba.num_phys *
  2687. sizeof(struct mpi3_sas_io_unit1_phy_data));
  2688. sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL);
  2689. if (!sas_io_unit_pg1) {
  2690. rc = -ENOMEM;
  2691. goto out;
  2692. }
  2693. if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
  2694. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  2695. __FILE__, __LINE__, __func__);
  2696. rc = -ENXIO;
  2697. goto out;
  2698. }
  2699. if (enable)
  2700. sas_io_unit_pg1->phy_data[phy->number].phy_flags
  2701. &= ~MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
  2702. else
  2703. sas_io_unit_pg1->phy_data[phy->number].phy_flags
  2704. |= MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
  2705. mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz);
  2706. /* link reset */
  2707. if (enable)
  2708. mpi3mr_transport_phy_reset(phy, 0);
  2709. out:
  2710. kfree(sas_io_unit_pg1);
  2711. kfree(sas_io_unit_pg0);
  2712. return rc;
  2713. }
  2714. /**
  2715. * mpi3mr_transport_phy_speed - set phy min/max speed
  2716. * @phy: The SAS transport later phy object
  2717. * @rates: Rates defined as in sas_phy_linkrates
  2718. *
  2719. * This function sets the link rates given in the rates
  2720. * argument to the given phy by executing required configuration
  2721. * page changes or expander phy control command
  2722. *
  2723. * Return: 0 for success, non-zero for failure.
  2724. */
  2725. static int
  2726. mpi3mr_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
  2727. {
  2728. struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
  2729. struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL;
  2730. struct mpi3_sas_phy_page0 phy_pg0;
  2731. u16 sz, ioc_status;
  2732. int rc = 0;
  2733. rc = mpi3mr_parent_present(mrioc, phy);
  2734. if (rc)
  2735. return rc;
  2736. if (!rates->minimum_linkrate)
  2737. rates->minimum_linkrate = phy->minimum_linkrate;
  2738. else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
  2739. rates->minimum_linkrate = phy->minimum_linkrate_hw;
  2740. if (!rates->maximum_linkrate)
  2741. rates->maximum_linkrate = phy->maximum_linkrate;
  2742. else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
  2743. rates->maximum_linkrate = phy->maximum_linkrate_hw;
  2744. /* handle expander phys */
  2745. if (phy->identify.sas_address != mrioc->sas_hba.sas_address) {
  2746. phy->minimum_linkrate = rates->minimum_linkrate;
  2747. phy->maximum_linkrate = rates->maximum_linkrate;
  2748. return mpi3mr_expander_phy_control(mrioc, phy,
  2749. SMP_PHY_CONTROL_LINK_RESET);
  2750. }
  2751. /* handle hba phys */
  2752. sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) +
  2753. (mrioc->sas_hba.num_phys *
  2754. sizeof(struct mpi3_sas_io_unit1_phy_data));
  2755. sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL);
  2756. if (!sas_io_unit_pg1) {
  2757. rc = -ENOMEM;
  2758. goto out;
  2759. }
  2760. if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
  2761. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  2762. __FILE__, __LINE__, __func__);
  2763. rc = -ENXIO;
  2764. goto out;
  2765. }
  2766. sas_io_unit_pg1->phy_data[phy->number].max_min_link_rate =
  2767. (rates->minimum_linkrate + (rates->maximum_linkrate << 4));
  2768. if (mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
  2769. ioc_err(mrioc, "failure at %s:%d/%s()!\n",
  2770. __FILE__, __LINE__, __func__);
  2771. rc = -ENXIO;
  2772. goto out;
  2773. }
  2774. /* link reset */
  2775. mpi3mr_transport_phy_reset(phy, 0);
  2776. /* read phy page 0, then update the rates in the sas transport phy */
  2777. if (!mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
  2778. sizeof(struct mpi3_sas_phy_page0),
  2779. MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number) &&
  2780. (ioc_status == MPI3_IOCSTATUS_SUCCESS)) {
  2781. phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
  2782. phy_pg0.programmed_link_rate &
  2783. MPI3_SAS_PRATE_MIN_RATE_MASK);
  2784. phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
  2785. phy_pg0.programmed_link_rate >> 4);
  2786. phy->negotiated_linkrate =
  2787. mpi3mr_convert_phy_link_rate(
  2788. (phy_pg0.negotiated_link_rate &
  2789. MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK)
  2790. >> MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
  2791. }
  2792. out:
  2793. kfree(sas_io_unit_pg1);
  2794. return rc;
  2795. }
  2796. /**
  2797. * mpi3mr_map_smp_buffer - map BSG dma buffer
  2798. * @dev: Generic device reference
  2799. * @buf: BSG buffer pointer
  2800. * @dma_addr: Physical address holder
  2801. * @dma_len: Mapped DMA buffer length.
  2802. * @p: Virtual address holder
  2803. *
  2804. * This function maps the DMAable buffer
  2805. *
  2806. * Return: 0 on success, non-zero on failure
  2807. */
  2808. static int
  2809. mpi3mr_map_smp_buffer(struct device *dev, struct bsg_buffer *buf,
  2810. dma_addr_t *dma_addr, size_t *dma_len, void **p)
  2811. {
  2812. /* Check if the request is split across multiple segments */
  2813. if (buf->sg_cnt > 1) {
  2814. *p = dma_alloc_coherent(dev, buf->payload_len, dma_addr,
  2815. GFP_KERNEL);
  2816. if (!*p)
  2817. return -ENOMEM;
  2818. *dma_len = buf->payload_len;
  2819. } else {
  2820. if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL))
  2821. return -ENOMEM;
  2822. *dma_addr = sg_dma_address(buf->sg_list);
  2823. *dma_len = sg_dma_len(buf->sg_list);
  2824. *p = NULL;
  2825. }
  2826. return 0;
  2827. }
  2828. /**
  2829. * mpi3mr_unmap_smp_buffer - unmap BSG dma buffer
  2830. * @dev: Generic device reference
  2831. * @buf: BSG buffer pointer
  2832. * @dma_addr: Physical address to be unmapped
  2833. * @p: Virtual address
  2834. *
  2835. * This function unmaps the DMAable buffer
  2836. */
  2837. static void
  2838. mpi3mr_unmap_smp_buffer(struct device *dev, struct bsg_buffer *buf,
  2839. dma_addr_t dma_addr, void *p)
  2840. {
  2841. if (p)
  2842. dma_free_coherent(dev, buf->payload_len, p, dma_addr);
  2843. else
  2844. dma_unmap_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL);
  2845. }
  2846. /**
  2847. * mpi3mr_transport_smp_handler - handler for smp passthru
  2848. * @job: BSG job reference
  2849. * @shost: SCSI host object reference
  2850. * @rphy: SAS transport rphy object pointing the expander
  2851. *
  2852. * This is used primarily by smp utils for sending the SMP
  2853. * commands to the expanders attached to the controller
  2854. */
  2855. static void
  2856. mpi3mr_transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
  2857. struct sas_rphy *rphy)
  2858. {
  2859. struct mpi3mr_ioc *mrioc = shost_priv(shost);
  2860. struct mpi3_smp_passthrough_request mpi_request;
  2861. struct mpi3_smp_passthrough_reply mpi_reply;
  2862. int rc;
  2863. void *psge;
  2864. dma_addr_t dma_addr_in;
  2865. dma_addr_t dma_addr_out;
  2866. void *addr_in = NULL;
  2867. void *addr_out = NULL;
  2868. size_t dma_len_in;
  2869. size_t dma_len_out;
  2870. unsigned int reslen = 0;
  2871. u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
  2872. u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
  2873. u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
  2874. u16 ioc_status;
  2875. if (mrioc->reset_in_progress) {
  2876. ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
  2877. rc = -EFAULT;
  2878. goto out;
  2879. }
  2880. rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
  2881. &dma_addr_out, &dma_len_out, &addr_out);
  2882. if (rc)
  2883. goto out;
  2884. if (addr_out)
  2885. sg_copy_to_buffer(job->request_payload.sg_list,
  2886. job->request_payload.sg_cnt, addr_out,
  2887. job->request_payload.payload_len);
  2888. rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->reply_payload,
  2889. &dma_addr_in, &dma_len_in, &addr_in);
  2890. if (rc)
  2891. goto unmap_out;
  2892. memset(&mpi_request, 0, request_sz);
  2893. memset(&mpi_reply, 0, reply_sz);
  2894. mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
  2895. mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
  2896. mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_rphy(mrioc, rphy);
  2897. mpi_request.sas_address = ((rphy) ?
  2898. cpu_to_le64(rphy->identify.sas_address) :
  2899. cpu_to_le64(mrioc->sas_hba.sas_address));
  2900. psge = &mpi_request.request_sge;
  2901. mpi3mr_add_sg_single(psge, sgl_flags, dma_len_out - 4, dma_addr_out);
  2902. psge = &mpi_request.response_sge;
  2903. mpi3mr_add_sg_single(psge, sgl_flags, dma_len_in - 4, dma_addr_in);
  2904. dprint_transport_info(mrioc, "sending SMP request\n");
  2905. rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
  2906. &mpi_reply, reply_sz,
  2907. MPI3MR_INTADMCMD_TIMEOUT, &ioc_status);
  2908. if (rc)
  2909. goto unmap_in;
  2910. dprint_transport_info(mrioc,
  2911. "SMP request completed with ioc_status(0x%04x)\n", ioc_status);
  2912. dprint_transport_info(mrioc,
  2913. "SMP request - reply data transfer size(%d)\n",
  2914. le16_to_cpu(mpi_reply.response_data_length));
  2915. memcpy(job->reply, &mpi_reply, reply_sz);
  2916. job->reply_len = reply_sz;
  2917. reslen = le16_to_cpu(mpi_reply.response_data_length);
  2918. if (addr_in)
  2919. sg_copy_from_buffer(job->reply_payload.sg_list,
  2920. job->reply_payload.sg_cnt, addr_in,
  2921. job->reply_payload.payload_len);
  2922. rc = 0;
  2923. unmap_in:
  2924. mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->reply_payload,
  2925. dma_addr_in, addr_in);
  2926. unmap_out:
  2927. mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
  2928. dma_addr_out, addr_out);
  2929. out:
  2930. bsg_job_done(job, rc, reslen);
  2931. }
  2932. struct sas_function_template mpi3mr_transport_functions = {
  2933. .get_linkerrors = mpi3mr_transport_get_linkerrors,
  2934. .get_enclosure_identifier = mpi3mr_transport_get_enclosure_identifier,
  2935. .get_bay_identifier = mpi3mr_transport_get_bay_identifier,
  2936. .phy_reset = mpi3mr_transport_phy_reset,
  2937. .phy_enable = mpi3mr_transport_phy_enable,
  2938. .set_phy_speed = mpi3mr_transport_phy_speed,
  2939. .smp_handler = mpi3mr_transport_smp_handler,
  2940. };
  2941. struct scsi_transport_template *mpi3mr_transport_template;