opa_vnic_vema.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076
  1. /*
  2. * Copyright(c) 2017 Intel Corporation.
  3. *
  4. * This file is provided under a dual BSD/GPLv2 license. When using or
  5. * redistributing this file, you may do so under either license.
  6. *
  7. * GPL LICENSE SUMMARY
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of version 2 of the GNU General Public License as
  11. * published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. *
  18. * BSD LICENSE
  19. *
  20. * Redistribution and use in source and binary forms, with or without
  21. * modification, are permitted provided that the following conditions
  22. * are met:
  23. *
  24. * - Redistributions of source code must retain the above copyright
  25. * notice, this list of conditions and the following disclaimer.
  26. * - Redistributions in binary form must reproduce the above copyright
  27. * notice, this list of conditions and the following disclaimer in
  28. * the documentation and/or other materials provided with the
  29. * distribution.
  30. * - Neither the name of Intel Corporation nor the names of its
  31. * contributors may be used to endorse or promote products derived
  32. * from this software without specific prior written permission.
  33. *
  34. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  35. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  36. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  37. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  38. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  39. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  40. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  41. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  42. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  43. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  44. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  45. *
  46. */
  47. /*
  48. * This file contains OPA Virtual Network Interface Controller (VNIC)
  49. * Ethernet Management Agent (EMA) driver
  50. */
  51. #include <linux/module.h>
  52. #include <rdma/ib_addr.h>
  53. #include <rdma/ib_verbs.h>
  54. #include <rdma/opa_smi.h>
  55. #include <rdma/opa_port_info.h>
  56. #include "opa_vnic_internal.h"
  57. #define DRV_VERSION "1.0"
  58. char opa_vnic_driver_name[] = "opa_vnic";
  59. const char opa_vnic_driver_version[] = DRV_VERSION;
  60. /*
  61. * The trap service level is kept in bits 3 to 7 in the trap_sl_rsvd
  62. * field in the class port info MAD.
  63. */
  64. #define GET_TRAP_SL_FROM_CLASS_PORT_INFO(x) (((x) >> 3) & 0x1f)
  65. /* Cap trap bursts to a reasonable limit good for normal cases */
  66. #define OPA_VNIC_TRAP_BURST_LIMIT 4
  67. /*
  68. * VNIC trap limit timeout.
  69. * Inverse of cap2_mask response time out (1.0737 secs) = 0.9
  70. * secs approx IB spec 13.4.6.2.1 PortInfoSubnetTimeout and
  71. * 13.4.9 Traps.
  72. */
  73. #define OPA_VNIC_TRAP_TIMEOUT ((4096 * (1UL << 18)) / 1000)
  74. #define OPA_VNIC_UNSUP_ATTR \
  75. cpu_to_be16(IB_MGMT_MAD_STATUS_UNSUPPORTED_METHOD_ATTRIB)
  76. #define OPA_VNIC_INVAL_ATTR \
  77. cpu_to_be16(IB_MGMT_MAD_STATUS_INVALID_ATTRIB_VALUE)
  78. #define OPA_VNIC_CLASS_CAP_TRAP 0x1
  79. /* Maximum number of VNIC ports supported */
  80. #define OPA_VNIC_MAX_NUM_VPORT 255
  81. /**
  82. * struct opa_vnic_vema_port -- VNIC VEMA port details
  83. * @cport: pointer to port
  84. * @mad_agent: pointer to mad agent for port
  85. * @class_port_info: Class port info information.
  86. * @tid: Transaction id
  87. * @port_num: OPA port number
  88. * @vport_idr: vnic ports idr
  89. * @event_handler: ib event handler
  90. * @lock: adapter interface lock
  91. */
  92. struct opa_vnic_vema_port {
  93. struct opa_vnic_ctrl_port *cport;
  94. struct ib_mad_agent *mad_agent;
  95. struct opa_class_port_info class_port_info;
  96. u64 tid;
  97. u8 port_num;
  98. struct idr vport_idr;
  99. struct ib_event_handler event_handler;
  100. /* Lock to query/update network adapter */
  101. struct mutex lock;
  102. };
  103. static void opa_vnic_vema_add_one(struct ib_device *device);
  104. static void opa_vnic_vema_rem_one(struct ib_device *device,
  105. void *client_data);
  106. static struct ib_client opa_vnic_client = {
  107. .name = opa_vnic_driver_name,
  108. .add = opa_vnic_vema_add_one,
  109. .remove = opa_vnic_vema_rem_one,
  110. };
  111. /**
  112. * vema_get_vport_num -- Get the vnic from the mad
  113. * @recvd_mad: Received mad
  114. *
  115. * Return: returns value of the vnic port number
  116. */
  117. static inline u8 vema_get_vport_num(struct opa_vnic_vema_mad *recvd_mad)
  118. {
  119. return be32_to_cpu(recvd_mad->mad_hdr.attr_mod) & 0xff;
  120. }
  121. /**
  122. * vema_get_vport_adapter -- Get vnic port adapter from recvd mad
  123. * @recvd_mad: received mad
  124. * @port: ptr to port struct on which MAD was recvd
  125. *
  126. * Return: vnic adapter
  127. */
  128. static inline struct opa_vnic_adapter *
  129. vema_get_vport_adapter(struct opa_vnic_vema_mad *recvd_mad,
  130. struct opa_vnic_vema_port *port)
  131. {
  132. u8 vport_num = vema_get_vport_num(recvd_mad);
  133. return idr_find(&port->vport_idr, vport_num);
  134. }
  135. /**
  136. * vema_mac_tbl_req_ok -- Check if mac request has correct values
  137. * @mac_tbl: mac table
  138. *
  139. * This function checks for the validity of the offset and number of
  140. * entries required.
  141. *
  142. * Return: true if offset and num_entries are valid
  143. */
  144. static inline bool vema_mac_tbl_req_ok(struct opa_veswport_mactable *mac_tbl)
  145. {
  146. u16 offset, num_entries;
  147. u16 req_entries = ((OPA_VNIC_EMA_DATA - sizeof(*mac_tbl)) /
  148. sizeof(mac_tbl->tbl_entries[0]));
  149. offset = be16_to_cpu(mac_tbl->offset);
  150. num_entries = be16_to_cpu(mac_tbl->num_entries);
  151. return ((num_entries <= req_entries) &&
  152. (offset + num_entries <= OPA_VNIC_MAC_TBL_MAX_ENTRIES));
  153. }
  154. /*
  155. * Return the power on default values in the port info structure
  156. * in big endian format as required by MAD.
  157. */
  158. static inline void vema_get_pod_values(struct opa_veswport_info *port_info)
  159. {
  160. memset(port_info, 0, sizeof(*port_info));
  161. port_info->vport.max_mac_tbl_ent =
  162. cpu_to_be16(OPA_VNIC_MAC_TBL_MAX_ENTRIES);
  163. port_info->vport.max_smac_ent =
  164. cpu_to_be16(OPA_VNIC_MAX_SMAC_LIMIT);
  165. port_info->vport.oper_state = OPA_VNIC_STATE_DROP_ALL;
  166. port_info->vport.config_state = OPA_VNIC_STATE_DROP_ALL;
  167. port_info->vesw.eth_mtu = cpu_to_be16(ETH_DATA_LEN);
  168. }
  169. /**
  170. * vema_add_vport -- Add a new vnic port
  171. * @port: ptr to opa_vnic_vema_port struct
  172. * @vport_num: vnic port number (to be added)
  173. *
  174. * Return a pointer to the vnic adapter structure
  175. */
  176. static struct opa_vnic_adapter *vema_add_vport(struct opa_vnic_vema_port *port,
  177. u8 vport_num)
  178. {
  179. struct opa_vnic_ctrl_port *cport = port->cport;
  180. struct opa_vnic_adapter *adapter;
  181. adapter = opa_vnic_add_netdev(cport->ibdev, port->port_num, vport_num);
  182. if (!IS_ERR(adapter)) {
  183. int rc;
  184. adapter->cport = cport;
  185. rc = idr_alloc(&port->vport_idr, adapter, vport_num,
  186. vport_num + 1, GFP_NOWAIT);
  187. if (rc < 0) {
  188. opa_vnic_rem_netdev(adapter);
  189. adapter = ERR_PTR(rc);
  190. }
  191. }
  192. return adapter;
  193. }
  194. /**
  195. * vema_get_class_port_info -- Get class info for port
  196. * @port: Port on whic MAD was received
  197. * @recvd_mad: pointer to the received mad
  198. * @rsp_mad: pointer to respose mad
  199. *
  200. * This function copies the latest class port info value set for the
  201. * port and stores it for generating traps
  202. */
  203. static void vema_get_class_port_info(struct opa_vnic_vema_port *port,
  204. struct opa_vnic_vema_mad *recvd_mad,
  205. struct opa_vnic_vema_mad *rsp_mad)
  206. {
  207. struct opa_class_port_info *port_info;
  208. port_info = (struct opa_class_port_info *)rsp_mad->data;
  209. memcpy(port_info, &port->class_port_info, sizeof(*port_info));
  210. port_info->base_version = OPA_MGMT_BASE_VERSION,
  211. port_info->class_version = OPA_EMA_CLASS_VERSION;
  212. /*
  213. * Set capability mask bit indicating agent generates traps,
  214. * and set the maximum number of VNIC ports supported.
  215. */
  216. port_info->cap_mask = cpu_to_be16((OPA_VNIC_CLASS_CAP_TRAP |
  217. (OPA_VNIC_MAX_NUM_VPORT << 8)));
  218. /*
  219. * Since a get routine is always sent by the EM first we
  220. * set the expected response time to
  221. * 4.096 usec * 2^18 == 1.0737 sec here.
  222. */
  223. port_info->cap_mask2_resp_time = cpu_to_be32(18);
  224. }
  225. /**
  226. * vema_set_class_port_info -- Get class info for port
  227. * @port: Port on whic MAD was received
  228. * @recvd_mad: pointer to the received mad
  229. * @rsp_mad: pointer to respose mad
  230. *
  231. * This function updates the port class info for the specific vnic
  232. * and sets up the response mad data
  233. */
  234. static void vema_set_class_port_info(struct opa_vnic_vema_port *port,
  235. struct opa_vnic_vema_mad *recvd_mad,
  236. struct opa_vnic_vema_mad *rsp_mad)
  237. {
  238. memcpy(&port->class_port_info, recvd_mad->data,
  239. sizeof(port->class_port_info));
  240. vema_get_class_port_info(port, recvd_mad, rsp_mad);
  241. }
  242. /**
  243. * vema_get_veswport_info -- Get veswport info
  244. * @port: source port on which MAD was received
  245. * @recvd_mad: pointer to the received mad
  246. * @rsp_mad: pointer to respose mad
  247. */
  248. static void vema_get_veswport_info(struct opa_vnic_vema_port *port,
  249. struct opa_vnic_vema_mad *recvd_mad,
  250. struct opa_vnic_vema_mad *rsp_mad)
  251. {
  252. struct opa_veswport_info *port_info =
  253. (struct opa_veswport_info *)rsp_mad->data;
  254. struct opa_vnic_adapter *adapter;
  255. adapter = vema_get_vport_adapter(recvd_mad, port);
  256. if (adapter) {
  257. memset(port_info, 0, sizeof(*port_info));
  258. opa_vnic_get_vesw_info(adapter, &port_info->vesw);
  259. opa_vnic_get_per_veswport_info(adapter,
  260. &port_info->vport);
  261. } else {
  262. vema_get_pod_values(port_info);
  263. }
  264. }
  265. /**
  266. * vema_set_veswport_info -- Set veswport info
  267. * @port: source port on which MAD was received
  268. * @recvd_mad: pointer to the received mad
  269. * @rsp_mad: pointer to respose mad
  270. *
  271. * This function gets the port class infor for vnic
  272. */
  273. static void vema_set_veswport_info(struct opa_vnic_vema_port *port,
  274. struct opa_vnic_vema_mad *recvd_mad,
  275. struct opa_vnic_vema_mad *rsp_mad)
  276. {
  277. struct opa_vnic_ctrl_port *cport = port->cport;
  278. struct opa_veswport_info *port_info;
  279. struct opa_vnic_adapter *adapter;
  280. u8 vport_num;
  281. vport_num = vema_get_vport_num(recvd_mad);
  282. adapter = vema_get_vport_adapter(recvd_mad, port);
  283. if (!adapter) {
  284. adapter = vema_add_vport(port, vport_num);
  285. if (IS_ERR(adapter)) {
  286. c_err("failed to add vport %d: %ld\n",
  287. vport_num, PTR_ERR(adapter));
  288. goto err_exit;
  289. }
  290. }
  291. port_info = (struct opa_veswport_info *)recvd_mad->data;
  292. opa_vnic_set_vesw_info(adapter, &port_info->vesw);
  293. opa_vnic_set_per_veswport_info(adapter, &port_info->vport);
  294. /* Process the new config settings */
  295. opa_vnic_process_vema_config(adapter);
  296. vema_get_veswport_info(port, recvd_mad, rsp_mad);
  297. return;
  298. err_exit:
  299. rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
  300. }
  301. /**
  302. * vema_get_mac_entries -- Get MAC entries in VNIC MAC table
  303. * @port: source port on which MAD was received
  304. * @recvd_mad: pointer to the received mad
  305. * @rsp_mad: pointer to respose mad
  306. *
  307. * This function gets the MAC entries that are programmed into
  308. * the VNIC MAC forwarding table. It checks for the validity of
  309. * the index into the MAC table and the number of entries that
  310. * are to be retrieved.
  311. */
  312. static void vema_get_mac_entries(struct opa_vnic_vema_port *port,
  313. struct opa_vnic_vema_mad *recvd_mad,
  314. struct opa_vnic_vema_mad *rsp_mad)
  315. {
  316. struct opa_veswport_mactable *mac_tbl_in, *mac_tbl_out;
  317. struct opa_vnic_adapter *adapter;
  318. adapter = vema_get_vport_adapter(recvd_mad, port);
  319. if (!adapter) {
  320. rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
  321. return;
  322. }
  323. mac_tbl_in = (struct opa_veswport_mactable *)recvd_mad->data;
  324. mac_tbl_out = (struct opa_veswport_mactable *)rsp_mad->data;
  325. if (vema_mac_tbl_req_ok(mac_tbl_in)) {
  326. mac_tbl_out->offset = mac_tbl_in->offset;
  327. mac_tbl_out->num_entries = mac_tbl_in->num_entries;
  328. opa_vnic_query_mac_tbl(adapter, mac_tbl_out);
  329. } else {
  330. rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
  331. }
  332. }
  333. /**
  334. * vema_set_mac_entries -- Set MAC entries in VNIC MAC table
  335. * @port: source port on which MAD was received
  336. * @recvd_mad: pointer to the received mad
  337. * @rsp_mad: pointer to respose mad
  338. *
  339. * This function sets the MAC entries in the VNIC forwarding table
  340. * It checks for the validity of the index and the number of forwarding
  341. * table entries to be programmed.
  342. */
  343. static void vema_set_mac_entries(struct opa_vnic_vema_port *port,
  344. struct opa_vnic_vema_mad *recvd_mad,
  345. struct opa_vnic_vema_mad *rsp_mad)
  346. {
  347. struct opa_veswport_mactable *mac_tbl;
  348. struct opa_vnic_adapter *adapter;
  349. adapter = vema_get_vport_adapter(recvd_mad, port);
  350. if (!adapter) {
  351. rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
  352. return;
  353. }
  354. mac_tbl = (struct opa_veswport_mactable *)recvd_mad->data;
  355. if (vema_mac_tbl_req_ok(mac_tbl)) {
  356. if (opa_vnic_update_mac_tbl(adapter, mac_tbl))
  357. rsp_mad->mad_hdr.status = OPA_VNIC_UNSUP_ATTR;
  358. } else {
  359. rsp_mad->mad_hdr.status = OPA_VNIC_UNSUP_ATTR;
  360. }
  361. vema_get_mac_entries(port, recvd_mad, rsp_mad);
  362. }
  363. /**
  364. * vema_set_delete_vesw -- Reset VESW info to POD values
  365. * @port: source port on which MAD was received
  366. * @recvd_mad: pointer to the received mad
  367. * @rsp_mad: pointer to respose mad
  368. *
  369. * This function clears all the fields of veswport info for the requested vesw
  370. * and sets them back to the power-on default values. It does not delete the
  371. * vesw.
  372. */
  373. static void vema_set_delete_vesw(struct opa_vnic_vema_port *port,
  374. struct opa_vnic_vema_mad *recvd_mad,
  375. struct opa_vnic_vema_mad *rsp_mad)
  376. {
  377. struct opa_veswport_info *port_info =
  378. (struct opa_veswport_info *)rsp_mad->data;
  379. struct opa_vnic_adapter *adapter;
  380. adapter = vema_get_vport_adapter(recvd_mad, port);
  381. if (!adapter) {
  382. rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
  383. return;
  384. }
  385. vema_get_pod_values(port_info);
  386. opa_vnic_set_vesw_info(adapter, &port_info->vesw);
  387. opa_vnic_set_per_veswport_info(adapter, &port_info->vport);
  388. /* Process the new config settings */
  389. opa_vnic_process_vema_config(adapter);
  390. opa_vnic_release_mac_tbl(adapter);
  391. vema_get_veswport_info(port, recvd_mad, rsp_mad);
  392. }
  393. /**
  394. * vema_get_mac_list -- Get the unicast/multicast macs.
  395. * @port: source port on which MAD was received
  396. * @recvd_mad: Received mad contains fields to set vnic parameters
  397. * @rsp_mad: Response mad to be built
  398. * @attr_id: Attribute ID indicating multicast or unicast mac list
  399. */
  400. static void vema_get_mac_list(struct opa_vnic_vema_port *port,
  401. struct opa_vnic_vema_mad *recvd_mad,
  402. struct opa_vnic_vema_mad *rsp_mad,
  403. u16 attr_id)
  404. {
  405. struct opa_veswport_iface_macs *macs_in, *macs_out;
  406. int max_entries = (OPA_VNIC_EMA_DATA - sizeof(*macs_out)) / ETH_ALEN;
  407. struct opa_vnic_adapter *adapter;
  408. adapter = vema_get_vport_adapter(recvd_mad, port);
  409. if (!adapter) {
  410. rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
  411. return;
  412. }
  413. macs_in = (struct opa_veswport_iface_macs *)recvd_mad->data;
  414. macs_out = (struct opa_veswport_iface_macs *)rsp_mad->data;
  415. macs_out->start_idx = macs_in->start_idx;
  416. if (macs_in->num_macs_in_msg)
  417. macs_out->num_macs_in_msg = macs_in->num_macs_in_msg;
  418. else
  419. macs_out->num_macs_in_msg = cpu_to_be16(max_entries);
  420. if (attr_id == OPA_EM_ATTR_IFACE_MCAST_MACS)
  421. opa_vnic_query_mcast_macs(adapter, macs_out);
  422. else
  423. opa_vnic_query_ucast_macs(adapter, macs_out);
  424. }
  425. /**
  426. * vema_get_summary_counters -- Gets summary counters.
  427. * @port: source port on which MAD was received
  428. * @recvd_mad: Received mad contains fields to set vnic parameters
  429. * @rsp_mad: Response mad to be built
  430. */
  431. static void vema_get_summary_counters(struct opa_vnic_vema_port *port,
  432. struct opa_vnic_vema_mad *recvd_mad,
  433. struct opa_vnic_vema_mad *rsp_mad)
  434. {
  435. struct opa_veswport_summary_counters *cntrs;
  436. struct opa_vnic_adapter *adapter;
  437. adapter = vema_get_vport_adapter(recvd_mad, port);
  438. if (adapter) {
  439. cntrs = (struct opa_veswport_summary_counters *)rsp_mad->data;
  440. opa_vnic_get_summary_counters(adapter, cntrs);
  441. } else {
  442. rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
  443. }
  444. }
  445. /**
  446. * vema_get_error_counters -- Gets summary counters.
  447. * @port: source port on which MAD was received
  448. * @recvd_mad: Received mad contains fields to set vnic parameters
  449. * @rsp_mad: Response mad to be built
  450. */
  451. static void vema_get_error_counters(struct opa_vnic_vema_port *port,
  452. struct opa_vnic_vema_mad *recvd_mad,
  453. struct opa_vnic_vema_mad *rsp_mad)
  454. {
  455. struct opa_veswport_error_counters *cntrs;
  456. struct opa_vnic_adapter *adapter;
  457. adapter = vema_get_vport_adapter(recvd_mad, port);
  458. if (adapter) {
  459. cntrs = (struct opa_veswport_error_counters *)rsp_mad->data;
  460. opa_vnic_get_error_counters(adapter, cntrs);
  461. } else {
  462. rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
  463. }
  464. }
  465. /**
  466. * vema_get -- Process received get MAD
  467. * @port: source port on which MAD was received
  468. * @recvd_mad: Received mad
  469. * @rsp_mad: Response mad to be built
  470. */
  471. static void vema_get(struct opa_vnic_vema_port *port,
  472. struct opa_vnic_vema_mad *recvd_mad,
  473. struct opa_vnic_vema_mad *rsp_mad)
  474. {
  475. u16 attr_id = be16_to_cpu(recvd_mad->mad_hdr.attr_id);
  476. switch (attr_id) {
  477. case OPA_EM_ATTR_CLASS_PORT_INFO:
  478. vema_get_class_port_info(port, recvd_mad, rsp_mad);
  479. break;
  480. case OPA_EM_ATTR_VESWPORT_INFO:
  481. vema_get_veswport_info(port, recvd_mad, rsp_mad);
  482. break;
  483. case OPA_EM_ATTR_VESWPORT_MAC_ENTRIES:
  484. vema_get_mac_entries(port, recvd_mad, rsp_mad);
  485. break;
  486. case OPA_EM_ATTR_IFACE_UCAST_MACS:
  487. /* fall through */
  488. case OPA_EM_ATTR_IFACE_MCAST_MACS:
  489. vema_get_mac_list(port, recvd_mad, rsp_mad, attr_id);
  490. break;
  491. case OPA_EM_ATTR_VESWPORT_SUMMARY_COUNTERS:
  492. vema_get_summary_counters(port, recvd_mad, rsp_mad);
  493. break;
  494. case OPA_EM_ATTR_VESWPORT_ERROR_COUNTERS:
  495. vema_get_error_counters(port, recvd_mad, rsp_mad);
  496. break;
  497. default:
  498. rsp_mad->mad_hdr.status = OPA_VNIC_UNSUP_ATTR;
  499. break;
  500. }
  501. }
  502. /**
  503. * vema_set -- Process received set MAD
  504. * @port: source port on which MAD was received
  505. * @recvd_mad: Received mad contains fields to set vnic parameters
  506. * @rsp_mad: Response mad to be built
  507. */
  508. static void vema_set(struct opa_vnic_vema_port *port,
  509. struct opa_vnic_vema_mad *recvd_mad,
  510. struct opa_vnic_vema_mad *rsp_mad)
  511. {
  512. u16 attr_id = be16_to_cpu(recvd_mad->mad_hdr.attr_id);
  513. switch (attr_id) {
  514. case OPA_EM_ATTR_CLASS_PORT_INFO:
  515. vema_set_class_port_info(port, recvd_mad, rsp_mad);
  516. break;
  517. case OPA_EM_ATTR_VESWPORT_INFO:
  518. vema_set_veswport_info(port, recvd_mad, rsp_mad);
  519. break;
  520. case OPA_EM_ATTR_VESWPORT_MAC_ENTRIES:
  521. vema_set_mac_entries(port, recvd_mad, rsp_mad);
  522. break;
  523. case OPA_EM_ATTR_DELETE_VESW:
  524. vema_set_delete_vesw(port, recvd_mad, rsp_mad);
  525. break;
  526. default:
  527. rsp_mad->mad_hdr.status = OPA_VNIC_UNSUP_ATTR;
  528. break;
  529. }
  530. }
  531. /**
  532. * vema_send -- Send handler for VEMA MAD agent
  533. * @mad_agent: pointer to the mad agent
  534. * @mad_wc: pointer to mad send work completion information
  535. *
  536. * Free all the data structures associated with the sent MAD
  537. */
  538. static void vema_send(struct ib_mad_agent *mad_agent,
  539. struct ib_mad_send_wc *mad_wc)
  540. {
  541. rdma_destroy_ah(mad_wc->send_buf->ah);
  542. ib_free_send_mad(mad_wc->send_buf);
  543. }
  544. /**
  545. * vema_recv -- Recv handler for VEMA MAD agent
  546. * @mad_agent: pointer to the mad agent
  547. * @send_buf: Send buffer if found, else NULL
  548. * @mad_wc: pointer to mad send work completion information
  549. *
  550. * Handle only set and get methods and respond to other methods
  551. * as unsupported. Allocate response buffer and address handle
  552. * for the response MAD.
  553. */
  554. static void vema_recv(struct ib_mad_agent *mad_agent,
  555. struct ib_mad_send_buf *send_buf,
  556. struct ib_mad_recv_wc *mad_wc)
  557. {
  558. struct opa_vnic_vema_port *port;
  559. struct ib_ah *ah;
  560. struct ib_mad_send_buf *rsp;
  561. struct opa_vnic_vema_mad *vema_mad;
  562. if (!mad_wc || !mad_wc->recv_buf.mad)
  563. return;
  564. port = mad_agent->context;
  565. ah = ib_create_ah_from_wc(mad_agent->qp->pd, mad_wc->wc,
  566. mad_wc->recv_buf.grh, mad_agent->port_num);
  567. if (IS_ERR(ah))
  568. goto free_recv_mad;
  569. rsp = ib_create_send_mad(mad_agent, mad_wc->wc->src_qp,
  570. mad_wc->wc->pkey_index, 0,
  571. IB_MGMT_VENDOR_HDR, OPA_VNIC_EMA_DATA,
  572. GFP_KERNEL, OPA_MGMT_BASE_VERSION);
  573. if (IS_ERR(rsp))
  574. goto err_rsp;
  575. rsp->ah = ah;
  576. vema_mad = rsp->mad;
  577. memcpy(vema_mad, mad_wc->recv_buf.mad, IB_MGMT_VENDOR_HDR);
  578. vema_mad->mad_hdr.method = IB_MGMT_METHOD_GET_RESP;
  579. vema_mad->mad_hdr.status = 0;
  580. /* Lock ensures network adapter is not removed */
  581. mutex_lock(&port->lock);
  582. switch (mad_wc->recv_buf.mad->mad_hdr.method) {
  583. case IB_MGMT_METHOD_GET:
  584. vema_get(port, (struct opa_vnic_vema_mad *)mad_wc->recv_buf.mad,
  585. vema_mad);
  586. break;
  587. case IB_MGMT_METHOD_SET:
  588. vema_set(port, (struct opa_vnic_vema_mad *)mad_wc->recv_buf.mad,
  589. vema_mad);
  590. break;
  591. default:
  592. vema_mad->mad_hdr.status = OPA_VNIC_UNSUP_ATTR;
  593. break;
  594. }
  595. mutex_unlock(&port->lock);
  596. if (!ib_post_send_mad(rsp, NULL)) {
  597. /*
  598. * with post send successful ah and send mad
  599. * will be destroyed in send handler
  600. */
  601. goto free_recv_mad;
  602. }
  603. ib_free_send_mad(rsp);
  604. err_rsp:
  605. rdma_destroy_ah(ah);
  606. free_recv_mad:
  607. ib_free_recv_mad(mad_wc);
  608. }
  609. /**
  610. * vema_get_port -- Gets the opa_vnic_vema_port
  611. * @cport: pointer to control dev
  612. * @port_num: Port number
  613. *
  614. * This function loops through the ports and returns
  615. * the opa_vnic_vema port structure that is associated
  616. * with the OPA port number
  617. *
  618. * Return: ptr to requested opa_vnic_vema_port strucure
  619. * if success, NULL if not
  620. */
  621. static struct opa_vnic_vema_port *
  622. vema_get_port(struct opa_vnic_ctrl_port *cport, u8 port_num)
  623. {
  624. struct opa_vnic_vema_port *port = (void *)cport + sizeof(*cport);
  625. if (port_num > cport->num_ports)
  626. return NULL;
  627. return port + (port_num - 1);
  628. }
  629. /**
  630. * opa_vnic_vema_send_trap -- This function sends a trap to the EM
  631. * @adapter: pointer to vnic adapter
  632. * @data: pointer to trap data filled by calling function
  633. * @lid: issuers lid (encap_slid from vesw_port_info)
  634. *
  635. * This function is called from the VNIC driver to send a trap if there
  636. * is somethng the EM should be notified about. These events currently
  637. * are
  638. * 1) UNICAST INTERFACE MACADDRESS changes
  639. * 2) MULTICAST INTERFACE MACADDRESS changes
  640. * 3) ETHERNET LINK STATUS changes
  641. * While allocating the send mad the remote site qpn used is 1
  642. * as this is the well known QP.
  643. *
  644. */
  645. void opa_vnic_vema_send_trap(struct opa_vnic_adapter *adapter,
  646. struct __opa_veswport_trap *data, u32 lid)
  647. {
  648. struct opa_vnic_ctrl_port *cport = adapter->cport;
  649. struct ib_mad_send_buf *send_buf;
  650. struct opa_vnic_vema_port *port;
  651. struct ib_device *ibp;
  652. struct opa_vnic_vema_mad_trap *trap_mad;
  653. struct opa_class_port_info *class;
  654. struct rdma_ah_attr ah_attr;
  655. struct ib_ah *ah;
  656. struct opa_veswport_trap *trap;
  657. u32 trap_lid;
  658. u16 pkey_idx;
  659. if (!cport)
  660. goto err_exit;
  661. ibp = cport->ibdev;
  662. port = vema_get_port(cport, data->opaportnum);
  663. if (!port || !port->mad_agent)
  664. goto err_exit;
  665. if (time_before(jiffies, adapter->trap_timeout)) {
  666. if (adapter->trap_count == OPA_VNIC_TRAP_BURST_LIMIT) {
  667. v_warn("Trap rate exceeded\n");
  668. goto err_exit;
  669. } else {
  670. adapter->trap_count++;
  671. }
  672. } else {
  673. adapter->trap_count = 0;
  674. }
  675. class = &port->class_port_info;
  676. /* Set up address handle */
  677. memset(&ah_attr, 0, sizeof(ah_attr));
  678. ah_attr.type = rdma_ah_find_type(ibp, port->port_num);
  679. rdma_ah_set_sl(&ah_attr,
  680. GET_TRAP_SL_FROM_CLASS_PORT_INFO(class->trap_sl_rsvd));
  681. rdma_ah_set_port_num(&ah_attr, port->port_num);
  682. trap_lid = be32_to_cpu(class->trap_lid);
  683. /*
  684. * check for trap lid validity, must not be zero
  685. * The trap sink could change after we fashion the MAD but since traps
  686. * are not guaranteed we won't use a lock as anyway the change will take
  687. * place even with locking.
  688. */
  689. if (!trap_lid) {
  690. c_err("%s: Invalid dlid\n", __func__);
  691. goto err_exit;
  692. }
  693. rdma_ah_set_dlid(&ah_attr, trap_lid);
  694. ah = rdma_create_ah(port->mad_agent->qp->pd, &ah_attr);
  695. if (IS_ERR(ah)) {
  696. c_err("%s:Couldn't create new AH = %p\n", __func__, ah);
  697. c_err("%s:dlid = %d, sl = %d, port = %d\n", __func__,
  698. rdma_ah_get_dlid(&ah_attr), rdma_ah_get_sl(&ah_attr),
  699. rdma_ah_get_port_num(&ah_attr));
  700. goto err_exit;
  701. }
  702. if (ib_find_pkey(ibp, data->opaportnum, IB_DEFAULT_PKEY_FULL,
  703. &pkey_idx) < 0) {
  704. c_err("%s:full key not found, defaulting to partial\n",
  705. __func__);
  706. if (ib_find_pkey(ibp, data->opaportnum, IB_DEFAULT_PKEY_PARTIAL,
  707. &pkey_idx) < 0)
  708. pkey_idx = 1;
  709. }
  710. send_buf = ib_create_send_mad(port->mad_agent, 1, pkey_idx, 0,
  711. IB_MGMT_VENDOR_HDR, IB_MGMT_MAD_DATA,
  712. GFP_ATOMIC, OPA_MGMT_BASE_VERSION);
  713. if (IS_ERR(send_buf)) {
  714. c_err("%s:Couldn't allocate send buf\n", __func__);
  715. goto err_sndbuf;
  716. }
  717. send_buf->ah = ah;
  718. /* Set up common MAD hdr */
  719. trap_mad = send_buf->mad;
  720. trap_mad->mad_hdr.base_version = OPA_MGMT_BASE_VERSION;
  721. trap_mad->mad_hdr.mgmt_class = OPA_MGMT_CLASS_INTEL_EMA;
  722. trap_mad->mad_hdr.class_version = OPA_EMA_CLASS_VERSION;
  723. trap_mad->mad_hdr.method = IB_MGMT_METHOD_TRAP;
  724. port->tid++;
  725. trap_mad->mad_hdr.tid = cpu_to_be64(port->tid);
  726. trap_mad->mad_hdr.attr_id = IB_SMP_ATTR_NOTICE;
  727. /* Set up vendor OUI */
  728. trap_mad->oui[0] = INTEL_OUI_1;
  729. trap_mad->oui[1] = INTEL_OUI_2;
  730. trap_mad->oui[2] = INTEL_OUI_3;
  731. /* Setup notice attribute portion */
  732. trap_mad->notice.gen_type = OPA_INTEL_EMA_NOTICE_TYPE_INFO << 1;
  733. trap_mad->notice.oui_1 = INTEL_OUI_1;
  734. trap_mad->notice.oui_2 = INTEL_OUI_2;
  735. trap_mad->notice.oui_3 = INTEL_OUI_3;
  736. trap_mad->notice.issuer_lid = cpu_to_be32(lid);
  737. /* copy the actual trap data */
  738. trap = (struct opa_veswport_trap *)trap_mad->notice.raw_data;
  739. trap->fabric_id = cpu_to_be16(data->fabric_id);
  740. trap->veswid = cpu_to_be16(data->veswid);
  741. trap->veswportnum = cpu_to_be32(data->veswportnum);
  742. trap->opaportnum = cpu_to_be16(data->opaportnum);
  743. trap->veswportindex = data->veswportindex;
  744. trap->opcode = data->opcode;
  745. /* If successful send set up rate limit timeout else bail */
  746. if (ib_post_send_mad(send_buf, NULL)) {
  747. ib_free_send_mad(send_buf);
  748. } else {
  749. if (adapter->trap_count)
  750. return;
  751. adapter->trap_timeout = jiffies +
  752. usecs_to_jiffies(OPA_VNIC_TRAP_TIMEOUT);
  753. return;
  754. }
  755. err_sndbuf:
  756. rdma_destroy_ah(ah);
  757. err_exit:
  758. v_err("Aborting trap\n");
  759. }
  760. static int vema_rem_vport(int id, void *p, void *data)
  761. {
  762. struct opa_vnic_adapter *adapter = p;
  763. opa_vnic_rem_netdev(adapter);
  764. return 0;
  765. }
  766. static int vema_enable_vport(int id, void *p, void *data)
  767. {
  768. struct opa_vnic_adapter *adapter = p;
  769. netif_carrier_on(adapter->netdev);
  770. return 0;
  771. }
  772. static int vema_disable_vport(int id, void *p, void *data)
  773. {
  774. struct opa_vnic_adapter *adapter = p;
  775. netif_carrier_off(adapter->netdev);
  776. return 0;
  777. }
  778. static void opa_vnic_event(struct ib_event_handler *handler,
  779. struct ib_event *record)
  780. {
  781. struct opa_vnic_vema_port *port =
  782. container_of(handler, struct opa_vnic_vema_port, event_handler);
  783. struct opa_vnic_ctrl_port *cport = port->cport;
  784. if (record->element.port_num != port->port_num)
  785. return;
  786. c_dbg("OPA_VNIC received event %d on device %s port %d\n",
  787. record->event, record->device->name, record->element.port_num);
  788. if (record->event == IB_EVENT_PORT_ERR)
  789. idr_for_each(&port->vport_idr, vema_disable_vport, NULL);
  790. if (record->event == IB_EVENT_PORT_ACTIVE)
  791. idr_for_each(&port->vport_idr, vema_enable_vport, NULL);
  792. }
  793. /**
  794. * vema_unregister -- Unregisters agent
  795. * @cport: pointer to control port
  796. *
  797. * This deletes the registration by VEMA for MADs
  798. */
  799. static void vema_unregister(struct opa_vnic_ctrl_port *cport)
  800. {
  801. int i;
  802. for (i = 1; i <= cport->num_ports; i++) {
  803. struct opa_vnic_vema_port *port = vema_get_port(cport, i);
  804. if (!port->mad_agent)
  805. continue;
  806. /* Lock ensures no MAD is being processed */
  807. mutex_lock(&port->lock);
  808. idr_for_each(&port->vport_idr, vema_rem_vport, NULL);
  809. mutex_unlock(&port->lock);
  810. ib_unregister_mad_agent(port->mad_agent);
  811. port->mad_agent = NULL;
  812. mutex_destroy(&port->lock);
  813. idr_destroy(&port->vport_idr);
  814. ib_unregister_event_handler(&port->event_handler);
  815. }
  816. }
  817. /**
  818. * vema_register -- Registers agent
  819. * @cport: pointer to control port
  820. *
  821. * This function registers the handlers for the VEMA MADs
  822. *
  823. * Return: returns 0 on success. non zero otherwise
  824. */
  825. static int vema_register(struct opa_vnic_ctrl_port *cport)
  826. {
  827. struct ib_mad_reg_req reg_req = {
  828. .mgmt_class = OPA_MGMT_CLASS_INTEL_EMA,
  829. .mgmt_class_version = OPA_MGMT_BASE_VERSION,
  830. .oui = { INTEL_OUI_1, INTEL_OUI_2, INTEL_OUI_3 }
  831. };
  832. int i;
  833. set_bit(IB_MGMT_METHOD_GET, reg_req.method_mask);
  834. set_bit(IB_MGMT_METHOD_SET, reg_req.method_mask);
  835. /* register ib event handler and mad agent for each port on dev */
  836. for (i = 1; i <= cport->num_ports; i++) {
  837. struct opa_vnic_vema_port *port = vema_get_port(cport, i);
  838. int ret;
  839. port->cport = cport;
  840. port->port_num = i;
  841. INIT_IB_EVENT_HANDLER(&port->event_handler,
  842. cport->ibdev, opa_vnic_event);
  843. ib_register_event_handler(&port->event_handler);
  844. idr_init(&port->vport_idr);
  845. mutex_init(&port->lock);
  846. port->mad_agent = ib_register_mad_agent(cport->ibdev, i,
  847. IB_QPT_GSI, &reg_req,
  848. IB_MGMT_RMPP_VERSION,
  849. vema_send, vema_recv,
  850. port, 0);
  851. if (IS_ERR(port->mad_agent)) {
  852. ret = PTR_ERR(port->mad_agent);
  853. port->mad_agent = NULL;
  854. mutex_destroy(&port->lock);
  855. idr_destroy(&port->vport_idr);
  856. vema_unregister(cport);
  857. return ret;
  858. }
  859. }
  860. return 0;
  861. }
  862. /**
  863. * opa_vnic_ctrl_config_dev -- This function sends a trap to the EM
  864. * by way of ib_modify_port to indicate support for ethernet on the
  865. * fabric.
  866. * @cport: pointer to control port
  867. * @en: enable or disable ethernet on fabric support
  868. */
  869. static void opa_vnic_ctrl_config_dev(struct opa_vnic_ctrl_port *cport, bool en)
  870. {
  871. struct ib_port_modify pm = { 0 };
  872. int i;
  873. if (en)
  874. pm.set_port_cap_mask = OPA_CAP_MASK3_IsEthOnFabricSupported;
  875. else
  876. pm.clr_port_cap_mask = OPA_CAP_MASK3_IsEthOnFabricSupported;
  877. for (i = 1; i <= cport->num_ports; i++)
  878. ib_modify_port(cport->ibdev, i, IB_PORT_OPA_MASK_CHG, &pm);
  879. }
  880. /**
  881. * opa_vnic_vema_add_one -- Handle new ib device
  882. * @device: ib device pointer
  883. *
  884. * Allocate the vnic control port and initialize it.
  885. */
  886. static void opa_vnic_vema_add_one(struct ib_device *device)
  887. {
  888. struct opa_vnic_ctrl_port *cport;
  889. int rc, size = sizeof(*cport);
  890. if (!rdma_cap_opa_vnic(device))
  891. return;
  892. size += device->phys_port_cnt * sizeof(struct opa_vnic_vema_port);
  893. cport = kzalloc(size, GFP_KERNEL);
  894. if (!cport)
  895. return;
  896. cport->num_ports = device->phys_port_cnt;
  897. cport->ibdev = device;
  898. /* Initialize opa vnic management agent (vema) */
  899. rc = vema_register(cport);
  900. if (!rc)
  901. c_info("VNIC client initialized\n");
  902. ib_set_client_data(device, &opa_vnic_client, cport);
  903. opa_vnic_ctrl_config_dev(cport, true);
  904. }
  905. /**
  906. * opa_vnic_vema_rem_one -- Handle ib device removal
  907. * @device: ib device pointer
  908. * @client_data: ib client data
  909. *
  910. * Uninitialize and free the vnic control port.
  911. */
  912. static void opa_vnic_vema_rem_one(struct ib_device *device,
  913. void *client_data)
  914. {
  915. struct opa_vnic_ctrl_port *cport = client_data;
  916. if (!cport)
  917. return;
  918. c_info("removing VNIC client\n");
  919. opa_vnic_ctrl_config_dev(cport, false);
  920. vema_unregister(cport);
  921. kfree(cport);
  922. }
  923. static int __init opa_vnic_init(void)
  924. {
  925. int rc;
  926. pr_info("OPA Virtual Network Driver - v%s\n",
  927. opa_vnic_driver_version);
  928. rc = ib_register_client(&opa_vnic_client);
  929. if (rc)
  930. pr_err("VNIC driver register failed %d\n", rc);
  931. return rc;
  932. }
  933. module_init(opa_vnic_init);
  934. static void opa_vnic_deinit(void)
  935. {
  936. ib_unregister_client(&opa_vnic_client);
  937. }
  938. module_exit(opa_vnic_deinit);
  939. MODULE_LICENSE("Dual BSD/GPL");
  940. MODULE_AUTHOR("Intel Corporation");
  941. MODULE_DESCRIPTION("Intel OPA Virtual Network driver");