You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

xsigo.c 50KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859
  1. /*
  2. * Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. *
  19. * You can also choose to distribute this program under the terms of
  20. * the Unmodified Binary Distribution Licence (as given in the file
  21. * COPYING.UBDL), provided that you have satisfied its requirements.
  22. */
  23. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  24. #include <string.h>
  25. #include <stdio.h>
  26. #include <errno.h>
  27. #include <byteswap.h>
  28. #include <ipxe/version.h>
  29. #include <ipxe/timer.h>
  30. #include <ipxe/malloc.h>
  31. #include <ipxe/iobuf.h>
  32. #include <ipxe/retry.h>
  33. #include <ipxe/process.h>
  34. #include <ipxe/settings.h>
  35. #include <ipxe/infiniband.h>
  36. #include <ipxe/ib_service.h>
  37. #include <ipxe/ib_cmrc.h>
  38. #include <ipxe/if_ether.h>
  39. #include <ipxe/ethernet.h>
  40. #include <ipxe/eoib.h>
  41. #include <ipxe/xsigo.h>
  42. /** @file
  43. *
  44. * Xsigo virtual Ethernet devices
  45. *
  46. */
  47. /** A Xsigo device */
  48. struct xsigo_device {
  49. /** Reference count */
  50. struct refcnt refcnt;
  51. /** Underlying Infiniband device */
  52. struct ib_device *ibdev;
  53. /** List of Xsigo devices */
  54. struct list_head list;
  55. /** Device name */
  56. const char *name;
  57. /** Link opener timer */
  58. struct retry_timer opener;
  59. /** Discovery timer */
  60. struct retry_timer discovery;
  61. /** Discovery management transaction (if any) */
  62. struct ib_mad_transaction *madx;
  63. /** List of configuration managers */
  64. struct list_head managers;
  65. };
  66. /** A Xsigo configuration manager */
  67. struct xsigo_manager {
  68. /** Reference count */
  69. struct refcnt refcnt;
  70. /** Xsigo device */
  71. struct xsigo_device *xdev;
  72. /** List of managers */
  73. struct list_head list;
  74. /** Device name */
  75. char name[16];
  76. /** Manager ID */
  77. struct xsigo_manager_id id;
  78. /** Data transfer interface */
  79. struct interface xfer;
  80. /** Connection timer */
  81. struct retry_timer reopen;
  82. /** Keepalive timer */
  83. struct retry_timer keepalive;
  84. /** Transmission process */
  85. struct process process;
  86. /** Pending transmissions */
  87. unsigned int pending;
  88. /** Transmit sequence number */
  89. uint32_t seq;
  90. /** List of virtual Ethernet devices */
  91. struct list_head nics;
  92. };
  93. /** Configuration manager pending transmissions */
  94. enum xsigo_manager_pending {
  95. /** Send connection request */
  96. XCM_TX_CONNECT = 0x0001,
  97. /** Send registration message */
  98. XCM_TX_REGISTER = 0x0002,
  99. };
  100. /** A Xsigo virtual Ethernet device */
  101. struct xsigo_nic {
  102. /** Configuration manager */
  103. struct xsigo_manager *xcm;
  104. /** List of virtual Ethernet devices */
  105. struct list_head list;
  106. /** Device name */
  107. char name[16];
  108. /** Resource identifier */
  109. union ib_guid resource;
  110. /** MAC address */
  111. uint8_t mac[ETH_ALEN];
  112. /** Network ID */
  113. unsigned long network;
  114. };
  115. /** Configuration manager service ID */
  116. static union ib_guid xcm_service_id = {
  117. .bytes = XCM_SERVICE_ID,
  118. };
  119. /** List of all Xsigo devices */
  120. static LIST_HEAD ( xsigo_devices );
  121. /**
  122. * Free Xsigo device
  123. *
  124. * @v refcnt Reference count
  125. */
  126. static void xsigo_free ( struct refcnt *refcnt ) {
  127. struct xsigo_device *xdev =
  128. container_of ( refcnt, struct xsigo_device, refcnt );
  129. /* Sanity checks */
  130. assert ( ! timer_running ( &xdev->opener ) );
  131. assert ( ! timer_running ( &xdev->discovery ) );
  132. assert ( xdev->madx == NULL );
  133. assert ( list_empty ( &xdev->managers ) );
  134. /* Drop reference to Infiniband device */
  135. ibdev_put ( xdev->ibdev );
  136. /* Free device */
  137. free ( xdev );
  138. }
  139. /**
  140. * Free configuration manager
  141. *
  142. * @v refcnt Reference count
  143. */
  144. static void xcm_free ( struct refcnt *refcnt ) {
  145. struct xsigo_manager *xcm =
  146. container_of ( refcnt, struct xsigo_manager, refcnt );
  147. /* Sanity checks */
  148. assert ( ! timer_running ( &xcm->reopen ) );
  149. assert ( ! timer_running ( &xcm->keepalive ) );
  150. assert ( ! process_running ( &xcm->process ) );
  151. assert ( list_empty ( &xcm->nics ) );
  152. /* Drop reference to Xsigo device */
  153. ref_put ( &xcm->xdev->refcnt );
  154. /* Free manager */
  155. free ( xcm );
  156. }
  157. /****************************************************************************
  158. *
  159. * Virtual Ethernet (XVE) devices
  160. *
  161. ****************************************************************************
  162. */
  163. /**
  164. * Create virtual Ethernet device
  165. *
  166. * @v xcm Configuration manager
  167. * @v resource Resource identifier
  168. * @v mac Ethernet MAC
  169. * @v network Network identifier
  170. * @v name Device name
  171. * @ret rc Return status code
  172. */
  173. static int xve_create ( struct xsigo_manager *xcm, union ib_guid *resource,
  174. const uint8_t *mac, unsigned long network,
  175. unsigned long qkey, const char *name ) {
  176. struct xsigo_device *xdev = xcm->xdev;
  177. struct ib_device *ibdev = xdev->ibdev;
  178. struct xsigo_nic *xve;
  179. struct ib_address_vector broadcast;
  180. int rc;
  181. /* Allocate and initialise structure */
  182. xve = zalloc ( sizeof ( *xve ) );
  183. if ( ! xve ) {
  184. rc = -ENOMEM;
  185. goto err_alloc;
  186. }
  187. xve->xcm = xcm;
  188. snprintf ( xve->name, sizeof ( xve->name ), "%s", name );
  189. memcpy ( &xve->resource, resource, sizeof ( xve->resource ) );
  190. memcpy ( xve->mac, mac, ETH_ALEN );
  191. xve->network = network;
  192. DBGC ( xve, "XVE %s created for %s " IB_GUID_FMT "\n",
  193. xve->name, xcm->name, IB_GUID_ARGS ( resource ) );
  194. DBGC ( xve, "XVE %s is MAC %s on network %ld\n",
  195. xve->name, eth_ntoa ( mac ), network );
  196. /* Construct broadcast address vector */
  197. memset ( &broadcast, 0, sizeof ( broadcast ) );
  198. broadcast.qpn = IB_QPN_BROADCAST;
  199. broadcast.qkey = qkey;
  200. broadcast.gid_present = 1;
  201. broadcast.gid.dwords[0] = htonl ( XVE_PREFIX );
  202. broadcast.gid.words[2] = htons ( ibdev->pkey );
  203. broadcast.gid.dwords[3] = htonl ( network );
  204. /* Create EoIB device */
  205. if ( ( rc = eoib_create ( ibdev, xve->mac, &broadcast,
  206. xve->name ) ) != 0 ) {
  207. DBGC ( xve, "XVE %s could not create EoIB device: %s\n",
  208. xve->name, strerror ( rc ) );
  209. goto err_create;
  210. }
  211. /* Add to list of virtual Ethernet devices. Do this only
  212. * after creating the EoIB device, so that our net device
  213. * notifier won't attempt to send an operational state update
  214. * before we have acknowledged the installation.
  215. */
  216. list_add ( &xve->list, &xcm->nics );
  217. return 0;
  218. list_del ( &xve->list );
  219. err_create:
  220. free ( xve );
  221. err_alloc:
  222. return rc;
  223. }
  224. /**
  225. * Find virtual Ethernet device
  226. *
  227. * @v xcm Configuration manager
  228. * @v resource Resource identifier
  229. * @ret xve Virtual Ethernet device, or NULL
  230. */
  231. static struct xsigo_nic * xve_find ( struct xsigo_manager *xcm,
  232. union ib_guid *resource ) {
  233. struct xsigo_nic *xve;
  234. list_for_each_entry ( xve, &xcm->nics, list ) {
  235. if ( memcmp ( resource, &xve->resource,
  236. sizeof ( *resource ) ) == 0 )
  237. return xve;
  238. }
  239. return NULL;
  240. }
  241. /**
  242. * Destroy virtual Ethernet device
  243. *
  244. * @v xve Virtual Ethernet device
  245. */
  246. static void xve_destroy ( struct xsigo_nic *xve ) {
  247. struct xsigo_manager *xcm = xve->xcm;
  248. struct xsigo_device *xdev = xcm->xdev;
  249. struct ib_device *ibdev = xdev->ibdev;
  250. struct eoib_device *eoib;
  251. /* Destroy corresponding EoIB device, if any */
  252. if ( ( eoib = eoib_find ( ibdev, xve->mac ) ) )
  253. eoib_destroy ( eoib );
  254. /* Remove from list of virtual Ethernet devices */
  255. list_del ( &xve->list );
  256. /* Free virtual Ethernet device */
  257. DBGC ( xve, "XVE %s destroyed\n", xve->name );
  258. free ( xve );
  259. }
  260. /**
  261. * Update virtual Ethernet device MTU
  262. *
  263. * @v xve Virtual Ethernet device
  264. * @v eoib EoIB device
  265. * @v mtu New MTU (excluding Ethernet and EoIB headers)
  266. * @ret rc Return status code
  267. */
  268. static int xve_update_mtu ( struct xsigo_nic *xve, struct eoib_device *eoib,
  269. size_t mtu ) {
  270. struct net_device *netdev = eoib->netdev;
  271. size_t max;
  272. /* Check that we can support this MTU */
  273. max = ( IB_MAX_PAYLOAD_SIZE - ( sizeof ( struct ethhdr ) +
  274. sizeof ( struct eoib_header ) ) );
  275. if ( mtu > max ) {
  276. DBGC ( xve, "XVE %s cannot support MTU %zd (max %zd)\n",
  277. xve->name, mtu, max );
  278. return -ERANGE;
  279. }
  280. /* Update MTU. No need to close/reopen the network device,
  281. * since our Infiniband stack uses a fixed MTU anyway. Note
  282. * that the network device sees the Ethernet frame header but
  283. * not the EoIB header.
  284. */
  285. netdev->max_pkt_len = ( mtu + sizeof ( struct ethhdr ) );
  286. netdev->mtu = mtu;
  287. DBGC ( xve, "XVE %s has MTU %zd\n", xve->name, mtu );
  288. return 0;
  289. }
  290. /**
  291. * Open virtual Ethernet device
  292. *
  293. * @v xve Virtual Ethernet device
  294. * @v eoib EoIB device
  295. * @v open New administrative state
  296. * @ret rc Return status code
  297. */
  298. static int xve_open ( struct xsigo_nic *xve, struct eoib_device *eoib ) {
  299. struct net_device *netdev = eoib->netdev;
  300. int rc;
  301. /* Do nothing if network device is already open */
  302. if ( netdev_is_open ( netdev ) )
  303. return 0;
  304. DBGC ( xve, "XVE %s opening network device\n", xve->name );
  305. /* Open network device */
  306. if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
  307. DBGC ( xve, "XVE %s could not open: %s\n",
  308. xve->name, strerror ( rc ) );
  309. return rc;
  310. }
  311. return 0;
  312. }
  313. /**
  314. * Close virtual Ethernet device
  315. *
  316. * @v xve Virtual Ethernet device
  317. * @v eoib EoIB device
  318. */
  319. static void xve_close ( struct xsigo_nic *xve, struct eoib_device *eoib ) {
  320. struct net_device *netdev = eoib->netdev;
  321. /* Do nothing if network device is already closed */
  322. if ( ! netdev_is_open ( netdev ) )
  323. return;
  324. /* Close network device */
  325. netdev_close ( netdev );
  326. DBGC ( xve, "XVE %s closed network device\n", xve->name );
  327. }
  328. /**
  329. * Update virtual Ethernet device administrative state
  330. *
  331. * @v xve Virtual Ethernet device
  332. * @v eoib EoIB device
  333. * @v open New administrative state
  334. * @ret rc Return status code
  335. */
  336. static int xve_update_state ( struct xsigo_nic *xve, struct eoib_device *eoib,
  337. int open ) {
  338. /* Open or close device, as applicable */
  339. if ( open ) {
  340. return xve_open ( xve, eoib );
  341. } else {
  342. xve_close ( xve, eoib );
  343. return 0;
  344. }
  345. }
  346. /**
  347. * Update gateway (TCA)
  348. *
  349. * @v xve Virtual Ethernet device
  350. * @v eoib EoIB device
  351. * @v av Address vector, or NULL if no gateway
  352. * @ret rc Return status code
  353. */
  354. static int xve_update_tca ( struct xsigo_nic *xve, struct eoib_device *eoib,
  355. struct ib_address_vector *av ) {
  356. /* Update gateway address */
  357. eoib_set_gateway ( eoib, av );
  358. if ( av ) {
  359. DBGC ( xve, "XVE %s has TCA " IB_GID_FMT " data %#lx qkey "
  360. "%#lx\n", xve->name, IB_GID_ARGS ( &av->gid ), av->qpn,
  361. av->qkey );
  362. } else {
  363. DBGC ( xve, "XVE %s has no TCA\n", xve->name );
  364. }
  365. /* The Linux driver will modify the local device's link state
  366. * to reflect the EoIB-to-Ethernet gateway's link state, but
  367. * this seems philosophically incorrect since communication
  368. * within the EoIB broadcast domain still works regardless of
  369. * the state of the gateway.
  370. */
  371. return 0;
  372. }
  373. /****************************************************************************
  374. *
  375. * Server management protocol (XSMP) session messages
  376. *
  377. ****************************************************************************
  378. */
  379. /**
  380. * Get session message name (for debugging)
  381. *
  382. * @v type Message type
  383. * @ret name Message name
  384. */
  385. static const char * xsmp_session_type ( unsigned int type ) {
  386. static char buf[16];
  387. switch ( type ) {
  388. case XSMP_SESSION_TYPE_HELLO: return "HELLO";
  389. case XSMP_SESSION_TYPE_REGISTER: return "REGISTER";
  390. case XSMP_SESSION_TYPE_CONFIRM: return "CONFIRM";
  391. case XSMP_SESSION_TYPE_REJECT: return "REJECT";
  392. case XSMP_SESSION_TYPE_SHUTDOWN: return "SHUTDOWN";
  393. default:
  394. snprintf ( buf, sizeof ( buf ), "UNKNOWN<%d>", type );
  395. return buf;
  396. }
  397. }
  398. /**
  399. * Extract chassis name (for debugging)
  400. *
  401. * @v msg Session message
  402. * @ret chassis Chassis name
  403. */
  404. static const char * xsmp_chassis_name ( struct xsmp_session_message *msg ) {
  405. static char chassis[ sizeof ( msg->chassis ) + 1 /* NUL */ ];
  406. memcpy ( chassis, msg->chassis, sizeof ( msg->chassis ) );
  407. return chassis;
  408. }
  409. /**
  410. * Extract session name (for debugging)
  411. *
  412. * @v msg Session message
  413. * @ret session Session name
  414. */
  415. static const char * xsmp_session_name ( struct xsmp_session_message *msg ) {
  416. static char session[ sizeof ( msg->session ) + 1 /* NUL */ ];
  417. memcpy ( session, msg->session, sizeof ( msg->session ) );
  418. return session;
  419. }
  420. /**
  421. * Send session message
  422. *
  423. * @v xcm Configuration manager
  424. * @v type Message type
  425. * @ret rc Return status code
  426. */
  427. static int xsmp_tx_session ( struct xsigo_manager *xcm, unsigned int type ) {
  428. struct xsigo_device *xdev = xcm->xdev;
  429. struct ib_device *ibdev = xdev->ibdev;
  430. struct xsmp_session_message msg;
  431. int rc;
  432. /* Construct session message */
  433. memset ( &msg, 0, sizeof ( msg ) );
  434. msg.hdr.type = XSMP_TYPE_SESSION;
  435. msg.hdr.len = htons ( sizeof ( msg ) );
  436. msg.hdr.seq = htonl ( ++xcm->seq );
  437. memcpy ( &msg.hdr.src.guid, &ibdev->gid.s.guid,
  438. sizeof ( msg.hdr.src.guid ) );
  439. memcpy ( &msg.hdr.dst.guid, &xcm->id.guid,
  440. sizeof ( msg.hdr.dst.guid ) );
  441. msg.type = type;
  442. msg.len = htons ( sizeof ( msg ) - sizeof ( msg.hdr ) );
  443. msg.os_type = XSIGO_OS_TYPE_GENERIC;
  444. msg.resources = htons ( XSIGO_RESOURCE_XVE |
  445. XSIGO_RESOURCE_NO_HA );
  446. msg.boot = htonl ( XSMP_BOOT_PXE );
  447. DBGCP ( xcm, "XCM %s TX[%d] session %s\n", xcm->name,
  448. ntohl ( msg.hdr.seq ), xsmp_session_type ( msg.type ) );
  449. DBGCP_HDA ( xcm, 0, &msg, sizeof ( msg ) );
  450. /* Send session message */
  451. if ( ( rc = xfer_deliver_raw ( &xcm->xfer, &msg,
  452. sizeof ( msg ) ) ) != 0 ) {
  453. DBGC ( xcm, "XCM %s TX session %s failed: %s\n", xcm->name,
  454. xsmp_session_type ( msg.type ), strerror ( rc ) );
  455. return rc;
  456. }
  457. return 0;
  458. }
  459. /**
  460. * Send registration message
  461. *
  462. * @v xcm Configuration manager
  463. * @ret rc Return status code
  464. */
  465. static inline int xsmp_tx_session_register ( struct xsigo_manager *xcm ) {
  466. DBGC ( xcm, "XCM %s registering with " IB_GUID_FMT "\n",
  467. xcm->name, IB_GUID_ARGS ( &xcm->id.guid ) );
  468. /* Send registration message */
  469. return xsmp_tx_session ( xcm, XSMP_SESSION_TYPE_REGISTER );
  470. }
  471. /**
  472. * Send keepalive message
  473. *
  474. * @v xcm Configuration manager
  475. * @ret rc Return status code
  476. */
  477. static int xsmp_tx_session_hello ( struct xsigo_manager *xcm ) {
  478. /* Send keepalive message */
  479. return xsmp_tx_session ( xcm, XSMP_SESSION_TYPE_HELLO );
  480. }
  481. /**
  482. * Handle received keepalive message
  483. *
  484. * @v xcm Configuration manager
  485. * @v msg Keepalive message
  486. * @ret rc Return status code
  487. */
  488. static int xsmp_rx_session_hello ( struct xsigo_manager *xcm,
  489. struct xsmp_session_message *msg __unused ) {
  490. /* Respond to keepalive message. Note that the XCM doesn't
  491. * seem to actually ever send these.
  492. */
  493. return xsmp_tx_session_hello ( xcm );
  494. }
  495. /**
  496. * Handle received registration confirmation message
  497. *
  498. * @v xcm Configuration manager
  499. * @v msg Registration confirmation message
  500. * @ret rc Return status code
  501. */
  502. static int xsmp_rx_session_confirm ( struct xsigo_manager *xcm,
  503. struct xsmp_session_message *msg ) {
  504. DBGC ( xcm, "XCM %s registered with \"%s\" as \"%s\"\n", xcm->name,
  505. xsmp_chassis_name ( msg ), xsmp_session_name ( msg ) );
  506. return 0;
  507. }
  508. /**
  509. * Handle received registration rejection message
  510. *
  511. * @v xcm Configuration manager
  512. * @v msg Registration confirmation message
  513. * @ret rc Return status code
  514. */
  515. static int xsmp_rx_session_reject ( struct xsigo_manager *xcm,
  516. struct xsmp_session_message *msg ) {
  517. DBGC ( xcm, "XCM %s rejected by \"%s\":\n",
  518. xcm->name, xsmp_chassis_name ( msg ) );
  519. DBGC_HDA ( xcm, 0, msg, sizeof ( *msg ) );
  520. return -EPERM;
  521. }
  522. /**
  523. * Handle received shutdown message
  524. *
  525. * @v xcm Configuration manager
  526. * @v msg Registration confirmation message
  527. * @ret rc Return status code
  528. */
  529. static int xsmp_rx_session_shutdown ( struct xsigo_manager *xcm,
  530. struct xsmp_session_message *msg ) {
  531. DBGC ( xcm, "XCM %s shut down by \"%s\":\n",
  532. xcm->name, xsmp_chassis_name ( msg ) );
  533. DBGC_HDA ( xcm, 0, msg, sizeof ( *msg ) );
  534. return -ENOTCONN;
  535. }
  536. /**
  537. * Handle received session message
  538. *
  539. * @v xcm Configuration manager
  540. * @v msg Session message
  541. * @ret rc Return status code
  542. */
  543. static int xsmp_rx_session ( struct xsigo_manager *xcm,
  544. struct xsmp_session_message *msg ) {
  545. DBGCP ( xcm, "XCM %s RX[%d] session %s\n", xcm->name,
  546. ntohl ( msg->hdr.seq ), xsmp_session_type ( msg->type ) );
  547. DBGCP_HDA ( xcm, 0, msg, sizeof ( *msg ) );
  548. /* Handle message according to type */
  549. switch ( msg->type ) {
  550. case XSMP_SESSION_TYPE_HELLO:
  551. return xsmp_rx_session_hello ( xcm, msg );
  552. case XSMP_SESSION_TYPE_CONFIRM:
  553. return xsmp_rx_session_confirm ( xcm, msg );
  554. case XSMP_SESSION_TYPE_REJECT:
  555. return xsmp_rx_session_reject ( xcm, msg );
  556. case XSMP_SESSION_TYPE_SHUTDOWN:
  557. return xsmp_rx_session_shutdown ( xcm, msg );
  558. default:
  559. DBGC ( xcm, "XCM %s RX[%d] session unexpected %s:\n", xcm->name,
  560. ntohl ( msg->hdr.seq ), xsmp_session_type ( msg->type ));
  561. DBGC_HDA ( xcm, 0, msg, sizeof ( *msg ) );
  562. return -EPROTO;
  563. }
  564. }
  565. /****************************************************************************
  566. *
  567. * Server management protocol (XSMP) virtual Ethernet (XVE) messages
  568. *
  569. ****************************************************************************
  570. */
  571. /**
  572. * Get virtual Ethernet message name (for debugging)
  573. *
  574. * @v type Message type
  575. * @ret name Message name
  576. */
  577. static const char * xsmp_xve_type ( unsigned int type ) {
  578. static char buf[16];
  579. switch ( type ) {
  580. case XSMP_XVE_TYPE_INSTALL: return "INSTALL";
  581. case XSMP_XVE_TYPE_DELETE: return "DELETE";
  582. case XSMP_XVE_TYPE_UPDATE: return "UPDATE";
  583. case XSMP_XVE_TYPE_OPER_UP: return "OPER_UP";
  584. case XSMP_XVE_TYPE_OPER_DOWN: return "OPER_DOWN";
  585. case XSMP_XVE_TYPE_OPER_REQ: return "OPER_REQ";
  586. case XSMP_XVE_TYPE_READY: return "READY";
  587. default:
  588. snprintf ( buf, sizeof ( buf ), "UNKNOWN<%d>", type );
  589. return buf;
  590. }
  591. }
  592. /**
  593. * Send virtual Ethernet message
  594. *
  595. * @v xcm Configuration manager
  596. * @v msg Partial message
  597. * @ret rc Return status code
  598. */
  599. static int xsmp_tx_xve ( struct xsigo_manager *xcm,
  600. struct xsmp_xve_message *msg ) {
  601. struct xsigo_device *xdev = xcm->xdev;
  602. struct ib_device *ibdev = xdev->ibdev;
  603. int rc;
  604. /* Fill in common header fields */
  605. msg->hdr.type = XSMP_TYPE_XVE;
  606. msg->hdr.len = htons ( sizeof ( *msg ) );
  607. msg->hdr.seq = htonl ( ++xcm->seq );
  608. memcpy ( &msg->hdr.src.guid, &ibdev->gid.s.guid,
  609. sizeof ( msg->hdr.src.guid ) );
  610. memcpy ( &msg->hdr.dst.guid, &xcm->id.guid,
  611. sizeof ( msg->hdr.dst.guid ) );
  612. msg->len = htons ( sizeof ( *msg ) - sizeof ( msg->hdr ) );
  613. DBGCP ( xcm, "XCM %s TX[%d] xve %s code %#02x\n", xcm->name,
  614. ntohl ( msg->hdr.seq ), xsmp_xve_type ( msg->type ),
  615. msg->code );
  616. DBGCP_HDA ( xcm, 0, msg, sizeof ( *msg ) );
  617. /* Send virtual Ethernet message */
  618. if ( ( rc = xfer_deliver_raw ( &xcm->xfer, msg,
  619. sizeof ( *msg ) ) ) != 0 ) {
  620. DBGC ( xcm, "XCM %s TX xve %s failed: %s\n", xcm->name,
  621. xsmp_xve_type ( msg->type ), strerror ( rc ) );
  622. return rc;
  623. }
  624. return 0;
  625. }
  626. /**
  627. * Send virtual Ethernet message including current device parameters
  628. *
  629. * @v xcm Configuration manager
  630. * @v msg Partial virtual Ethernet message
  631. * @v xve Virtual Ethernet device
  632. * @v eoib EoIB device
  633. * @ret rc Return status code
  634. */
  635. static int xsmp_tx_xve_params ( struct xsigo_manager *xcm,
  636. struct xsmp_xve_message *msg,
  637. struct xsigo_nic *xve,
  638. struct eoib_device *eoib ) {
  639. struct xsigo_device *xdev = xcm->xdev;
  640. struct ib_device *ibdev = xdev->ibdev;
  641. struct net_device *netdev = eoib->netdev;
  642. /* Set successful response code */
  643. msg->code = 0;
  644. /* Include network identifier, MTU, and current HCA parameters */
  645. msg->network = htonl ( xve->network );
  646. msg->mtu = htons ( netdev->max_pkt_len - sizeof ( struct ethhdr ) );
  647. msg->hca.prefix_le.qword = bswap_64 ( ibdev->gid.s.prefix.qword );
  648. msg->hca.pkey = htons ( ibdev->pkey );
  649. msg->hca.qkey = msg->tca.qkey;
  650. if ( eoib->qp ) {
  651. msg->hca.data = htonl ( eoib->qp->ext_qpn );
  652. msg->hca.qkey = htons ( eoib->qp->qkey );
  653. }
  654. /* The message type field is (ab)used to return the current
  655. * operational status.
  656. */
  657. if ( msg->type == XSMP_XVE_TYPE_OPER_REQ ) {
  658. msg->type = ( netdev_is_open ( netdev ) ?
  659. XSMP_XVE_TYPE_OPER_UP : XSMP_XVE_TYPE_OPER_DOWN );
  660. }
  661. /* Send message */
  662. DBGC ( xve, "XVE %s network %d MTU %d ctrl %#x data %#x qkey %#04x "
  663. "%s\n", xve->name, ntohl ( msg->network ), ntohs ( msg->mtu ),
  664. ntohl ( msg->hca.ctrl ), ntohl ( msg->hca.data ),
  665. ntohs ( msg->hca.qkey ), xsmp_xve_type ( msg->type ) );
  666. return xsmp_tx_xve ( xcm, msg );
  667. }
  668. /**
  669. * Send virtual Ethernet error response
  670. *
  671. * @v xcm Configuration manager
  672. * @v msg Partial virtual Ethernet message
  673. * @ret rc Return status code
  674. */
  675. static inline int xsmp_tx_xve_nack ( struct xsigo_manager *xcm,
  676. struct xsmp_xve_message *msg ) {
  677. /* Set error response code. (There aren't any meaningful
  678. * detailed response codes defined by the wire protocol.)
  679. */
  680. msg->code = XSMP_XVE_CODE_ERROR;
  681. /* Send message */
  682. return xsmp_tx_xve ( xcm, msg );
  683. }
  684. /**
  685. * Send virtual Ethernet notification
  686. *
  687. * @v xcm Configuration manager
  688. * @v type Message type
  689. * @v xve Virtual Ethernet device
  690. * @v eoib EoIB device
  691. * @ret rc Return status code
  692. */
  693. static int xsmp_tx_xve_notify ( struct xsigo_manager *xcm,
  694. unsigned int type,
  695. struct xsigo_nic *xve,
  696. struct eoib_device *eoib ) {
  697. struct xsmp_xve_message msg;
  698. /* Construct message */
  699. memset ( &msg, 0, sizeof ( msg ) );
  700. msg.type = type;
  701. memcpy ( &msg.resource, &xve->resource, sizeof ( msg.resource ) );
  702. /* Send message */
  703. return xsmp_tx_xve_params ( xcm, &msg, xve, eoib );
  704. }
  705. /**
  706. * Send virtual Ethernet current operational state
  707. *
  708. * @v xcm Configuration manager
  709. * @v xve Virtual Ethernet device
  710. * @v eoib EoIB device
  711. * @ret rc Return status code
  712. */
  713. static inline int xsmp_tx_xve_oper ( struct xsigo_manager *xcm,
  714. struct xsigo_nic *xve,
  715. struct eoib_device *eoib ) {
  716. /* Send notification */
  717. return xsmp_tx_xve_notify ( xcm, XSMP_XVE_TYPE_OPER_REQ, xve, eoib );
  718. }
  719. /**
  720. * Handle received virtual Ethernet modification message
  721. *
  722. * @v xcm Configuration manager
  723. * @v msg Virtual Ethernet message
  724. * @v update Update bitmask
  725. * @ret rc Return status code
  726. */
  727. static int xsmp_rx_xve_modify ( struct xsigo_manager *xcm,
  728. struct xsmp_xve_message *msg,
  729. unsigned int update ) {
  730. struct xsigo_device *xdev = xcm->xdev;
  731. struct ib_device *ibdev = xdev->ibdev;
  732. struct xsigo_nic *xve;
  733. struct eoib_device *eoib;
  734. struct ib_address_vector tca;
  735. size_t mtu;
  736. int rc;
  737. /* Avoid returning uninitialised HCA parameters in response */
  738. memset ( &msg->hca, 0, sizeof ( msg->hca ) );
  739. /* Find virtual Ethernet device */
  740. xve = xve_find ( xcm, &msg->resource );
  741. if ( ! xve ) {
  742. DBGC ( xcm, "XCM %s unrecognised resource " IB_GUID_FMT "\n",
  743. xcm->name, IB_GUID_ARGS ( &msg->resource ) );
  744. rc = -ENOENT;
  745. goto err_no_xve;
  746. }
  747. /* Find corresponding EoIB device */
  748. eoib = eoib_find ( ibdev, xve->mac );
  749. if ( ! eoib ) {
  750. DBGC ( xve, "XVE %s has no EoIB device\n", xve->name );
  751. rc = -EPIPE;
  752. goto err_no_eoib;
  753. }
  754. /* The Xsigo management software fails to create the EoIB
  755. * multicast group. This is a fundamental design flaw.
  756. */
  757. eoib_force_group_creation ( eoib );
  758. /* Extract modifiable parameters. Note that the TCA GID is
  759. * erroneously transmitted as little-endian.
  760. */
  761. mtu = ntohs ( msg->mtu );
  762. tca.qpn = ntohl ( msg->tca.data );
  763. tca.qkey = ntohs ( msg->tca.qkey );
  764. tca.gid_present = 1;
  765. tca.gid.s.prefix.qword = bswap_64 ( msg->tca.prefix_le.qword );
  766. tca.gid.s.guid.qword = bswap_64 ( msg->guid_le.qword );
  767. /* Update MTU, if applicable */
  768. if ( ( update & XSMP_XVE_UPDATE_MTU ) &&
  769. ( ( rc = xve_update_mtu ( xve, eoib, mtu ) ) != 0 ) )
  770. goto err_mtu;
  771. update &= ~XSMP_XVE_UPDATE_MTU;
  772. /* Update admin state, if applicable */
  773. if ( ( update & XSMP_XVE_UPDATE_STATE ) &&
  774. ( ( rc = xve_update_state ( xve, eoib, msg->state ) ) != 0 ) )
  775. goto err_state;
  776. update &= ~XSMP_XVE_UPDATE_STATE;
  777. /* Remove gateway, if applicable */
  778. if ( ( update & XSMP_XVE_UPDATE_GW_DOWN ) &&
  779. ( ( rc = xve_update_tca ( xve, eoib, NULL ) ) != 0 ) )
  780. goto err_gw_down;
  781. update &= ~XSMP_XVE_UPDATE_GW_DOWN;
  782. /* Update gateway, if applicable */
  783. if ( ( update & XSMP_XVE_UPDATE_GW_CHANGE ) &&
  784. ( ( rc = xve_update_tca ( xve, eoib, &tca ) ) != 0 ) )
  785. goto err_gw_change;
  786. update &= ~XSMP_XVE_UPDATE_GW_CHANGE;
  787. /* Warn about unexpected updates */
  788. if ( update ) {
  789. DBGC ( xve, "XVE %s unrecognised update(s) %#08x\n",
  790. xve->name, update );
  791. }
  792. xsmp_tx_xve_params ( xcm, msg, xve, eoib );
  793. return 0;
  794. err_gw_change:
  795. err_gw_down:
  796. err_state:
  797. err_mtu:
  798. err_no_eoib:
  799. err_no_xve:
  800. /* Send NACK */
  801. xsmp_tx_xve_nack ( xcm, msg );
  802. return rc;
  803. }
  804. /**
  805. * Handle received virtual Ethernet installation message
  806. *
  807. * @v xcm Configuration manager
  808. * @v msg Virtual Ethernet message
  809. * @ret rc Return status code
  810. */
  811. static int xsmp_rx_xve_install ( struct xsigo_manager *xcm,
  812. struct xsmp_xve_message *msg ) {
  813. union {
  814. struct xsmp_xve_mac msg;
  815. uint8_t raw[ETH_ALEN];
  816. } mac;
  817. char name[ sizeof ( msg->name ) + 1 /* NUL */ ];
  818. unsigned long network;
  819. unsigned long qkey;
  820. unsigned int update;
  821. int rc;
  822. /* Demangle MAC address (which is erroneously transmitted as
  823. * little-endian).
  824. */
  825. mac.msg.high = bswap_16 ( msg->mac_le.high );
  826. mac.msg.low = bswap_32 ( msg->mac_le.low );
  827. /* Extract interface name (which may not be NUL-terminated) */
  828. memcpy ( name, msg->name, ( sizeof ( name ) - 1 /* NUL */ ) );
  829. name[ sizeof ( name ) - 1 /* NUL */ ] = '\0';
  830. /* Extract remaining message parameters */
  831. network = ntohl ( msg->network );
  832. qkey = ntohs ( msg->tca.qkey );
  833. DBGC2 ( xcm, "XCM %s " IB_GUID_FMT " install \"%s\" %s net %ld qkey "
  834. "%#lx\n", xcm->name, IB_GUID_ARGS ( &msg->resource ), name,
  835. eth_ntoa ( mac.raw ), network, qkey );
  836. /* Create virtual Ethernet device, if applicable */
  837. if ( ( xve_find ( xcm, &msg->resource ) == NULL ) &&
  838. ( ( rc = xve_create ( xcm, &msg->resource, mac.raw, network,
  839. qkey, name ) ) != 0 ) )
  840. goto err_create;
  841. /* Handle remaining parameters as for a modification message */
  842. update = XSMP_XVE_UPDATE_MTU;
  843. if ( msg->uplink == XSMP_XVE_UPLINK )
  844. update |= XSMP_XVE_UPDATE_GW_CHANGE;
  845. return xsmp_rx_xve_modify ( xcm, msg, update );
  846. err_create:
  847. /* Send NACK */
  848. xsmp_tx_xve_nack ( xcm, msg );
  849. return rc;
  850. }
  851. /**
  852. * Handle received virtual Ethernet deletion message
  853. *
  854. * @v xcm Configuration manager
  855. * @v msg Virtual Ethernet message
  856. * @ret rc Return status code
  857. */
  858. static int xsmp_rx_xve_delete ( struct xsigo_manager *xcm,
  859. struct xsmp_xve_message *msg ) {
  860. struct xsigo_nic *xve;
  861. DBGC2 ( xcm, "XCM %s " IB_GUID_FMT " delete\n",
  862. xcm->name, IB_GUID_ARGS ( &msg->resource ) );
  863. /* Destroy virtual Ethernet device (if any) */
  864. if ( ( xve = xve_find ( xcm, &msg->resource ) ) )
  865. xve_destroy ( xve );
  866. /* Send ACK */
  867. msg->code = 0;
  868. xsmp_tx_xve ( xcm, msg );
  869. return 0;
  870. }
  871. /**
  872. * Handle received virtual Ethernet update message
  873. *
  874. * @v xcm Configuration manager
  875. * @v msg Virtual Ethernet message
  876. * @ret rc Return status code
  877. */
  878. static int xsmp_rx_xve_update ( struct xsigo_manager *xcm,
  879. struct xsmp_xve_message *msg ) {
  880. unsigned int update = ntohl ( msg->update );
  881. DBGC2 ( xcm, "XCM %s " IB_GUID_FMT " update (%08x)\n",
  882. xcm->name, IB_GUID_ARGS ( &msg->resource ), update );
  883. /* Handle as a modification message */
  884. return xsmp_rx_xve_modify ( xcm, msg, update );
  885. }
  886. /**
  887. * Handle received virtual Ethernet operational request message
  888. *
  889. * @v xcm Configuration manager
  890. * @v msg Virtual Ethernet message
  891. * @ret rc Return status code
  892. */
  893. static int xsmp_rx_xve_oper_req ( struct xsigo_manager *xcm,
  894. struct xsmp_xve_message *msg ) {
  895. DBGC2 ( xcm, "XCM %s " IB_GUID_FMT " operational request\n",
  896. xcm->name, IB_GUID_ARGS ( &msg->resource ) );
  897. /* Handle as a nullipotent modification message */
  898. return xsmp_rx_xve_modify ( xcm, msg, 0 );
  899. }
  900. /**
  901. * Handle received virtual Ethernet readiness message
  902. *
  903. * @v xcm Configuration manager
  904. * @v msg Virtual Ethernet message
  905. * @ret rc Return status code
  906. */
  907. static int xsmp_rx_xve_ready ( struct xsigo_manager *xcm,
  908. struct xsmp_xve_message *msg ) {
  909. int rc;
  910. DBGC2 ( xcm, "XCM %s " IB_GUID_FMT " ready\n",
  911. xcm->name, IB_GUID_ARGS ( &msg->resource ) );
  912. /* Handle as a nullipotent modification message */
  913. if ( ( rc = xsmp_rx_xve_modify ( xcm, msg, 0 ) ) != 0 )
  914. return rc;
  915. /* Send an unsolicited operational state update, since there
  916. * is no other way to convey the current operational state.
  917. */
  918. msg->type = XSMP_XVE_TYPE_OPER_REQ;
  919. if ( ( rc = xsmp_rx_xve_modify ( xcm, msg, 0 ) ) != 0 )
  920. return rc;
  921. return 0;
  922. }
  923. /**
  924. * Handle received virtual Ethernet message
  925. *
  926. * @v xcm Configuration manager
  927. * @v msg Virtual Ethernet message
  928. * @ret rc Return status code
  929. */
  930. static int xsmp_rx_xve ( struct xsigo_manager *xcm,
  931. struct xsmp_xve_message *msg ) {
  932. DBGCP ( xcm, "XCM %s RX[%d] xve %s\n", xcm->name,
  933. ntohl ( msg->hdr.seq ), xsmp_xve_type ( msg->type ) );
  934. DBGCP_HDA ( xcm, 0, msg, sizeof ( *msg ) );
  935. /* Handle message according to type */
  936. switch ( msg->type ) {
  937. case XSMP_XVE_TYPE_INSTALL:
  938. return xsmp_rx_xve_install ( xcm, msg );
  939. case XSMP_XVE_TYPE_DELETE:
  940. return xsmp_rx_xve_delete ( xcm, msg );
  941. case XSMP_XVE_TYPE_UPDATE:
  942. return xsmp_rx_xve_update ( xcm, msg );
  943. case XSMP_XVE_TYPE_OPER_REQ:
  944. return xsmp_rx_xve_oper_req ( xcm, msg );
  945. case XSMP_XVE_TYPE_READY:
  946. return xsmp_rx_xve_ready ( xcm, msg );
  947. default:
  948. DBGC ( xcm, "XCM %s RX[%d] xve unexpected %s:\n", xcm->name,
  949. ntohl ( msg->hdr.seq ), xsmp_xve_type ( msg->type ) );
  950. DBGC_HDA ( xcm, 0, msg, sizeof ( *msg ) );
  951. return -EPROTO;
  952. }
  953. }
  954. /****************************************************************************
  955. *
  956. * Configuration managers (XCM)
  957. *
  958. ****************************************************************************
  959. */
  960. /**
  961. * Close configuration manager connection
  962. *
  963. * @v xcm Configuration manager
  964. * @v rc Reason for close
  965. */
  966. static void xcm_close ( struct xsigo_manager *xcm, int rc ) {
  967. DBGC ( xcm, "XCM %s closed: %s\n", xcm->name, strerror ( rc ) );
  968. /* Stop transmission process */
  969. process_del ( &xcm->process );
  970. /* Stop keepalive timer */
  971. stop_timer ( &xcm->keepalive );
  972. /* Restart data transfer interface */
  973. intf_restart ( &xcm->xfer, rc );
  974. /* Schedule reconnection attempt */
  975. start_timer ( &xcm->reopen );
  976. }
  977. /**
  978. * Send data to configuration manager
  979. *
  980. * @v xcm Configuration manager
  981. */
  982. static void xcm_step ( struct xsigo_manager *xcm ) {
  983. int rc;
  984. /* Do nothing unless we have something to send */
  985. if ( ! xcm->pending )
  986. return;
  987. /* Send (empty) connection request, if applicable */
  988. if ( xcm->pending & XCM_TX_CONNECT ) {
  989. if ( ( rc = xfer_deliver_raw ( &xcm->xfer, NULL, 0 ) ) != 0 ) {
  990. DBGC ( xcm, "XCM %s could not send connection request: "
  991. "%s\n", xcm->name, strerror ( rc ) );
  992. goto err;
  993. }
  994. xcm->pending &= ~XCM_TX_CONNECT;
  995. return;
  996. }
  997. /* Wait until data transfer interface is connected */
  998. if ( ! xfer_window ( &xcm->xfer ) )
  999. return;
  1000. /* Send registration message, if applicable */
  1001. if ( xcm->pending & XCM_TX_REGISTER ) {
  1002. if ( ( rc = xsmp_tx_session_register ( xcm ) ) != 0 )
  1003. goto err;
  1004. xcm->pending &= ~XCM_TX_REGISTER;
  1005. return;
  1006. }
  1007. return;
  1008. err:
  1009. xcm_close ( xcm, rc );
  1010. }
  1011. /**
  1012. * Receive data from configuration manager
  1013. *
  1014. * @v xcm Configuration manager
  1015. * @v iobuf I/O buffer
  1016. * @v meta Data transfer metadata
  1017. * @ret rc Return status code
  1018. */
  1019. static int xcm_deliver ( struct xsigo_manager *xcm, struct io_buffer *iobuf,
  1020. struct xfer_metadata *meta __unused ) {
  1021. union xsmp_message *msg;
  1022. size_t len = iob_len ( iobuf );
  1023. int rc;
  1024. /* Sanity check */
  1025. if ( len < sizeof ( msg->hdr ) ) {
  1026. DBGC ( xcm, "XCM %s underlength message:\n", xcm->name );
  1027. DBGC_HDA ( xcm, 0, iobuf->data, iob_len ( iobuf ) );
  1028. rc = -EPROTO;
  1029. goto out;
  1030. }
  1031. msg = iobuf->data;
  1032. /* Handle message according to type */
  1033. if ( ! msg->hdr.type ) {
  1034. /* Ignore unused communication manager private data blocks */
  1035. rc = 0;
  1036. } else if ( ( msg->hdr.type == XSMP_TYPE_SESSION ) &&
  1037. ( len >= sizeof ( msg->sess ) ) ) {
  1038. /* Session message */
  1039. rc = xsmp_rx_session ( xcm, &msg->sess );
  1040. } else if ( ( msg->hdr.type == XSMP_TYPE_XVE ) &&
  1041. ( len >= sizeof ( msg->xve ) ) ) {
  1042. /* Virtual Ethernet message */
  1043. xsmp_rx_xve ( xcm, &msg->xve );
  1044. /* Virtual Ethernet message errors are non-fatal */
  1045. rc = 0;
  1046. } else {
  1047. /* Unknown message */
  1048. DBGC ( xcm, "XCM %s unexpected message type %d:\n",
  1049. xcm->name, msg->hdr.type );
  1050. DBGC_HDA ( xcm, 0, iobuf->data, iob_len ( iobuf ) );
  1051. rc = -EPROTO;
  1052. }
  1053. out:
  1054. free_iob ( iobuf );
  1055. if ( rc != 0 )
  1056. xcm_close ( xcm, rc );
  1057. return rc;
  1058. }
  1059. /** Configuration manager data transfer interface operations */
  1060. static struct interface_operation xcm_xfer_op[] = {
  1061. INTF_OP ( xfer_deliver, struct xsigo_manager *, xcm_deliver ),
  1062. INTF_OP ( xfer_window_changed, struct xsigo_manager *, xcm_step ),
  1063. INTF_OP ( intf_close, struct xsigo_manager *, xcm_close ),
  1064. };
  1065. /** Configuration manager data transfer interface descriptor */
  1066. static struct interface_descriptor xcm_xfer_desc =
  1067. INTF_DESC ( struct xsigo_manager, xfer, xcm_xfer_op );
  1068. /** Configuration manager process descriptor */
  1069. static struct process_descriptor xcm_process_desc =
  1070. PROC_DESC_ONCE ( struct xsigo_manager, process, xcm_step );
  1071. /**
  1072. * Handle configuration manager connection timer expiry
  1073. *
  1074. * @v timer Connection timer
  1075. * @v fail Failure indicator
  1076. */
  1077. static void xcm_reopen ( struct retry_timer *timer, int fail __unused ) {
  1078. struct xsigo_manager *xcm =
  1079. container_of ( timer, struct xsigo_manager, reopen );
  1080. struct xsigo_device *xdev = xcm->xdev;
  1081. struct ib_device *ibdev = xdev->ibdev;
  1082. union ib_gid gid;
  1083. int rc;
  1084. /* Stop transmission process */
  1085. process_del ( &xcm->process );
  1086. /* Stop keepalive timer */
  1087. stop_timer ( &xcm->keepalive );
  1088. /* Restart data transfer interface */
  1089. intf_restart ( &xcm->xfer, -ECANCELED );
  1090. /* Reset sequence number */
  1091. xcm->seq = 0;
  1092. /* Construct GID */
  1093. memcpy ( &gid.s.prefix, &ibdev->gid.s.prefix, sizeof ( gid.s.prefix ) );
  1094. memcpy ( &gid.s.guid, &xcm->id.guid, sizeof ( gid.s.guid ) );
  1095. DBGC ( xcm, "XCM %s connecting to " IB_GID_FMT "\n",
  1096. xcm->name, IB_GID_ARGS ( &gid ) );
  1097. /* Open CMRC connection */
  1098. if ( ( rc = ib_cmrc_open ( &xcm->xfer, ibdev, &gid,
  1099. &xcm_service_id, xcm->name ) ) != 0 ) {
  1100. DBGC ( xcm, "XCM %s could not open CMRC connection: %s\n",
  1101. xcm->name, strerror ( rc ) );
  1102. start_timer ( &xcm->reopen );
  1103. return;
  1104. }
  1105. /* Schedule transmissions */
  1106. xcm->pending |= ( XCM_TX_CONNECT | XCM_TX_REGISTER );
  1107. process_add ( &xcm->process );
  1108. /* Start keepalive timer */
  1109. start_timer_fixed ( &xcm->keepalive, XSIGO_KEEPALIVE_INTERVAL );
  1110. return;
  1111. }
  1112. /**
  1113. * Handle configuration manager keepalive timer expiry
  1114. *
  1115. * @v timer Connection timer
  1116. * @v fail Failure indicator
  1117. */
  1118. static void xcm_keepalive ( struct retry_timer *timer, int fail __unused ) {
  1119. struct xsigo_manager *xcm =
  1120. container_of ( timer, struct xsigo_manager, keepalive );
  1121. int rc;
  1122. /* Send keepalive message. The server won't actually respond
  1123. * to these, but it gives the RC queue pair a chance to
  1124. * complain if it doesn't ever at least get an ACK.
  1125. */
  1126. if ( ( rc = xsmp_tx_session_hello ( xcm ) ) != 0 ) {
  1127. xcm_close ( xcm, rc );
  1128. return;
  1129. }
  1130. /* Restart keepalive timer */
  1131. start_timer_fixed ( &xcm->keepalive, XSIGO_KEEPALIVE_INTERVAL );
  1132. }
  1133. /**
  1134. * Create configuration manager
  1135. *
  1136. * @v xsigo Xsigo device
  1137. * @v id Configuration manager ID
  1138. * @ret rc Return status code
  1139. */
  1140. static int xcm_create ( struct xsigo_device *xdev,
  1141. struct xsigo_manager_id *id ) {
  1142. struct xsigo_manager *xcm;
  1143. /* Allocate and initialise structure */
  1144. xcm = zalloc ( sizeof ( *xcm ) );
  1145. if ( ! xcm )
  1146. return -ENOMEM;
  1147. ref_init ( &xcm->refcnt, xcm_free );
  1148. xcm->xdev = xdev;
  1149. ref_get ( &xcm->xdev->refcnt );
  1150. snprintf ( xcm->name, sizeof ( xcm->name ), "%s:xcm-%d",
  1151. xdev->name, ntohs ( id->lid ) );
  1152. memcpy ( &xcm->id, id, sizeof ( xcm->id ) );
  1153. intf_init ( &xcm->xfer, &xcm_xfer_desc, &xcm->refcnt );
  1154. timer_init ( &xcm->keepalive, xcm_keepalive, &xcm->refcnt );
  1155. timer_init ( &xcm->reopen, xcm_reopen, &xcm->refcnt );
  1156. process_init_stopped ( &xcm->process, &xcm_process_desc, &xcm->refcnt );
  1157. INIT_LIST_HEAD ( &xcm->nics );
  1158. /* Start timer to open connection */
  1159. start_timer_nodelay ( &xcm->reopen );
  1160. /* Add to list of managers and transfer reference to list */
  1161. list_add ( &xcm->list, &xdev->managers );
  1162. DBGC ( xcm, "XCM %s created for " IB_GUID_FMT " (LID %d)\n", xcm->name,
  1163. IB_GUID_ARGS ( &xcm->id.guid ), ntohs ( id->lid ) );
  1164. return 0;
  1165. }
  1166. /**
  1167. * Find configuration manager
  1168. *
  1169. * @v xsigo Xsigo device
  1170. * @v id Configuration manager ID
  1171. * @ret xcm Configuration manager, or NULL
  1172. */
  1173. static struct xsigo_manager * xcm_find ( struct xsigo_device *xdev,
  1174. struct xsigo_manager_id *id ) {
  1175. struct xsigo_manager *xcm;
  1176. union ib_guid *guid = &id->guid;
  1177. /* Find configuration manager */
  1178. list_for_each_entry ( xcm, &xdev->managers, list ) {
  1179. if ( memcmp ( guid, &xcm->id.guid, sizeof ( *guid ) ) == 0 )
  1180. return xcm;
  1181. }
  1182. return NULL;
  1183. }
  1184. /**
  1185. * Destroy configuration manager
  1186. *
  1187. * @v xcm Configuration manager
  1188. */
  1189. static void xcm_destroy ( struct xsigo_manager *xcm ) {
  1190. struct xsigo_nic *xve;
  1191. /* Remove all EoIB NICs */
  1192. while ( ( xve = list_first_entry ( &xcm->nics, struct xsigo_nic,
  1193. list ) ) ) {
  1194. xve_destroy ( xve );
  1195. }
  1196. /* Stop transmission process */
  1197. process_del ( &xcm->process );
  1198. /* Stop timers */
  1199. stop_timer ( &xcm->keepalive );
  1200. stop_timer ( &xcm->reopen );
  1201. /* Shut down data transfer interface */
  1202. intf_shutdown ( &xcm->xfer, 0 );
  1203. /* Remove from list of managers and drop list's reference */
  1204. DBGC ( xcm, "XCM %s destroyed\n", xcm->name );
  1205. list_del ( &xcm->list );
  1206. ref_put ( &xcm->refcnt );
  1207. }
  1208. /**
  1209. * Synchronise list of configuration managers
  1210. *
  1211. * @v xdev Xsigo device
  1212. * @v ids List of manager IDs
  1213. * @v count Number of manager IDs
  1214. * @ret rc Return status code
  1215. */
  1216. static int xcm_list ( struct xsigo_device *xdev, struct xsigo_manager_id *ids,
  1217. unsigned int count ) {
  1218. struct xsigo_manager_id *id;
  1219. struct xsigo_manager *xcm;
  1220. struct xsigo_manager *tmp;
  1221. struct list_head list;
  1222. unsigned int i;
  1223. int rc;
  1224. /* Create list of managers to be retained */
  1225. INIT_LIST_HEAD ( &list );
  1226. for ( i = 0, id = ids ; i < count ; i++, id++ ) {
  1227. if ( ( xcm = xcm_find ( xdev, id ) ) ) {
  1228. list_del ( &xcm->list );
  1229. list_add_tail ( &xcm->list, &list );
  1230. }
  1231. }
  1232. /* Destroy any managers not in the list */
  1233. list_for_each_entry_safe ( xcm, tmp, &xdev->managers, list )
  1234. xcm_destroy ( xcm );
  1235. list_splice ( &list, &xdev->managers );
  1236. /* Create any new managers in the list, and force reconnection
  1237. * for any changed LIDs.
  1238. */
  1239. for ( i = 0, id = ids ; i < count ; i++, id++ ) {
  1240. if ( ( xcm = xcm_find ( xdev, id ) ) ) {
  1241. if ( xcm->id.lid != id->lid )
  1242. start_timer_nodelay ( &xcm->reopen );
  1243. continue;
  1244. }
  1245. if ( ( rc = xcm_create ( xdev, id ) ) != 0 ) {
  1246. DBGC ( xdev, "XDEV %s could not create manager: %s\n",
  1247. xdev->name, strerror ( rc ) );
  1248. return rc;
  1249. }
  1250. }
  1251. return 0;
  1252. }
  1253. /****************************************************************************
  1254. *
  1255. * Configuration manager discovery
  1256. *
  1257. ****************************************************************************
  1258. */
  1259. /** A stage of discovery */
  1260. struct xsigo_discovery {
  1261. /** Name */
  1262. const char *name;
  1263. /** Management transaction operations */
  1264. struct ib_mad_transaction_operations op;
  1265. };
  1266. /**
  1267. * Handle configuration manager lookup completion
  1268. *
  1269. * @v ibdev Infiniband device
  1270. * @v mi Management interface
  1271. * @v madx Management transaction
  1272. * @v rc Status code
  1273. * @v mad Received MAD (or NULL on error)
  1274. * @v av Source address vector (or NULL on error)
  1275. */
  1276. static void xsigo_xcm_complete ( struct ib_device *ibdev,
  1277. struct ib_mad_interface *mi __unused,
  1278. struct ib_mad_transaction *madx,
  1279. int rc, union ib_mad *mad,
  1280. struct ib_address_vector *av __unused ) {
  1281. struct xsigo_device *xdev = ib_madx_get_ownerdata ( madx );
  1282. union xsigo_mad *xsmad = container_of ( mad, union xsigo_mad, mad );
  1283. struct xsigo_managers_reply *reply = &xsmad->reply;
  1284. /* Check for failures */
  1285. if ( ( rc == 0 ) && ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ) )
  1286. rc = -ENODEV;
  1287. if ( rc != 0 ) {
  1288. DBGC ( xdev, "XDEV %s manager lookup failed: %s\n",
  1289. xdev->name, strerror ( rc ) );
  1290. goto out;
  1291. }
  1292. /* Sanity checks */
  1293. if ( reply->count > ( sizeof ( reply->manager ) /
  1294. sizeof ( reply->manager[0] ) ) ) {
  1295. DBGC ( xdev, "XDEV %s has too many managers (%d)\n",
  1296. xdev->name, reply->count );
  1297. goto out;
  1298. }
  1299. /* Synchronise list of managers */
  1300. if ( ( rc = xcm_list ( xdev, reply->manager, reply->count ) ) != 0 )
  1301. goto out;
  1302. /* Report an empty list of managers */
  1303. if ( reply->count == 0 )
  1304. DBGC ( xdev, "XDEV %s has no managers\n", xdev->name );
  1305. /* Delay next discovery attempt */
  1306. start_timer_fixed ( &xdev->discovery, XSIGO_DISCOVERY_SUCCESS_DELAY );
  1307. out:
  1308. /* Destroy the completed transaction */
  1309. ib_destroy_madx ( ibdev, ibdev->gsi, madx );
  1310. xdev->madx = NULL;
  1311. }
  1312. /** Configuration manager lookup discovery stage */
  1313. static struct xsigo_discovery xsigo_xcm_discovery = {
  1314. .name = "manager",
  1315. .op = {
  1316. .complete = xsigo_xcm_complete,
  1317. },
  1318. };
  1319. /**
  1320. * Handle directory service lookup completion
  1321. *
  1322. * @v ibdev Infiniband device
  1323. * @v mi Management interface
  1324. * @v madx Management transaction
  1325. * @v rc Status code
  1326. * @v mad Received MAD (or NULL on error)
  1327. * @v av Source address vector (or NULL on error)
  1328. */
  1329. static void xsigo_xds_complete ( struct ib_device *ibdev,
  1330. struct ib_mad_interface *mi __unused,
  1331. struct ib_mad_transaction *madx,
  1332. int rc, union ib_mad *mad,
  1333. struct ib_address_vector *av __unused ) {
  1334. struct xsigo_device *xdev = ib_madx_get_ownerdata ( madx );
  1335. union xsigo_mad *xsmad = container_of ( mad, union xsigo_mad, mad );
  1336. struct xsigo_managers_request *request = &xsmad->request;
  1337. struct ib_service_record *svc;
  1338. struct ib_address_vector dest;
  1339. union ib_guid *guid;
  1340. /* Allow for reuse of transaction pointer */
  1341. xdev->madx = NULL;
  1342. /* Check for failures */
  1343. if ( ( rc == 0 ) && ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ) )
  1344. rc = -ENODEV;
  1345. if ( rc != 0 ) {
  1346. DBGC ( xdev, "XDEV %s directory lookup failed: %s\n",
  1347. xdev->name, strerror ( rc ) );
  1348. goto out;
  1349. }
  1350. /* Construct address vector */
  1351. memset ( &dest, 0, sizeof ( dest ) );
  1352. svc = &mad->sa.sa_data.service_record;
  1353. dest.lid = ntohs ( svc->data16[0] );
  1354. dest.sl = ibdev->sm_sl;
  1355. dest.qpn = IB_QPN_GSI;
  1356. dest.qkey = IB_QKEY_GSI;
  1357. guid = ( ( union ib_guid * ) &svc->data64[0] );
  1358. DBGC2 ( xdev, "XDEV %s found directory at LID %d GUID " IB_GUID_FMT
  1359. "\n", xdev->name, dest.lid, IB_GUID_ARGS ( guid ) );
  1360. /* Construct request (reusing MAD buffer) */
  1361. memset ( request, 0, sizeof ( *request ) );
  1362. request->mad_hdr.mgmt_class = XSIGO_MGMT_CLASS;
  1363. request->mad_hdr.class_version = XSIGO_MGMT_CLASS_VERSION;
  1364. request->mad_hdr.method = IB_MGMT_METHOD_GET;
  1365. request->mad_hdr.attr_id = htons ( XSIGO_ATTR_XCM_REQUEST );
  1366. memcpy ( &request->server.guid, &ibdev->gid.s.guid,
  1367. sizeof ( request->server.guid ) );
  1368. snprintf ( request->os_version, sizeof ( request->os_version ),
  1369. "%s %s", product_short_name, product_version );
  1370. snprintf ( request->arch, sizeof ( request->arch ), _S2 ( ARCH ) );
  1371. request->os_type = XSIGO_OS_TYPE_GENERIC;
  1372. request->resources = htons ( XSIGO_RESOURCES_PRESENT |
  1373. XSIGO_RESOURCE_XVE |
  1374. XSIGO_RESOURCE_NO_HA );
  1375. /* The handling of this request on the server side is a
  1376. * textbook example of how not to design a wire protocol. The
  1377. * server uses the _driver_ version number to determine which
  1378. * fields are present.
  1379. */
  1380. request->driver_version = htonl ( 0x2a2a2a );
  1381. /* The build version field is ignored unless it happens to
  1382. * contain the substring "xg-".
  1383. */
  1384. snprintf ( request->build, sizeof ( request->build ),
  1385. "not-xg-%08lx", build_id );
  1386. /* The server side user interface occasionally has no way to
  1387. * refer to an entry with an empty hostname.
  1388. */
  1389. fetch_string_setting ( NULL, &hostname_setting, request->hostname,
  1390. sizeof ( request->hostname ) );
  1391. if ( ! request->hostname[0] ) {
  1392. snprintf ( request->hostname, sizeof ( request->hostname ),
  1393. "%s-" IB_GUID_FMT, product_short_name,
  1394. IB_GUID_ARGS ( &ibdev->gid.s.guid ) );
  1395. }
  1396. /* Start configuration manager lookup */
  1397. xdev->madx = ib_create_madx ( ibdev, ibdev->gsi, mad, &dest,
  1398. &xsigo_xcm_discovery.op );
  1399. if ( ! xdev->madx ) {
  1400. DBGC ( xdev, "XDEV %s could not start manager lookup\n",
  1401. xdev->name );
  1402. goto out;
  1403. }
  1404. ib_madx_set_ownerdata ( xdev->madx, xdev );
  1405. out:
  1406. /* Destroy the completed transaction */
  1407. ib_destroy_madx ( ibdev, ibdev->gsi, madx );
  1408. }
  1409. /** Directory service lookup discovery stage */
  1410. static struct xsigo_discovery xsigo_xds_discovery = {
  1411. .name = "directory",
  1412. .op = {
  1413. .complete = xsigo_xds_complete,
  1414. },
  1415. };
  1416. /**
  1417. * Discover configuration managers
  1418. *
  1419. * @v timer Retry timer
  1420. * @v over Failure indicator
  1421. */
  1422. static void xsigo_discover ( struct retry_timer *timer, int over __unused ) {
  1423. struct xsigo_device *xdev =
  1424. container_of ( timer, struct xsigo_device, discovery );
  1425. struct ib_device *ibdev = xdev->ibdev;
  1426. struct xsigo_discovery *discovery;
  1427. /* Restart timer */
  1428. start_timer_fixed ( &xdev->discovery, XSIGO_DISCOVERY_FAILURE_DELAY );
  1429. /* Cancel any pending discovery transaction */
  1430. if ( xdev->madx ) {
  1431. discovery = container_of ( xdev->madx->op,
  1432. struct xsigo_discovery, op );
  1433. DBGC ( xdev, "XDEV %s timed out waiting for %s lookup\n",
  1434. xdev->name, discovery->name );
  1435. ib_destroy_madx ( ibdev, ibdev->gsi, xdev->madx );
  1436. xdev->madx = NULL;
  1437. }
  1438. /* Start directory service lookup */
  1439. xdev->madx = ib_create_service_madx ( ibdev, ibdev->gsi,
  1440. XDS_SERVICE_NAME,
  1441. &xsigo_xds_discovery.op );
  1442. if ( ! xdev->madx ) {
  1443. DBGC ( xdev, "XDEV %s could not start directory lookup\n",
  1444. xdev->name );
  1445. return;
  1446. }
  1447. ib_madx_set_ownerdata ( xdev->madx, xdev );
  1448. }
  1449. /****************************************************************************
  1450. *
  1451. * Infiniband device driver
  1452. *
  1453. ****************************************************************************
  1454. */
  1455. /**
  1456. * Open link and start discovery
  1457. *
  1458. * @v opener Link opener
  1459. * @v over Failure indicator
  1460. */
  1461. static void xsigo_ib_open ( struct retry_timer *opener, int over __unused ) {
  1462. struct xsigo_device *xdev =
  1463. container_of ( opener, struct xsigo_device, opener );
  1464. struct ib_device *ibdev = xdev->ibdev;
  1465. int rc;
  1466. /* Open Infiniband device */
  1467. if ( ( rc = ib_open ( ibdev ) ) != 0 ) {
  1468. DBGC ( xdev, "XDEV %s could not open: %s\n",
  1469. xdev->name, strerror ( rc ) );
  1470. /* Delay and try again */
  1471. start_timer_fixed ( &xdev->opener, XSIGO_OPEN_RETRY_DELAY );
  1472. return;
  1473. }
  1474. /* If link is already up, then start discovery */
  1475. if ( ib_link_ok ( ibdev ) )
  1476. start_timer_nodelay ( &xdev->discovery );
  1477. }
  1478. /**
  1479. * Probe Xsigo device
  1480. *
  1481. * @v ibdev Infiniband device
  1482. * @ret rc Return status code
  1483. */
  1484. static int xsigo_ib_probe ( struct ib_device *ibdev ) {
  1485. struct xsigo_device *xdev;
  1486. /* Allocate and initialise structure */
  1487. xdev = zalloc ( sizeof ( *xdev ) );
  1488. if ( ! xdev )
  1489. return -ENOMEM;
  1490. ref_init ( &xdev->refcnt, xsigo_free );
  1491. xdev->ibdev = ibdev_get ( ibdev );
  1492. xdev->name = ibdev->name;
  1493. timer_init ( &xdev->opener, xsigo_ib_open, &xdev->refcnt );
  1494. timer_init ( &xdev->discovery, xsigo_discover, &xdev->refcnt );
  1495. INIT_LIST_HEAD ( &xdev->managers );
  1496. /* Start timer to open Infiniband device. (We are currently
  1497. * within the Infiniband device probe callback list; opening
  1498. * the device here would have interesting side-effects.)
  1499. */
  1500. start_timer_nodelay ( &xdev->opener );
  1501. /* Add to list of devices and transfer reference to list */
  1502. list_add_tail ( &xdev->list, &xsigo_devices );
  1503. DBGC ( xdev, "XDEV %s created for " IB_GUID_FMT "\n",
  1504. xdev->name, IB_GUID_ARGS ( &ibdev->gid.s.guid ) );
  1505. return 0;
  1506. }
  1507. /**
  1508. * Handle device or link status change
  1509. *
  1510. * @v ibdev Infiniband device
  1511. */
  1512. static void xsigo_ib_notify ( struct ib_device *ibdev ) {
  1513. struct xsigo_device *xdev;
  1514. /* Stop/restart discovery on any attached devices */
  1515. list_for_each_entry ( xdev, &xsigo_devices, list ) {
  1516. /* Skip non-attached devices */
  1517. if ( xdev->ibdev != ibdev )
  1518. continue;
  1519. /* Stop any ongoing discovery */
  1520. if ( xdev->madx ) {
  1521. ib_destroy_madx ( ibdev, ibdev->gsi, xdev->madx );
  1522. xdev->madx = NULL;
  1523. }
  1524. stop_timer ( &xdev->discovery );
  1525. /* If link is up, then start discovery */
  1526. if ( ib_link_ok ( ibdev ) )
  1527. start_timer_nodelay ( &xdev->discovery );
  1528. }
  1529. }
  1530. /**
  1531. * Remove Xsigo device
  1532. *
  1533. * @v ibdev Infiniband device
  1534. */
  1535. static void xsigo_ib_remove ( struct ib_device *ibdev ) {
  1536. struct xsigo_device *xdev;
  1537. struct xsigo_device *tmp;
  1538. /* Remove any attached Xsigo devices */
  1539. list_for_each_entry_safe ( xdev, tmp, &xsigo_devices, list ) {
  1540. /* Skip non-attached devices */
  1541. if ( xdev->ibdev != ibdev )
  1542. continue;
  1543. /* Stop any ongoing discovery */
  1544. if ( xdev->madx ) {
  1545. ib_destroy_madx ( ibdev, ibdev->gsi, xdev->madx );
  1546. xdev->madx = NULL;
  1547. }
  1548. stop_timer ( &xdev->discovery );
  1549. /* Destroy all configuration managers */
  1550. xcm_list ( xdev, NULL, 0 );
  1551. /* Close Infiniband device, if applicable */
  1552. if ( ! timer_running ( &xdev->opener ) )
  1553. ib_close ( xdev->ibdev );
  1554. /* Stop link opener */
  1555. stop_timer ( &xdev->opener );
  1556. /* Remove from list of devices and drop list's reference */
  1557. DBGC ( xdev, "XDEV %s destroyed\n", xdev->name );
  1558. list_del ( &xdev->list );
  1559. ref_put ( &xdev->refcnt );
  1560. }
  1561. }
  1562. /** Xsigo Infiniband driver */
  1563. struct ib_driver xsigo_ib_driver __ib_driver = {
  1564. .name = "Xsigo",
  1565. .probe = xsigo_ib_probe,
  1566. .notify = xsigo_ib_notify,
  1567. .remove = xsigo_ib_remove,
  1568. };
  1569. /****************************************************************************
  1570. *
  1571. * Network device driver
  1572. *
  1573. ****************************************************************************
  1574. */
  1575. /**
  1576. * Handle device or link status change
  1577. *
  1578. * @v netdev Network device
  1579. */
  1580. static void xsigo_net_notify ( struct net_device *netdev ) {
  1581. struct xsigo_device *xdev;
  1582. struct ib_device *ibdev;
  1583. struct xsigo_manager *xcm;
  1584. struct xsigo_nic *xve;
  1585. struct eoib_device *eoib;
  1586. /* Send current operational state to XCM, if applicable */
  1587. list_for_each_entry ( xdev, &xsigo_devices, list ) {
  1588. ibdev = xdev->ibdev;
  1589. list_for_each_entry ( xcm, &xdev->managers, list ) {
  1590. list_for_each_entry ( xve, &xcm->nics, list ) {
  1591. eoib = eoib_find ( ibdev, xve->mac );
  1592. if ( ! eoib )
  1593. continue;
  1594. if ( eoib->netdev != netdev )
  1595. continue;
  1596. xsmp_tx_xve_oper ( xcm, xve, eoib );
  1597. }
  1598. }
  1599. }
  1600. }
  1601. /** Xsigo network driver */
  1602. struct net_driver xsigo_net_driver __net_driver = {
  1603. .name = "Xsigo",
  1604. .notify = xsigo_net_notify,
  1605. };