11bd671abSVishwanathapura, Niranjana /*
21bd671abSVishwanathapura, Niranjana * Copyright(c) 2017 Intel Corporation.
3*4892298cSScott Breyer * Copyright(c) 2021 Cornelis Networks.
41bd671abSVishwanathapura, Niranjana *
51bd671abSVishwanathapura, Niranjana * This file is provided under a dual BSD/GPLv2 license. When using or
61bd671abSVishwanathapura, Niranjana * redistributing this file, you may do so under either license.
71bd671abSVishwanathapura, Niranjana *
81bd671abSVishwanathapura, Niranjana * GPL LICENSE SUMMARY
91bd671abSVishwanathapura, Niranjana *
101bd671abSVishwanathapura, Niranjana * This program is free software; you can redistribute it and/or modify
111bd671abSVishwanathapura, Niranjana * it under the terms of version 2 of the GNU General Public License as
121bd671abSVishwanathapura, Niranjana * published by the Free Software Foundation.
131bd671abSVishwanathapura, Niranjana *
141bd671abSVishwanathapura, Niranjana * This program is distributed in the hope that it will be useful, but
151bd671abSVishwanathapura, Niranjana * WITHOUT ANY WARRANTY; without even the implied warranty of
161bd671abSVishwanathapura, Niranjana * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
171bd671abSVishwanathapura, Niranjana * General Public License for more details.
181bd671abSVishwanathapura, Niranjana *
191bd671abSVishwanathapura, Niranjana * BSD LICENSE
201bd671abSVishwanathapura, Niranjana *
211bd671abSVishwanathapura, Niranjana * Redistribution and use in source and binary forms, with or without
221bd671abSVishwanathapura, Niranjana * modification, are permitted provided that the following conditions
231bd671abSVishwanathapura, Niranjana * are met:
241bd671abSVishwanathapura, Niranjana *
251bd671abSVishwanathapura, Niranjana * - Redistributions of source code must retain the above copyright
261bd671abSVishwanathapura, Niranjana * notice, this list of conditions and the following disclaimer.
271bd671abSVishwanathapura, Niranjana * - Redistributions in binary form must reproduce the above copyright
281bd671abSVishwanathapura, Niranjana * notice, this list of conditions and the following disclaimer in
291bd671abSVishwanathapura, Niranjana * the documentation and/or other materials provided with the
301bd671abSVishwanathapura, Niranjana * distribution.
311bd671abSVishwanathapura, Niranjana * - Neither the name of Intel Corporation nor the names of its
321bd671abSVishwanathapura, Niranjana * contributors may be used to endorse or promote products derived
331bd671abSVishwanathapura, Niranjana * from this software without specific prior written permission.
341bd671abSVishwanathapura, Niranjana *
351bd671abSVishwanathapura, Niranjana * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
361bd671abSVishwanathapura, Niranjana * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
371bd671abSVishwanathapura, Niranjana * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
381bd671abSVishwanathapura, Niranjana * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
391bd671abSVishwanathapura, Niranjana * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
401bd671abSVishwanathapura, Niranjana * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
411bd671abSVishwanathapura, Niranjana * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
421bd671abSVishwanathapura, Niranjana * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
431bd671abSVishwanathapura, Niranjana * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
441bd671abSVishwanathapura, Niranjana * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
451bd671abSVishwanathapura, Niranjana * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
461bd671abSVishwanathapura, Niranjana *
471bd671abSVishwanathapura, Niranjana */
481bd671abSVishwanathapura, Niranjana
491bd671abSVishwanathapura, Niranjana /*
50*4892298cSScott Breyer * This file contains OPX Virtual Network Interface Controller (VNIC)
511bd671abSVishwanathapura, Niranjana * Ethernet Management Agent (EMA) driver
521bd671abSVishwanathapura, Niranjana */
531bd671abSVishwanathapura, Niranjana
541bd671abSVishwanathapura, Niranjana #include <linux/module.h>
55fae7a699SMatthew Wilcox #include <linux/xarray.h>
561bd671abSVishwanathapura, Niranjana #include <rdma/ib_addr.h>
57cb49366fSVishwanathapura, Niranjana #include <rdma/ib_verbs.h>
58cb49366fSVishwanathapura, Niranjana #include <rdma/opa_smi.h>
59cb49366fSVishwanathapura, Niranjana #include <rdma/opa_port_info.h>
601bd671abSVishwanathapura, Niranjana
611bd671abSVishwanathapura, Niranjana #include "opa_vnic_internal.h"
621bd671abSVishwanathapura, Niranjana
631bd671abSVishwanathapura, Niranjana char opa_vnic_driver_name[] = "opa_vnic";
641bd671abSVishwanathapura, Niranjana
651bd671abSVishwanathapura, Niranjana /*
661bd671abSVishwanathapura, Niranjana * The trap service level is kept in bits 3 to 7 in the trap_sl_rsvd
671bd671abSVishwanathapura, Niranjana * field in the class port info MAD.
681bd671abSVishwanathapura, Niranjana */
691bd671abSVishwanathapura, Niranjana #define GET_TRAP_SL_FROM_CLASS_PORT_INFO(x) (((x) >> 3) & 0x1f)
701bd671abSVishwanathapura, Niranjana
711bd671abSVishwanathapura, Niranjana /* Cap trap bursts to a reasonable limit good for normal cases */
721bd671abSVishwanathapura, Niranjana #define OPA_VNIC_TRAP_BURST_LIMIT 4
731bd671abSVishwanathapura, Niranjana
741bd671abSVishwanathapura, Niranjana /*
751bd671abSVishwanathapura, Niranjana * VNIC trap limit timeout.
761bd671abSVishwanathapura, Niranjana * Inverse of cap2_mask response time out (1.0737 secs) = 0.9
771bd671abSVishwanathapura, Niranjana * secs approx IB spec 13.4.6.2.1 PortInfoSubnetTimeout and
781bd671abSVishwanathapura, Niranjana * 13.4.9 Traps.
791bd671abSVishwanathapura, Niranjana */
801bd671abSVishwanathapura, Niranjana #define OPA_VNIC_TRAP_TIMEOUT ((4096 * (1UL << 18)) / 1000)
811bd671abSVishwanathapura, Niranjana
821bd671abSVishwanathapura, Niranjana #define OPA_VNIC_UNSUP_ATTR \
831bd671abSVishwanathapura, Niranjana cpu_to_be16(IB_MGMT_MAD_STATUS_UNSUPPORTED_METHOD_ATTRIB)
841bd671abSVishwanathapura, Niranjana
851bd671abSVishwanathapura, Niranjana #define OPA_VNIC_INVAL_ATTR \
861bd671abSVishwanathapura, Niranjana cpu_to_be16(IB_MGMT_MAD_STATUS_INVALID_ATTRIB_VALUE)
871bd671abSVishwanathapura, Niranjana
881bd671abSVishwanathapura, Niranjana #define OPA_VNIC_CLASS_CAP_TRAP 0x1
891bd671abSVishwanathapura, Niranjana
901bd671abSVishwanathapura, Niranjana /* Maximum number of VNIC ports supported */
911bd671abSVishwanathapura, Niranjana #define OPA_VNIC_MAX_NUM_VPORT 255
921bd671abSVishwanathapura, Niranjana
931bd671abSVishwanathapura, Niranjana /**
941bd671abSVishwanathapura, Niranjana * struct opa_vnic_vema_port -- VNIC VEMA port details
951bd671abSVishwanathapura, Niranjana * @cport: pointer to port
961bd671abSVishwanathapura, Niranjana * @mad_agent: pointer to mad agent for port
971bd671abSVishwanathapura, Niranjana * @class_port_info: Class port info information.
981bd671abSVishwanathapura, Niranjana * @tid: Transaction id
991bd671abSVishwanathapura, Niranjana * @port_num: OPA port number
100fae7a699SMatthew Wilcox * @vports: vnic ports
1011bd671abSVishwanathapura, Niranjana * @event_handler: ib event handler
1021bd671abSVishwanathapura, Niranjana * @lock: adapter interface lock
1031bd671abSVishwanathapura, Niranjana */
1041bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_port {
1051bd671abSVishwanathapura, Niranjana struct opa_vnic_ctrl_port *cport;
1061bd671abSVishwanathapura, Niranjana struct ib_mad_agent *mad_agent;
1071bd671abSVishwanathapura, Niranjana struct opa_class_port_info class_port_info;
1081bd671abSVishwanathapura, Niranjana u64 tid;
1091bd671abSVishwanathapura, Niranjana u8 port_num;
110fae7a699SMatthew Wilcox struct xarray vports;
1111bd671abSVishwanathapura, Niranjana struct ib_event_handler event_handler;
1121bd671abSVishwanathapura, Niranjana
1131bd671abSVishwanathapura, Niranjana /* Lock to query/update network adapter */
1141bd671abSVishwanathapura, Niranjana struct mutex lock;
1151bd671abSVishwanathapura, Niranjana };
1161bd671abSVishwanathapura, Niranjana
11711a0ae4cSJason Gunthorpe static int opa_vnic_vema_add_one(struct ib_device *device);
1181bd671abSVishwanathapura, Niranjana static void opa_vnic_vema_rem_one(struct ib_device *device,
1191bd671abSVishwanathapura, Niranjana void *client_data);
1201bd671abSVishwanathapura, Niranjana
1211bd671abSVishwanathapura, Niranjana static struct ib_client opa_vnic_client = {
1221bd671abSVishwanathapura, Niranjana .name = opa_vnic_driver_name,
1231bd671abSVishwanathapura, Niranjana .add = opa_vnic_vema_add_one,
1241bd671abSVishwanathapura, Niranjana .remove = opa_vnic_vema_rem_one,
1251bd671abSVishwanathapura, Niranjana };
1261bd671abSVishwanathapura, Niranjana
1271bd671abSVishwanathapura, Niranjana /**
1281bd671abSVishwanathapura, Niranjana * vema_get_vport_num -- Get the vnic from the mad
1291bd671abSVishwanathapura, Niranjana * @recvd_mad: Received mad
1301bd671abSVishwanathapura, Niranjana *
1311bd671abSVishwanathapura, Niranjana * Return: returns value of the vnic port number
1321bd671abSVishwanathapura, Niranjana */
vema_get_vport_num(struct opa_vnic_vema_mad * recvd_mad)1331bd671abSVishwanathapura, Niranjana static inline u8 vema_get_vport_num(struct opa_vnic_vema_mad *recvd_mad)
1341bd671abSVishwanathapura, Niranjana {
1351bd671abSVishwanathapura, Niranjana return be32_to_cpu(recvd_mad->mad_hdr.attr_mod) & 0xff;
1361bd671abSVishwanathapura, Niranjana }
1371bd671abSVishwanathapura, Niranjana
1381bd671abSVishwanathapura, Niranjana /**
1391bd671abSVishwanathapura, Niranjana * vema_get_vport_adapter -- Get vnic port adapter from recvd mad
1401bd671abSVishwanathapura, Niranjana * @recvd_mad: received mad
1411bd671abSVishwanathapura, Niranjana * @port: ptr to port struct on which MAD was recvd
1421bd671abSVishwanathapura, Niranjana *
1431bd671abSVishwanathapura, Niranjana * Return: vnic adapter
1441bd671abSVishwanathapura, Niranjana */
1451bd671abSVishwanathapura, Niranjana static inline struct opa_vnic_adapter *
vema_get_vport_adapter(struct opa_vnic_vema_mad * recvd_mad,struct opa_vnic_vema_port * port)1461bd671abSVishwanathapura, Niranjana vema_get_vport_adapter(struct opa_vnic_vema_mad *recvd_mad,
1471bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_port *port)
1481bd671abSVishwanathapura, Niranjana {
1491bd671abSVishwanathapura, Niranjana u8 vport_num = vema_get_vport_num(recvd_mad);
1501bd671abSVishwanathapura, Niranjana
151fae7a699SMatthew Wilcox return xa_load(&port->vports, vport_num);
1521bd671abSVishwanathapura, Niranjana }
1531bd671abSVishwanathapura, Niranjana
1541bd671abSVishwanathapura, Niranjana /**
1551bd671abSVishwanathapura, Niranjana * vema_mac_tbl_req_ok -- Check if mac request has correct values
1561bd671abSVishwanathapura, Niranjana * @mac_tbl: mac table
1571bd671abSVishwanathapura, Niranjana *
1581bd671abSVishwanathapura, Niranjana * This function checks for the validity of the offset and number of
1591bd671abSVishwanathapura, Niranjana * entries required.
1601bd671abSVishwanathapura, Niranjana *
1611bd671abSVishwanathapura, Niranjana * Return: true if offset and num_entries are valid
1621bd671abSVishwanathapura, Niranjana */
vema_mac_tbl_req_ok(struct opa_veswport_mactable * mac_tbl)1631bd671abSVishwanathapura, Niranjana static inline bool vema_mac_tbl_req_ok(struct opa_veswport_mactable *mac_tbl)
1641bd671abSVishwanathapura, Niranjana {
1651bd671abSVishwanathapura, Niranjana u16 offset, num_entries;
1661bd671abSVishwanathapura, Niranjana u16 req_entries = ((OPA_VNIC_EMA_DATA - sizeof(*mac_tbl)) /
1671bd671abSVishwanathapura, Niranjana sizeof(mac_tbl->tbl_entries[0]));
1681bd671abSVishwanathapura, Niranjana
1691bd671abSVishwanathapura, Niranjana offset = be16_to_cpu(mac_tbl->offset);
1701bd671abSVishwanathapura, Niranjana num_entries = be16_to_cpu(mac_tbl->num_entries);
1711bd671abSVishwanathapura, Niranjana
1721bd671abSVishwanathapura, Niranjana return ((num_entries <= req_entries) &&
1731bd671abSVishwanathapura, Niranjana (offset + num_entries <= OPA_VNIC_MAC_TBL_MAX_ENTRIES));
1741bd671abSVishwanathapura, Niranjana }
1751bd671abSVishwanathapura, Niranjana
1761bd671abSVishwanathapura, Niranjana /*
1771bd671abSVishwanathapura, Niranjana * Return the power on default values in the port info structure
1781bd671abSVishwanathapura, Niranjana * in big endian format as required by MAD.
1791bd671abSVishwanathapura, Niranjana */
vema_get_pod_values(struct opa_veswport_info * port_info)1801bd671abSVishwanathapura, Niranjana static inline void vema_get_pod_values(struct opa_veswport_info *port_info)
1811bd671abSVishwanathapura, Niranjana {
1821bd671abSVishwanathapura, Niranjana memset(port_info, 0, sizeof(*port_info));
1831bd671abSVishwanathapura, Niranjana port_info->vport.max_mac_tbl_ent =
1841bd671abSVishwanathapura, Niranjana cpu_to_be16(OPA_VNIC_MAC_TBL_MAX_ENTRIES);
1851bd671abSVishwanathapura, Niranjana port_info->vport.max_smac_ent =
1861bd671abSVishwanathapura, Niranjana cpu_to_be16(OPA_VNIC_MAX_SMAC_LIMIT);
1871bd671abSVishwanathapura, Niranjana port_info->vport.oper_state = OPA_VNIC_STATE_DROP_ALL;
1881bd671abSVishwanathapura, Niranjana port_info->vport.config_state = OPA_VNIC_STATE_DROP_ALL;
1897f291d28SNiranjana Vishwanathapura port_info->vesw.eth_mtu = cpu_to_be16(ETH_DATA_LEN);
1901bd671abSVishwanathapura, Niranjana }
1911bd671abSVishwanathapura, Niranjana
1921bd671abSVishwanathapura, Niranjana /**
1931bd671abSVishwanathapura, Niranjana * vema_add_vport -- Add a new vnic port
1941bd671abSVishwanathapura, Niranjana * @port: ptr to opa_vnic_vema_port struct
1951bd671abSVishwanathapura, Niranjana * @vport_num: vnic port number (to be added)
1961bd671abSVishwanathapura, Niranjana *
1971bd671abSVishwanathapura, Niranjana * Return a pointer to the vnic adapter structure
1981bd671abSVishwanathapura, Niranjana */
vema_add_vport(struct opa_vnic_vema_port * port,u8 vport_num)1991bd671abSVishwanathapura, Niranjana static struct opa_vnic_adapter *vema_add_vport(struct opa_vnic_vema_port *port,
2001bd671abSVishwanathapura, Niranjana u8 vport_num)
2011bd671abSVishwanathapura, Niranjana {
2021bd671abSVishwanathapura, Niranjana struct opa_vnic_ctrl_port *cport = port->cport;
2031bd671abSVishwanathapura, Niranjana struct opa_vnic_adapter *adapter;
2041bd671abSVishwanathapura, Niranjana
2051bd671abSVishwanathapura, Niranjana adapter = opa_vnic_add_netdev(cport->ibdev, port->port_num, vport_num);
2061bd671abSVishwanathapura, Niranjana if (!IS_ERR(adapter)) {
2071bd671abSVishwanathapura, Niranjana int rc;
2081bd671abSVishwanathapura, Niranjana
2091bd671abSVishwanathapura, Niranjana adapter->cport = cport;
210fae7a699SMatthew Wilcox rc = xa_insert(&port->vports, vport_num, adapter, GFP_KERNEL);
2111bd671abSVishwanathapura, Niranjana if (rc < 0) {
2121bd671abSVishwanathapura, Niranjana opa_vnic_rem_netdev(adapter);
2131bd671abSVishwanathapura, Niranjana adapter = ERR_PTR(rc);
2141bd671abSVishwanathapura, Niranjana }
2151bd671abSVishwanathapura, Niranjana }
2161bd671abSVishwanathapura, Niranjana
2171bd671abSVishwanathapura, Niranjana return adapter;
2181bd671abSVishwanathapura, Niranjana }
2191bd671abSVishwanathapura, Niranjana
2201bd671abSVishwanathapura, Niranjana /**
2211bd671abSVishwanathapura, Niranjana * vema_get_class_port_info -- Get class info for port
2221bd671abSVishwanathapura, Niranjana * @port: Port on whic MAD was received
2231bd671abSVishwanathapura, Niranjana * @recvd_mad: pointer to the received mad
2241bd671abSVishwanathapura, Niranjana * @rsp_mad: pointer to respose mad
2251bd671abSVishwanathapura, Niranjana *
2261bd671abSVishwanathapura, Niranjana * This function copies the latest class port info value set for the
2271bd671abSVishwanathapura, Niranjana * port and stores it for generating traps
2281bd671abSVishwanathapura, Niranjana */
vema_get_class_port_info(struct opa_vnic_vema_port * port,struct opa_vnic_vema_mad * recvd_mad,struct opa_vnic_vema_mad * rsp_mad)2291bd671abSVishwanathapura, Niranjana static void vema_get_class_port_info(struct opa_vnic_vema_port *port,
2301bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *recvd_mad,
2311bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *rsp_mad)
2321bd671abSVishwanathapura, Niranjana {
2331bd671abSVishwanathapura, Niranjana struct opa_class_port_info *port_info;
2341bd671abSVishwanathapura, Niranjana
2351bd671abSVishwanathapura, Niranjana port_info = (struct opa_class_port_info *)rsp_mad->data;
2361bd671abSVishwanathapura, Niranjana memcpy(port_info, &port->class_port_info, sizeof(*port_info));
23790eef9f7SZheng Yongjun port_info->base_version = OPA_MGMT_BASE_VERSION;
2381bd671abSVishwanathapura, Niranjana port_info->class_version = OPA_EMA_CLASS_VERSION;
2391bd671abSVishwanathapura, Niranjana
2401bd671abSVishwanathapura, Niranjana /*
2411bd671abSVishwanathapura, Niranjana * Set capability mask bit indicating agent generates traps,
2421bd671abSVishwanathapura, Niranjana * and set the maximum number of VNIC ports supported.
2431bd671abSVishwanathapura, Niranjana */
2441bd671abSVishwanathapura, Niranjana port_info->cap_mask = cpu_to_be16((OPA_VNIC_CLASS_CAP_TRAP |
2451bd671abSVishwanathapura, Niranjana (OPA_VNIC_MAX_NUM_VPORT << 8)));
2461bd671abSVishwanathapura, Niranjana
2471bd671abSVishwanathapura, Niranjana /*
2481bd671abSVishwanathapura, Niranjana * Since a get routine is always sent by the EM first we
2491bd671abSVishwanathapura, Niranjana * set the expected response time to
2501bd671abSVishwanathapura, Niranjana * 4.096 usec * 2^18 == 1.0737 sec here.
2511bd671abSVishwanathapura, Niranjana */
2521bd671abSVishwanathapura, Niranjana port_info->cap_mask2_resp_time = cpu_to_be32(18);
2531bd671abSVishwanathapura, Niranjana }
2541bd671abSVishwanathapura, Niranjana
2551bd671abSVishwanathapura, Niranjana /**
2561bd671abSVishwanathapura, Niranjana * vema_set_class_port_info -- Get class info for port
2571bd671abSVishwanathapura, Niranjana * @port: Port on whic MAD was received
2581bd671abSVishwanathapura, Niranjana * @recvd_mad: pointer to the received mad
2591bd671abSVishwanathapura, Niranjana * @rsp_mad: pointer to respose mad
2601bd671abSVishwanathapura, Niranjana *
2611bd671abSVishwanathapura, Niranjana * This function updates the port class info for the specific vnic
2621bd671abSVishwanathapura, Niranjana * and sets up the response mad data
2631bd671abSVishwanathapura, Niranjana */
vema_set_class_port_info(struct opa_vnic_vema_port * port,struct opa_vnic_vema_mad * recvd_mad,struct opa_vnic_vema_mad * rsp_mad)2641bd671abSVishwanathapura, Niranjana static void vema_set_class_port_info(struct opa_vnic_vema_port *port,
2651bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *recvd_mad,
2661bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *rsp_mad)
2671bd671abSVishwanathapura, Niranjana {
2681bd671abSVishwanathapura, Niranjana memcpy(&port->class_port_info, recvd_mad->data,
2691bd671abSVishwanathapura, Niranjana sizeof(port->class_port_info));
2701bd671abSVishwanathapura, Niranjana
2711bd671abSVishwanathapura, Niranjana vema_get_class_port_info(port, recvd_mad, rsp_mad);
2721bd671abSVishwanathapura, Niranjana }
2731bd671abSVishwanathapura, Niranjana
2741bd671abSVishwanathapura, Niranjana /**
2751bd671abSVishwanathapura, Niranjana * vema_get_veswport_info -- Get veswport info
2761bd671abSVishwanathapura, Niranjana * @port: source port on which MAD was received
2771bd671abSVishwanathapura, Niranjana * @recvd_mad: pointer to the received mad
2781bd671abSVishwanathapura, Niranjana * @rsp_mad: pointer to respose mad
2791bd671abSVishwanathapura, Niranjana */
vema_get_veswport_info(struct opa_vnic_vema_port * port,struct opa_vnic_vema_mad * recvd_mad,struct opa_vnic_vema_mad * rsp_mad)2801bd671abSVishwanathapura, Niranjana static void vema_get_veswport_info(struct opa_vnic_vema_port *port,
2811bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *recvd_mad,
2821bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *rsp_mad)
2831bd671abSVishwanathapura, Niranjana {
2841bd671abSVishwanathapura, Niranjana struct opa_veswport_info *port_info =
2851bd671abSVishwanathapura, Niranjana (struct opa_veswport_info *)rsp_mad->data;
2861bd671abSVishwanathapura, Niranjana struct opa_vnic_adapter *adapter;
2871bd671abSVishwanathapura, Niranjana
2881bd671abSVishwanathapura, Niranjana adapter = vema_get_vport_adapter(recvd_mad, port);
2891bd671abSVishwanathapura, Niranjana if (adapter) {
2901bd671abSVishwanathapura, Niranjana memset(port_info, 0, sizeof(*port_info));
2911bd671abSVishwanathapura, Niranjana opa_vnic_get_vesw_info(adapter, &port_info->vesw);
2921bd671abSVishwanathapura, Niranjana opa_vnic_get_per_veswport_info(adapter,
2931bd671abSVishwanathapura, Niranjana &port_info->vport);
2941bd671abSVishwanathapura, Niranjana } else {
2951bd671abSVishwanathapura, Niranjana vema_get_pod_values(port_info);
2961bd671abSVishwanathapura, Niranjana }
2971bd671abSVishwanathapura, Niranjana }
2981bd671abSVishwanathapura, Niranjana
2991bd671abSVishwanathapura, Niranjana /**
3001bd671abSVishwanathapura, Niranjana * vema_set_veswport_info -- Set veswport info
3011bd671abSVishwanathapura, Niranjana * @port: source port on which MAD was received
3021bd671abSVishwanathapura, Niranjana * @recvd_mad: pointer to the received mad
3031bd671abSVishwanathapura, Niranjana * @rsp_mad: pointer to respose mad
3041bd671abSVishwanathapura, Niranjana *
3051bd671abSVishwanathapura, Niranjana * This function gets the port class infor for vnic
3061bd671abSVishwanathapura, Niranjana */
vema_set_veswport_info(struct opa_vnic_vema_port * port,struct opa_vnic_vema_mad * recvd_mad,struct opa_vnic_vema_mad * rsp_mad)3071bd671abSVishwanathapura, Niranjana static void vema_set_veswport_info(struct opa_vnic_vema_port *port,
3081bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *recvd_mad,
3091bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *rsp_mad)
3101bd671abSVishwanathapura, Niranjana {
3111bd671abSVishwanathapura, Niranjana struct opa_vnic_ctrl_port *cport = port->cport;
3121bd671abSVishwanathapura, Niranjana struct opa_veswport_info *port_info;
3131bd671abSVishwanathapura, Niranjana struct opa_vnic_adapter *adapter;
3141bd671abSVishwanathapura, Niranjana u8 vport_num;
3151bd671abSVishwanathapura, Niranjana
3161bd671abSVishwanathapura, Niranjana vport_num = vema_get_vport_num(recvd_mad);
3171bd671abSVishwanathapura, Niranjana
3181bd671abSVishwanathapura, Niranjana adapter = vema_get_vport_adapter(recvd_mad, port);
3191bd671abSVishwanathapura, Niranjana if (!adapter) {
3201bd671abSVishwanathapura, Niranjana adapter = vema_add_vport(port, vport_num);
3211bd671abSVishwanathapura, Niranjana if (IS_ERR(adapter)) {
3221bd671abSVishwanathapura, Niranjana c_err("failed to add vport %d: %ld\n",
3231bd671abSVishwanathapura, Niranjana vport_num, PTR_ERR(adapter));
3241bd671abSVishwanathapura, Niranjana goto err_exit;
3251bd671abSVishwanathapura, Niranjana }
3261bd671abSVishwanathapura, Niranjana }
3271bd671abSVishwanathapura, Niranjana
3281bd671abSVishwanathapura, Niranjana port_info = (struct opa_veswport_info *)recvd_mad->data;
3291bd671abSVishwanathapura, Niranjana opa_vnic_set_vesw_info(adapter, &port_info->vesw);
3301bd671abSVishwanathapura, Niranjana opa_vnic_set_per_veswport_info(adapter, &port_info->vport);
3311bd671abSVishwanathapura, Niranjana
3321bd671abSVishwanathapura, Niranjana /* Process the new config settings */
3331bd671abSVishwanathapura, Niranjana opa_vnic_process_vema_config(adapter);
3341bd671abSVishwanathapura, Niranjana
3351bd671abSVishwanathapura, Niranjana vema_get_veswport_info(port, recvd_mad, rsp_mad);
3361bd671abSVishwanathapura, Niranjana return;
3371bd671abSVishwanathapura, Niranjana
3381bd671abSVishwanathapura, Niranjana err_exit:
3391bd671abSVishwanathapura, Niranjana rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
3401bd671abSVishwanathapura, Niranjana }
3411bd671abSVishwanathapura, Niranjana
3421bd671abSVishwanathapura, Niranjana /**
3431bd671abSVishwanathapura, Niranjana * vema_get_mac_entries -- Get MAC entries in VNIC MAC table
3441bd671abSVishwanathapura, Niranjana * @port: source port on which MAD was received
3451bd671abSVishwanathapura, Niranjana * @recvd_mad: pointer to the received mad
3461bd671abSVishwanathapura, Niranjana * @rsp_mad: pointer to respose mad
3471bd671abSVishwanathapura, Niranjana *
3481bd671abSVishwanathapura, Niranjana * This function gets the MAC entries that are programmed into
3491bd671abSVishwanathapura, Niranjana * the VNIC MAC forwarding table. It checks for the validity of
3501bd671abSVishwanathapura, Niranjana * the index into the MAC table and the number of entries that
3511bd671abSVishwanathapura, Niranjana * are to be retrieved.
3521bd671abSVishwanathapura, Niranjana */
vema_get_mac_entries(struct opa_vnic_vema_port * port,struct opa_vnic_vema_mad * recvd_mad,struct opa_vnic_vema_mad * rsp_mad)3531bd671abSVishwanathapura, Niranjana static void vema_get_mac_entries(struct opa_vnic_vema_port *port,
3541bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *recvd_mad,
3551bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *rsp_mad)
3561bd671abSVishwanathapura, Niranjana {
3571bd671abSVishwanathapura, Niranjana struct opa_veswport_mactable *mac_tbl_in, *mac_tbl_out;
3581bd671abSVishwanathapura, Niranjana struct opa_vnic_adapter *adapter;
3591bd671abSVishwanathapura, Niranjana
3601bd671abSVishwanathapura, Niranjana adapter = vema_get_vport_adapter(recvd_mad, port);
3611bd671abSVishwanathapura, Niranjana if (!adapter) {
3621bd671abSVishwanathapura, Niranjana rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
3631bd671abSVishwanathapura, Niranjana return;
3641bd671abSVishwanathapura, Niranjana }
3651bd671abSVishwanathapura, Niranjana
3661bd671abSVishwanathapura, Niranjana mac_tbl_in = (struct opa_veswport_mactable *)recvd_mad->data;
3671bd671abSVishwanathapura, Niranjana mac_tbl_out = (struct opa_veswport_mactable *)rsp_mad->data;
3681bd671abSVishwanathapura, Niranjana
3691bd671abSVishwanathapura, Niranjana if (vema_mac_tbl_req_ok(mac_tbl_in)) {
3701bd671abSVishwanathapura, Niranjana mac_tbl_out->offset = mac_tbl_in->offset;
3711bd671abSVishwanathapura, Niranjana mac_tbl_out->num_entries = mac_tbl_in->num_entries;
3721bd671abSVishwanathapura, Niranjana opa_vnic_query_mac_tbl(adapter, mac_tbl_out);
3731bd671abSVishwanathapura, Niranjana } else {
3741bd671abSVishwanathapura, Niranjana rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
3751bd671abSVishwanathapura, Niranjana }
3761bd671abSVishwanathapura, Niranjana }
3771bd671abSVishwanathapura, Niranjana
3781bd671abSVishwanathapura, Niranjana /**
3791bd671abSVishwanathapura, Niranjana * vema_set_mac_entries -- Set MAC entries in VNIC MAC table
3801bd671abSVishwanathapura, Niranjana * @port: source port on which MAD was received
3811bd671abSVishwanathapura, Niranjana * @recvd_mad: pointer to the received mad
3821bd671abSVishwanathapura, Niranjana * @rsp_mad: pointer to respose mad
3831bd671abSVishwanathapura, Niranjana *
3841bd671abSVishwanathapura, Niranjana * This function sets the MAC entries in the VNIC forwarding table
3851bd671abSVishwanathapura, Niranjana * It checks for the validity of the index and the number of forwarding
3861bd671abSVishwanathapura, Niranjana * table entries to be programmed.
3871bd671abSVishwanathapura, Niranjana */
vema_set_mac_entries(struct opa_vnic_vema_port * port,struct opa_vnic_vema_mad * recvd_mad,struct opa_vnic_vema_mad * rsp_mad)3881bd671abSVishwanathapura, Niranjana static void vema_set_mac_entries(struct opa_vnic_vema_port *port,
3891bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *recvd_mad,
3901bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *rsp_mad)
3911bd671abSVishwanathapura, Niranjana {
3921bd671abSVishwanathapura, Niranjana struct opa_veswport_mactable *mac_tbl;
3931bd671abSVishwanathapura, Niranjana struct opa_vnic_adapter *adapter;
3941bd671abSVishwanathapura, Niranjana
3951bd671abSVishwanathapura, Niranjana adapter = vema_get_vport_adapter(recvd_mad, port);
3961bd671abSVishwanathapura, Niranjana if (!adapter) {
3971bd671abSVishwanathapura, Niranjana rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
3981bd671abSVishwanathapura, Niranjana return;
3991bd671abSVishwanathapura, Niranjana }
4001bd671abSVishwanathapura, Niranjana
4011bd671abSVishwanathapura, Niranjana mac_tbl = (struct opa_veswport_mactable *)recvd_mad->data;
4021bd671abSVishwanathapura, Niranjana if (vema_mac_tbl_req_ok(mac_tbl)) {
4031bd671abSVishwanathapura, Niranjana if (opa_vnic_update_mac_tbl(adapter, mac_tbl))
4041bd671abSVishwanathapura, Niranjana rsp_mad->mad_hdr.status = OPA_VNIC_UNSUP_ATTR;
4051bd671abSVishwanathapura, Niranjana } else {
4061bd671abSVishwanathapura, Niranjana rsp_mad->mad_hdr.status = OPA_VNIC_UNSUP_ATTR;
4071bd671abSVishwanathapura, Niranjana }
4081bd671abSVishwanathapura, Niranjana vema_get_mac_entries(port, recvd_mad, rsp_mad);
4091bd671abSVishwanathapura, Niranjana }
4101bd671abSVishwanathapura, Niranjana
4111bd671abSVishwanathapura, Niranjana /**
4121bd671abSVishwanathapura, Niranjana * vema_set_delete_vesw -- Reset VESW info to POD values
4131bd671abSVishwanathapura, Niranjana * @port: source port on which MAD was received
4141bd671abSVishwanathapura, Niranjana * @recvd_mad: pointer to the received mad
4151bd671abSVishwanathapura, Niranjana * @rsp_mad: pointer to respose mad
4161bd671abSVishwanathapura, Niranjana *
4171bd671abSVishwanathapura, Niranjana * This function clears all the fields of veswport info for the requested vesw
4181bd671abSVishwanathapura, Niranjana * and sets them back to the power-on default values. It does not delete the
4191bd671abSVishwanathapura, Niranjana * vesw.
4201bd671abSVishwanathapura, Niranjana */
vema_set_delete_vesw(struct opa_vnic_vema_port * port,struct opa_vnic_vema_mad * recvd_mad,struct opa_vnic_vema_mad * rsp_mad)4211bd671abSVishwanathapura, Niranjana static void vema_set_delete_vesw(struct opa_vnic_vema_port *port,
4221bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *recvd_mad,
4231bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *rsp_mad)
4241bd671abSVishwanathapura, Niranjana {
4251bd671abSVishwanathapura, Niranjana struct opa_veswport_info *port_info =
4261bd671abSVishwanathapura, Niranjana (struct opa_veswport_info *)rsp_mad->data;
4271bd671abSVishwanathapura, Niranjana struct opa_vnic_adapter *adapter;
4281bd671abSVishwanathapura, Niranjana
4291bd671abSVishwanathapura, Niranjana adapter = vema_get_vport_adapter(recvd_mad, port);
4301bd671abSVishwanathapura, Niranjana if (!adapter) {
4311bd671abSVishwanathapura, Niranjana rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
4321bd671abSVishwanathapura, Niranjana return;
4331bd671abSVishwanathapura, Niranjana }
4341bd671abSVishwanathapura, Niranjana
4351bd671abSVishwanathapura, Niranjana vema_get_pod_values(port_info);
4361bd671abSVishwanathapura, Niranjana opa_vnic_set_vesw_info(adapter, &port_info->vesw);
4371bd671abSVishwanathapura, Niranjana opa_vnic_set_per_veswport_info(adapter, &port_info->vport);
4381bd671abSVishwanathapura, Niranjana
4391bd671abSVishwanathapura, Niranjana /* Process the new config settings */
4401bd671abSVishwanathapura, Niranjana opa_vnic_process_vema_config(adapter);
4411bd671abSVishwanathapura, Niranjana
4421bd671abSVishwanathapura, Niranjana opa_vnic_release_mac_tbl(adapter);
4431bd671abSVishwanathapura, Niranjana
4441bd671abSVishwanathapura, Niranjana vema_get_veswport_info(port, recvd_mad, rsp_mad);
4451bd671abSVishwanathapura, Niranjana }
4461bd671abSVishwanathapura, Niranjana
4471bd671abSVishwanathapura, Niranjana /**
4481bd671abSVishwanathapura, Niranjana * vema_get_mac_list -- Get the unicast/multicast macs.
4491bd671abSVishwanathapura, Niranjana * @port: source port on which MAD was received
4501bd671abSVishwanathapura, Niranjana * @recvd_mad: Received mad contains fields to set vnic parameters
4511bd671abSVishwanathapura, Niranjana * @rsp_mad: Response mad to be built
4521bd671abSVishwanathapura, Niranjana * @attr_id: Attribute ID indicating multicast or unicast mac list
4531bd671abSVishwanathapura, Niranjana */
vema_get_mac_list(struct opa_vnic_vema_port * port,struct opa_vnic_vema_mad * recvd_mad,struct opa_vnic_vema_mad * rsp_mad,u16 attr_id)4541bd671abSVishwanathapura, Niranjana static void vema_get_mac_list(struct opa_vnic_vema_port *port,
4551bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *recvd_mad,
4561bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *rsp_mad,
4571bd671abSVishwanathapura, Niranjana u16 attr_id)
4581bd671abSVishwanathapura, Niranjana {
4591bd671abSVishwanathapura, Niranjana struct opa_veswport_iface_macs *macs_in, *macs_out;
4601bd671abSVishwanathapura, Niranjana int max_entries = (OPA_VNIC_EMA_DATA - sizeof(*macs_out)) / ETH_ALEN;
4611bd671abSVishwanathapura, Niranjana struct opa_vnic_adapter *adapter;
4621bd671abSVishwanathapura, Niranjana
4631bd671abSVishwanathapura, Niranjana adapter = vema_get_vport_adapter(recvd_mad, port);
4641bd671abSVishwanathapura, Niranjana if (!adapter) {
4651bd671abSVishwanathapura, Niranjana rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
4661bd671abSVishwanathapura, Niranjana return;
4671bd671abSVishwanathapura, Niranjana }
4681bd671abSVishwanathapura, Niranjana
4691bd671abSVishwanathapura, Niranjana macs_in = (struct opa_veswport_iface_macs *)recvd_mad->data;
4701bd671abSVishwanathapura, Niranjana macs_out = (struct opa_veswport_iface_macs *)rsp_mad->data;
4711bd671abSVishwanathapura, Niranjana
4721bd671abSVishwanathapura, Niranjana macs_out->start_idx = macs_in->start_idx;
4731bd671abSVishwanathapura, Niranjana if (macs_in->num_macs_in_msg)
4741bd671abSVishwanathapura, Niranjana macs_out->num_macs_in_msg = macs_in->num_macs_in_msg;
4751bd671abSVishwanathapura, Niranjana else
4761bd671abSVishwanathapura, Niranjana macs_out->num_macs_in_msg = cpu_to_be16(max_entries);
4771bd671abSVishwanathapura, Niranjana
4781bd671abSVishwanathapura, Niranjana if (attr_id == OPA_EM_ATTR_IFACE_MCAST_MACS)
4791bd671abSVishwanathapura, Niranjana opa_vnic_query_mcast_macs(adapter, macs_out);
4801bd671abSVishwanathapura, Niranjana else
4811bd671abSVishwanathapura, Niranjana opa_vnic_query_ucast_macs(adapter, macs_out);
4821bd671abSVishwanathapura, Niranjana }
4831bd671abSVishwanathapura, Niranjana
4841bd671abSVishwanathapura, Niranjana /**
4851bd671abSVishwanathapura, Niranjana * vema_get_summary_counters -- Gets summary counters.
4861bd671abSVishwanathapura, Niranjana * @port: source port on which MAD was received
4871bd671abSVishwanathapura, Niranjana * @recvd_mad: Received mad contains fields to set vnic parameters
4881bd671abSVishwanathapura, Niranjana * @rsp_mad: Response mad to be built
4891bd671abSVishwanathapura, Niranjana */
vema_get_summary_counters(struct opa_vnic_vema_port * port,struct opa_vnic_vema_mad * recvd_mad,struct opa_vnic_vema_mad * rsp_mad)4901bd671abSVishwanathapura, Niranjana static void vema_get_summary_counters(struct opa_vnic_vema_port *port,
4911bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *recvd_mad,
4921bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *rsp_mad)
4931bd671abSVishwanathapura, Niranjana {
4941bd671abSVishwanathapura, Niranjana struct opa_veswport_summary_counters *cntrs;
4951bd671abSVishwanathapura, Niranjana struct opa_vnic_adapter *adapter;
4961bd671abSVishwanathapura, Niranjana
4971bd671abSVishwanathapura, Niranjana adapter = vema_get_vport_adapter(recvd_mad, port);
4981bd671abSVishwanathapura, Niranjana if (adapter) {
4991bd671abSVishwanathapura, Niranjana cntrs = (struct opa_veswport_summary_counters *)rsp_mad->data;
5001bd671abSVishwanathapura, Niranjana opa_vnic_get_summary_counters(adapter, cntrs);
5011bd671abSVishwanathapura, Niranjana } else {
5021bd671abSVishwanathapura, Niranjana rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
5031bd671abSVishwanathapura, Niranjana }
5041bd671abSVishwanathapura, Niranjana }
5051bd671abSVishwanathapura, Niranjana
5061bd671abSVishwanathapura, Niranjana /**
5071bd671abSVishwanathapura, Niranjana * vema_get_error_counters -- Gets summary counters.
5081bd671abSVishwanathapura, Niranjana * @port: source port on which MAD was received
5091bd671abSVishwanathapura, Niranjana * @recvd_mad: Received mad contains fields to set vnic parameters
5101bd671abSVishwanathapura, Niranjana * @rsp_mad: Response mad to be built
5111bd671abSVishwanathapura, Niranjana */
vema_get_error_counters(struct opa_vnic_vema_port * port,struct opa_vnic_vema_mad * recvd_mad,struct opa_vnic_vema_mad * rsp_mad)5121bd671abSVishwanathapura, Niranjana static void vema_get_error_counters(struct opa_vnic_vema_port *port,
5131bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *recvd_mad,
5141bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *rsp_mad)
5151bd671abSVishwanathapura, Niranjana {
5161bd671abSVishwanathapura, Niranjana struct opa_veswport_error_counters *cntrs;
5171bd671abSVishwanathapura, Niranjana struct opa_vnic_adapter *adapter;
5181bd671abSVishwanathapura, Niranjana
5191bd671abSVishwanathapura, Niranjana adapter = vema_get_vport_adapter(recvd_mad, port);
5201bd671abSVishwanathapura, Niranjana if (adapter) {
5211bd671abSVishwanathapura, Niranjana cntrs = (struct opa_veswport_error_counters *)rsp_mad->data;
5221bd671abSVishwanathapura, Niranjana opa_vnic_get_error_counters(adapter, cntrs);
5231bd671abSVishwanathapura, Niranjana } else {
5241bd671abSVishwanathapura, Niranjana rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
5251bd671abSVishwanathapura, Niranjana }
5261bd671abSVishwanathapura, Niranjana }
5271bd671abSVishwanathapura, Niranjana
5281bd671abSVishwanathapura, Niranjana /**
5291bd671abSVishwanathapura, Niranjana * vema_get -- Process received get MAD
5301bd671abSVishwanathapura, Niranjana * @port: source port on which MAD was received
5311bd671abSVishwanathapura, Niranjana * @recvd_mad: Received mad
5321bd671abSVishwanathapura, Niranjana * @rsp_mad: Response mad to be built
5331bd671abSVishwanathapura, Niranjana */
vema_get(struct opa_vnic_vema_port * port,struct opa_vnic_vema_mad * recvd_mad,struct opa_vnic_vema_mad * rsp_mad)5341bd671abSVishwanathapura, Niranjana static void vema_get(struct opa_vnic_vema_port *port,
5351bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *recvd_mad,
5361bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *rsp_mad)
5371bd671abSVishwanathapura, Niranjana {
5381bd671abSVishwanathapura, Niranjana u16 attr_id = be16_to_cpu(recvd_mad->mad_hdr.attr_id);
5391bd671abSVishwanathapura, Niranjana
5401bd671abSVishwanathapura, Niranjana switch (attr_id) {
5411bd671abSVishwanathapura, Niranjana case OPA_EM_ATTR_CLASS_PORT_INFO:
5421bd671abSVishwanathapura, Niranjana vema_get_class_port_info(port, recvd_mad, rsp_mad);
5431bd671abSVishwanathapura, Niranjana break;
5441bd671abSVishwanathapura, Niranjana case OPA_EM_ATTR_VESWPORT_INFO:
5451bd671abSVishwanathapura, Niranjana vema_get_veswport_info(port, recvd_mad, rsp_mad);
5461bd671abSVishwanathapura, Niranjana break;
5471bd671abSVishwanathapura, Niranjana case OPA_EM_ATTR_VESWPORT_MAC_ENTRIES:
5481bd671abSVishwanathapura, Niranjana vema_get_mac_entries(port, recvd_mad, rsp_mad);
5491bd671abSVishwanathapura, Niranjana break;
5501bd671abSVishwanathapura, Niranjana case OPA_EM_ATTR_IFACE_UCAST_MACS:
5511bd671abSVishwanathapura, Niranjana case OPA_EM_ATTR_IFACE_MCAST_MACS:
5521bd671abSVishwanathapura, Niranjana vema_get_mac_list(port, recvd_mad, rsp_mad, attr_id);
5531bd671abSVishwanathapura, Niranjana break;
5541bd671abSVishwanathapura, Niranjana case OPA_EM_ATTR_VESWPORT_SUMMARY_COUNTERS:
5551bd671abSVishwanathapura, Niranjana vema_get_summary_counters(port, recvd_mad, rsp_mad);
5561bd671abSVishwanathapura, Niranjana break;
5571bd671abSVishwanathapura, Niranjana case OPA_EM_ATTR_VESWPORT_ERROR_COUNTERS:
5581bd671abSVishwanathapura, Niranjana vema_get_error_counters(port, recvd_mad, rsp_mad);
5591bd671abSVishwanathapura, Niranjana break;
5601bd671abSVishwanathapura, Niranjana default:
5611bd671abSVishwanathapura, Niranjana rsp_mad->mad_hdr.status = OPA_VNIC_UNSUP_ATTR;
5621bd671abSVishwanathapura, Niranjana break;
5631bd671abSVishwanathapura, Niranjana }
5641bd671abSVishwanathapura, Niranjana }
5651bd671abSVishwanathapura, Niranjana
5661bd671abSVishwanathapura, Niranjana /**
5671bd671abSVishwanathapura, Niranjana * vema_set -- Process received set MAD
5681bd671abSVishwanathapura, Niranjana * @port: source port on which MAD was received
5691bd671abSVishwanathapura, Niranjana * @recvd_mad: Received mad contains fields to set vnic parameters
5701bd671abSVishwanathapura, Niranjana * @rsp_mad: Response mad to be built
5711bd671abSVishwanathapura, Niranjana */
vema_set(struct opa_vnic_vema_port * port,struct opa_vnic_vema_mad * recvd_mad,struct opa_vnic_vema_mad * rsp_mad)5721bd671abSVishwanathapura, Niranjana static void vema_set(struct opa_vnic_vema_port *port,
5731bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *recvd_mad,
5741bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *rsp_mad)
5751bd671abSVishwanathapura, Niranjana {
5761bd671abSVishwanathapura, Niranjana u16 attr_id = be16_to_cpu(recvd_mad->mad_hdr.attr_id);
5771bd671abSVishwanathapura, Niranjana
5781bd671abSVishwanathapura, Niranjana switch (attr_id) {
5791bd671abSVishwanathapura, Niranjana case OPA_EM_ATTR_CLASS_PORT_INFO:
5801bd671abSVishwanathapura, Niranjana vema_set_class_port_info(port, recvd_mad, rsp_mad);
5811bd671abSVishwanathapura, Niranjana break;
5821bd671abSVishwanathapura, Niranjana case OPA_EM_ATTR_VESWPORT_INFO:
5831bd671abSVishwanathapura, Niranjana vema_set_veswport_info(port, recvd_mad, rsp_mad);
5841bd671abSVishwanathapura, Niranjana break;
5851bd671abSVishwanathapura, Niranjana case OPA_EM_ATTR_VESWPORT_MAC_ENTRIES:
5861bd671abSVishwanathapura, Niranjana vema_set_mac_entries(port, recvd_mad, rsp_mad);
5871bd671abSVishwanathapura, Niranjana break;
5881bd671abSVishwanathapura, Niranjana case OPA_EM_ATTR_DELETE_VESW:
5891bd671abSVishwanathapura, Niranjana vema_set_delete_vesw(port, recvd_mad, rsp_mad);
5901bd671abSVishwanathapura, Niranjana break;
5911bd671abSVishwanathapura, Niranjana default:
5921bd671abSVishwanathapura, Niranjana rsp_mad->mad_hdr.status = OPA_VNIC_UNSUP_ATTR;
5931bd671abSVishwanathapura, Niranjana break;
5941bd671abSVishwanathapura, Niranjana }
5951bd671abSVishwanathapura, Niranjana }
5961bd671abSVishwanathapura, Niranjana
5971bd671abSVishwanathapura, Niranjana /**
5981bd671abSVishwanathapura, Niranjana * vema_send -- Send handler for VEMA MAD agent
5991bd671abSVishwanathapura, Niranjana * @mad_agent: pointer to the mad agent
6001bd671abSVishwanathapura, Niranjana * @mad_wc: pointer to mad send work completion information
6011bd671abSVishwanathapura, Niranjana *
6021bd671abSVishwanathapura, Niranjana * Free all the data structures associated with the sent MAD
6031bd671abSVishwanathapura, Niranjana */
vema_send(struct ib_mad_agent * mad_agent,struct ib_mad_send_wc * mad_wc)6041bd671abSVishwanathapura, Niranjana static void vema_send(struct ib_mad_agent *mad_agent,
6051bd671abSVishwanathapura, Niranjana struct ib_mad_send_wc *mad_wc)
6061bd671abSVishwanathapura, Niranjana {
6072553ba21SGal Pressman rdma_destroy_ah(mad_wc->send_buf->ah, RDMA_DESTROY_AH_SLEEPABLE);
6081bd671abSVishwanathapura, Niranjana ib_free_send_mad(mad_wc->send_buf);
6091bd671abSVishwanathapura, Niranjana }
6101bd671abSVishwanathapura, Niranjana
6111bd671abSVishwanathapura, Niranjana /**
6121bd671abSVishwanathapura, Niranjana * vema_recv -- Recv handler for VEMA MAD agent
6131bd671abSVishwanathapura, Niranjana * @mad_agent: pointer to the mad agent
6141bd671abSVishwanathapura, Niranjana * @send_buf: Send buffer if found, else NULL
6151bd671abSVishwanathapura, Niranjana * @mad_wc: pointer to mad send work completion information
6161bd671abSVishwanathapura, Niranjana *
6171bd671abSVishwanathapura, Niranjana * Handle only set and get methods and respond to other methods
6181bd671abSVishwanathapura, Niranjana * as unsupported. Allocate response buffer and address handle
6191bd671abSVishwanathapura, Niranjana * for the response MAD.
6201bd671abSVishwanathapura, Niranjana */
vema_recv(struct ib_mad_agent * mad_agent,struct ib_mad_send_buf * send_buf,struct ib_mad_recv_wc * mad_wc)6211bd671abSVishwanathapura, Niranjana static void vema_recv(struct ib_mad_agent *mad_agent,
6221bd671abSVishwanathapura, Niranjana struct ib_mad_send_buf *send_buf,
6231bd671abSVishwanathapura, Niranjana struct ib_mad_recv_wc *mad_wc)
6241bd671abSVishwanathapura, Niranjana {
6251bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_port *port;
6261bd671abSVishwanathapura, Niranjana struct ib_ah *ah;
6271bd671abSVishwanathapura, Niranjana struct ib_mad_send_buf *rsp;
6281bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad *vema_mad;
6291bd671abSVishwanathapura, Niranjana
6301bd671abSVishwanathapura, Niranjana if (!mad_wc || !mad_wc->recv_buf.mad)
6311bd671abSVishwanathapura, Niranjana return;
6321bd671abSVishwanathapura, Niranjana
6331bd671abSVishwanathapura, Niranjana port = mad_agent->context;
6341bd671abSVishwanathapura, Niranjana ah = ib_create_ah_from_wc(mad_agent->qp->pd, mad_wc->wc,
6351bd671abSVishwanathapura, Niranjana mad_wc->recv_buf.grh, mad_agent->port_num);
6361bd671abSVishwanathapura, Niranjana if (IS_ERR(ah))
6371bd671abSVishwanathapura, Niranjana goto free_recv_mad;
6381bd671abSVishwanathapura, Niranjana
6391bd671abSVishwanathapura, Niranjana rsp = ib_create_send_mad(mad_agent, mad_wc->wc->src_qp,
6401bd671abSVishwanathapura, Niranjana mad_wc->wc->pkey_index, 0,
6411bd671abSVishwanathapura, Niranjana IB_MGMT_VENDOR_HDR, OPA_VNIC_EMA_DATA,
6421bd671abSVishwanathapura, Niranjana GFP_KERNEL, OPA_MGMT_BASE_VERSION);
6431bd671abSVishwanathapura, Niranjana if (IS_ERR(rsp))
6441bd671abSVishwanathapura, Niranjana goto err_rsp;
6451bd671abSVishwanathapura, Niranjana
6461bd671abSVishwanathapura, Niranjana rsp->ah = ah;
6471bd671abSVishwanathapura, Niranjana vema_mad = rsp->mad;
6481bd671abSVishwanathapura, Niranjana memcpy(vema_mad, mad_wc->recv_buf.mad, IB_MGMT_VENDOR_HDR);
6491bd671abSVishwanathapura, Niranjana vema_mad->mad_hdr.method = IB_MGMT_METHOD_GET_RESP;
6501bd671abSVishwanathapura, Niranjana vema_mad->mad_hdr.status = 0;
6511bd671abSVishwanathapura, Niranjana
6521bd671abSVishwanathapura, Niranjana /* Lock ensures network adapter is not removed */
6531bd671abSVishwanathapura, Niranjana mutex_lock(&port->lock);
6541bd671abSVishwanathapura, Niranjana
6551bd671abSVishwanathapura, Niranjana switch (mad_wc->recv_buf.mad->mad_hdr.method) {
6561bd671abSVishwanathapura, Niranjana case IB_MGMT_METHOD_GET:
6571bd671abSVishwanathapura, Niranjana vema_get(port, (struct opa_vnic_vema_mad *)mad_wc->recv_buf.mad,
6581bd671abSVishwanathapura, Niranjana vema_mad);
6591bd671abSVishwanathapura, Niranjana break;
6601bd671abSVishwanathapura, Niranjana case IB_MGMT_METHOD_SET:
6611bd671abSVishwanathapura, Niranjana vema_set(port, (struct opa_vnic_vema_mad *)mad_wc->recv_buf.mad,
6621bd671abSVishwanathapura, Niranjana vema_mad);
6631bd671abSVishwanathapura, Niranjana break;
6641bd671abSVishwanathapura, Niranjana default:
6651bd671abSVishwanathapura, Niranjana vema_mad->mad_hdr.status = OPA_VNIC_UNSUP_ATTR;
6661bd671abSVishwanathapura, Niranjana break;
6671bd671abSVishwanathapura, Niranjana }
6681bd671abSVishwanathapura, Niranjana mutex_unlock(&port->lock);
6691bd671abSVishwanathapura, Niranjana
6701bd671abSVishwanathapura, Niranjana if (!ib_post_send_mad(rsp, NULL)) {
6711bd671abSVishwanathapura, Niranjana /*
6721bd671abSVishwanathapura, Niranjana * with post send successful ah and send mad
6731bd671abSVishwanathapura, Niranjana * will be destroyed in send handler
6741bd671abSVishwanathapura, Niranjana */
6751bd671abSVishwanathapura, Niranjana goto free_recv_mad;
6761bd671abSVishwanathapura, Niranjana }
6771bd671abSVishwanathapura, Niranjana
6781bd671abSVishwanathapura, Niranjana ib_free_send_mad(rsp);
6791bd671abSVishwanathapura, Niranjana
6801bd671abSVishwanathapura, Niranjana err_rsp:
6812553ba21SGal Pressman rdma_destroy_ah(ah, RDMA_DESTROY_AH_SLEEPABLE);
6821bd671abSVishwanathapura, Niranjana free_recv_mad:
6831bd671abSVishwanathapura, Niranjana ib_free_recv_mad(mad_wc);
6841bd671abSVishwanathapura, Niranjana }
6851bd671abSVishwanathapura, Niranjana
6861bd671abSVishwanathapura, Niranjana /**
6871bd671abSVishwanathapura, Niranjana * vema_get_port -- Gets the opa_vnic_vema_port
6881bd671abSVishwanathapura, Niranjana * @cport: pointer to control dev
6891bd671abSVishwanathapura, Niranjana * @port_num: Port number
6901bd671abSVishwanathapura, Niranjana *
6911bd671abSVishwanathapura, Niranjana * This function loops through the ports and returns
6921bd671abSVishwanathapura, Niranjana * the opa_vnic_vema port structure that is associated
6931bd671abSVishwanathapura, Niranjana * with the OPA port number
6941bd671abSVishwanathapura, Niranjana *
6951bd671abSVishwanathapura, Niranjana * Return: ptr to requested opa_vnic_vema_port strucure
6961bd671abSVishwanathapura, Niranjana * if success, NULL if not
6971bd671abSVishwanathapura, Niranjana */
6981bd671abSVishwanathapura, Niranjana static struct opa_vnic_vema_port *
vema_get_port(struct opa_vnic_ctrl_port * cport,u8 port_num)6991bd671abSVishwanathapura, Niranjana vema_get_port(struct opa_vnic_ctrl_port *cport, u8 port_num)
7001bd671abSVishwanathapura, Niranjana {
7011bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_port *port = (void *)cport + sizeof(*cport);
7021bd671abSVishwanathapura, Niranjana
7031bd671abSVishwanathapura, Niranjana if (port_num > cport->num_ports)
7041bd671abSVishwanathapura, Niranjana return NULL;
7051bd671abSVishwanathapura, Niranjana
7061bd671abSVishwanathapura, Niranjana return port + (port_num - 1);
7071bd671abSVishwanathapura, Niranjana }
7081bd671abSVishwanathapura, Niranjana
7091bd671abSVishwanathapura, Niranjana /**
7101bd671abSVishwanathapura, Niranjana * opa_vnic_vema_send_trap -- This function sends a trap to the EM
711cb8d0942SRandy Dunlap * @adapter: pointer to vnic adapter
7121bd671abSVishwanathapura, Niranjana * @data: pointer to trap data filled by calling function
7131bd671abSVishwanathapura, Niranjana * @lid: issuers lid (encap_slid from vesw_port_info)
7141bd671abSVishwanathapura, Niranjana *
7151bd671abSVishwanathapura, Niranjana * This function is called from the VNIC driver to send a trap if there
7161bd671abSVishwanathapura, Niranjana * is somethng the EM should be notified about. These events currently
7171bd671abSVishwanathapura, Niranjana * are
7181bd671abSVishwanathapura, Niranjana * 1) UNICAST INTERFACE MACADDRESS changes
7191bd671abSVishwanathapura, Niranjana * 2) MULTICAST INTERFACE MACADDRESS changes
7201bd671abSVishwanathapura, Niranjana * 3) ETHERNET LINK STATUS changes
7211bd671abSVishwanathapura, Niranjana * While allocating the send mad the remote site qpn used is 1
7221bd671abSVishwanathapura, Niranjana * as this is the well known QP.
7231bd671abSVishwanathapura, Niranjana *
7241bd671abSVishwanathapura, Niranjana */
opa_vnic_vema_send_trap(struct opa_vnic_adapter * adapter,struct __opa_veswport_trap * data,u32 lid)7251bd671abSVishwanathapura, Niranjana void opa_vnic_vema_send_trap(struct opa_vnic_adapter *adapter,
7261bd671abSVishwanathapura, Niranjana struct __opa_veswport_trap *data, u32 lid)
7271bd671abSVishwanathapura, Niranjana {
7281bd671abSVishwanathapura, Niranjana struct opa_vnic_ctrl_port *cport = adapter->cport;
7291bd671abSVishwanathapura, Niranjana struct ib_mad_send_buf *send_buf;
7301bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_port *port;
7311bd671abSVishwanathapura, Niranjana struct ib_device *ibp;
7321bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_mad_trap *trap_mad;
7331bd671abSVishwanathapura, Niranjana struct opa_class_port_info *class;
73490898850SDasaratharaman Chandramouli struct rdma_ah_attr ah_attr;
7351bd671abSVishwanathapura, Niranjana struct ib_ah *ah;
7361bd671abSVishwanathapura, Niranjana struct opa_veswport_trap *trap;
7371bd671abSVishwanathapura, Niranjana u32 trap_lid;
7381bd671abSVishwanathapura, Niranjana u16 pkey_idx;
7391bd671abSVishwanathapura, Niranjana
7401bd671abSVishwanathapura, Niranjana if (!cport)
7411bd671abSVishwanathapura, Niranjana goto err_exit;
7421bd671abSVishwanathapura, Niranjana ibp = cport->ibdev;
7431bd671abSVishwanathapura, Niranjana port = vema_get_port(cport, data->opaportnum);
7441bd671abSVishwanathapura, Niranjana if (!port || !port->mad_agent)
7451bd671abSVishwanathapura, Niranjana goto err_exit;
7461bd671abSVishwanathapura, Niranjana
7471bd671abSVishwanathapura, Niranjana if (time_before(jiffies, adapter->trap_timeout)) {
7481bd671abSVishwanathapura, Niranjana if (adapter->trap_count == OPA_VNIC_TRAP_BURST_LIMIT) {
7491bd671abSVishwanathapura, Niranjana v_warn("Trap rate exceeded\n");
7501bd671abSVishwanathapura, Niranjana goto err_exit;
7511bd671abSVishwanathapura, Niranjana } else {
7521bd671abSVishwanathapura, Niranjana adapter->trap_count++;
7531bd671abSVishwanathapura, Niranjana }
7541bd671abSVishwanathapura, Niranjana } else {
7551bd671abSVishwanathapura, Niranjana adapter->trap_count = 0;
7561bd671abSVishwanathapura, Niranjana }
7571bd671abSVishwanathapura, Niranjana
7581bd671abSVishwanathapura, Niranjana class = &port->class_port_info;
7591bd671abSVishwanathapura, Niranjana /* Set up address handle */
7601bd671abSVishwanathapura, Niranjana memset(&ah_attr, 0, sizeof(ah_attr));
76144c58487SDasaratharaman Chandramouli ah_attr.type = rdma_ah_find_type(ibp, port->port_num);
762d8966fcdSDasaratharaman Chandramouli rdma_ah_set_sl(&ah_attr,
763d8966fcdSDasaratharaman Chandramouli GET_TRAP_SL_FROM_CLASS_PORT_INFO(class->trap_sl_rsvd));
764d8966fcdSDasaratharaman Chandramouli rdma_ah_set_port_num(&ah_attr, port->port_num);
7651bd671abSVishwanathapura, Niranjana trap_lid = be32_to_cpu(class->trap_lid);
7661bd671abSVishwanathapura, Niranjana /*
7671bd671abSVishwanathapura, Niranjana * check for trap lid validity, must not be zero
7681bd671abSVishwanathapura, Niranjana * The trap sink could change after we fashion the MAD but since traps
7691bd671abSVishwanathapura, Niranjana * are not guaranteed we won't use a lock as anyway the change will take
7701bd671abSVishwanathapura, Niranjana * place even with locking.
7711bd671abSVishwanathapura, Niranjana */
7721bd671abSVishwanathapura, Niranjana if (!trap_lid) {
7731bd671abSVishwanathapura, Niranjana c_err("%s: Invalid dlid\n", __func__);
7741bd671abSVishwanathapura, Niranjana goto err_exit;
7751bd671abSVishwanathapura, Niranjana }
7761bd671abSVishwanathapura, Niranjana
777d8966fcdSDasaratharaman Chandramouli rdma_ah_set_dlid(&ah_attr, trap_lid);
778b090c4e3SGal Pressman ah = rdma_create_ah(port->mad_agent->qp->pd, &ah_attr, 0);
7791bd671abSVishwanathapura, Niranjana if (IS_ERR(ah)) {
7801bd671abSVishwanathapura, Niranjana c_err("%s:Couldn't create new AH = %p\n", __func__, ah);
7811bd671abSVishwanathapura, Niranjana c_err("%s:dlid = %d, sl = %d, port = %d\n", __func__,
782d8966fcdSDasaratharaman Chandramouli rdma_ah_get_dlid(&ah_attr), rdma_ah_get_sl(&ah_attr),
783d8966fcdSDasaratharaman Chandramouli rdma_ah_get_port_num(&ah_attr));
7841bd671abSVishwanathapura, Niranjana goto err_exit;
7851bd671abSVishwanathapura, Niranjana }
7861bd671abSVishwanathapura, Niranjana
7871bd671abSVishwanathapura, Niranjana if (ib_find_pkey(ibp, data->opaportnum, IB_DEFAULT_PKEY_FULL,
7881bd671abSVishwanathapura, Niranjana &pkey_idx) < 0) {
7891bd671abSVishwanathapura, Niranjana c_err("%s:full key not found, defaulting to partial\n",
7901bd671abSVishwanathapura, Niranjana __func__);
7911bd671abSVishwanathapura, Niranjana if (ib_find_pkey(ibp, data->opaportnum, IB_DEFAULT_PKEY_PARTIAL,
7921bd671abSVishwanathapura, Niranjana &pkey_idx) < 0)
7931bd671abSVishwanathapura, Niranjana pkey_idx = 1;
7941bd671abSVishwanathapura, Niranjana }
7951bd671abSVishwanathapura, Niranjana
7961bd671abSVishwanathapura, Niranjana send_buf = ib_create_send_mad(port->mad_agent, 1, pkey_idx, 0,
7971bd671abSVishwanathapura, Niranjana IB_MGMT_VENDOR_HDR, IB_MGMT_MAD_DATA,
7980568c464SVishwanathapura, Niranjana GFP_ATOMIC, OPA_MGMT_BASE_VERSION);
7991bd671abSVishwanathapura, Niranjana if (IS_ERR(send_buf)) {
8001bd671abSVishwanathapura, Niranjana c_err("%s:Couldn't allocate send buf\n", __func__);
8011bd671abSVishwanathapura, Niranjana goto err_sndbuf;
8021bd671abSVishwanathapura, Niranjana }
8031bd671abSVishwanathapura, Niranjana
8041bd671abSVishwanathapura, Niranjana send_buf->ah = ah;
8051bd671abSVishwanathapura, Niranjana
8061bd671abSVishwanathapura, Niranjana /* Set up common MAD hdr */
8071bd671abSVishwanathapura, Niranjana trap_mad = send_buf->mad;
8081bd671abSVishwanathapura, Niranjana trap_mad->mad_hdr.base_version = OPA_MGMT_BASE_VERSION;
8091bd671abSVishwanathapura, Niranjana trap_mad->mad_hdr.mgmt_class = OPA_MGMT_CLASS_INTEL_EMA;
8101bd671abSVishwanathapura, Niranjana trap_mad->mad_hdr.class_version = OPA_EMA_CLASS_VERSION;
8111bd671abSVishwanathapura, Niranjana trap_mad->mad_hdr.method = IB_MGMT_METHOD_TRAP;
8121bd671abSVishwanathapura, Niranjana port->tid++;
8131bd671abSVishwanathapura, Niranjana trap_mad->mad_hdr.tid = cpu_to_be64(port->tid);
8141bd671abSVishwanathapura, Niranjana trap_mad->mad_hdr.attr_id = IB_SMP_ATTR_NOTICE;
8151bd671abSVishwanathapura, Niranjana
8161bd671abSVishwanathapura, Niranjana /* Set up vendor OUI */
8171bd671abSVishwanathapura, Niranjana trap_mad->oui[0] = INTEL_OUI_1;
8181bd671abSVishwanathapura, Niranjana trap_mad->oui[1] = INTEL_OUI_2;
8191bd671abSVishwanathapura, Niranjana trap_mad->oui[2] = INTEL_OUI_3;
8201bd671abSVishwanathapura, Niranjana
8211bd671abSVishwanathapura, Niranjana /* Setup notice attribute portion */
8221bd671abSVishwanathapura, Niranjana trap_mad->notice.gen_type = OPA_INTEL_EMA_NOTICE_TYPE_INFO << 1;
8231bd671abSVishwanathapura, Niranjana trap_mad->notice.oui_1 = INTEL_OUI_1;
8241bd671abSVishwanathapura, Niranjana trap_mad->notice.oui_2 = INTEL_OUI_2;
8251bd671abSVishwanathapura, Niranjana trap_mad->notice.oui_3 = INTEL_OUI_3;
8261bd671abSVishwanathapura, Niranjana trap_mad->notice.issuer_lid = cpu_to_be32(lid);
8271bd671abSVishwanathapura, Niranjana
8281bd671abSVishwanathapura, Niranjana /* copy the actual trap data */
8291bd671abSVishwanathapura, Niranjana trap = (struct opa_veswport_trap *)trap_mad->notice.raw_data;
8301bd671abSVishwanathapura, Niranjana trap->fabric_id = cpu_to_be16(data->fabric_id);
8311bd671abSVishwanathapura, Niranjana trap->veswid = cpu_to_be16(data->veswid);
8321bd671abSVishwanathapura, Niranjana trap->veswportnum = cpu_to_be32(data->veswportnum);
8331bd671abSVishwanathapura, Niranjana trap->opaportnum = cpu_to_be16(data->opaportnum);
8341bd671abSVishwanathapura, Niranjana trap->veswportindex = data->veswportindex;
8351bd671abSVishwanathapura, Niranjana trap->opcode = data->opcode;
8361bd671abSVishwanathapura, Niranjana
8371bd671abSVishwanathapura, Niranjana /* If successful send set up rate limit timeout else bail */
8381bd671abSVishwanathapura, Niranjana if (ib_post_send_mad(send_buf, NULL)) {
8391bd671abSVishwanathapura, Niranjana ib_free_send_mad(send_buf);
8401bd671abSVishwanathapura, Niranjana } else {
8411bd671abSVishwanathapura, Niranjana if (adapter->trap_count)
8421bd671abSVishwanathapura, Niranjana return;
8431bd671abSVishwanathapura, Niranjana adapter->trap_timeout = jiffies +
8441bd671abSVishwanathapura, Niranjana usecs_to_jiffies(OPA_VNIC_TRAP_TIMEOUT);
8451bd671abSVishwanathapura, Niranjana return;
8461bd671abSVishwanathapura, Niranjana }
8471bd671abSVishwanathapura, Niranjana
8481bd671abSVishwanathapura, Niranjana err_sndbuf:
8492553ba21SGal Pressman rdma_destroy_ah(ah, 0);
8501bd671abSVishwanathapura, Niranjana err_exit:
8511bd671abSVishwanathapura, Niranjana v_err("Aborting trap\n");
8521bd671abSVishwanathapura, Niranjana }
8531bd671abSVishwanathapura, Niranjana
opa_vnic_event(struct ib_event_handler * handler,struct ib_event * record)8541bd671abSVishwanathapura, Niranjana static void opa_vnic_event(struct ib_event_handler *handler,
8551bd671abSVishwanathapura, Niranjana struct ib_event *record)
8561bd671abSVishwanathapura, Niranjana {
8571bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_port *port =
8581bd671abSVishwanathapura, Niranjana container_of(handler, struct opa_vnic_vema_port, event_handler);
8591bd671abSVishwanathapura, Niranjana struct opa_vnic_ctrl_port *cport = port->cport;
860fae7a699SMatthew Wilcox struct opa_vnic_adapter *adapter;
861fae7a699SMatthew Wilcox unsigned long index;
8621bd671abSVishwanathapura, Niranjana
8631bd671abSVishwanathapura, Niranjana if (record->element.port_num != port->port_num)
8641bd671abSVishwanathapura, Niranjana return;
8651bd671abSVishwanathapura, Niranjana
8661bd671abSVishwanathapura, Niranjana c_dbg("OPA_VNIC received event %d on device %s port %d\n",
8676c854111SJason Gunthorpe record->event, dev_name(&record->device->dev),
8686c854111SJason Gunthorpe record->element.port_num);
8691bd671abSVishwanathapura, Niranjana
8704d2e11d4SColin Ian King if (record->event != IB_EVENT_PORT_ERR &&
871fae7a699SMatthew Wilcox record->event != IB_EVENT_PORT_ACTIVE)
872fae7a699SMatthew Wilcox return;
873fae7a699SMatthew Wilcox
874fae7a699SMatthew Wilcox xa_for_each(&port->vports, index, adapter) {
8751bd671abSVishwanathapura, Niranjana if (record->event == IB_EVENT_PORT_ACTIVE)
876fae7a699SMatthew Wilcox netif_carrier_on(adapter->netdev);
877fae7a699SMatthew Wilcox else
878fae7a699SMatthew Wilcox netif_carrier_off(adapter->netdev);
879fae7a699SMatthew Wilcox }
8801bd671abSVishwanathapura, Niranjana }
8811bd671abSVishwanathapura, Niranjana
8821bd671abSVishwanathapura, Niranjana /**
8831bd671abSVishwanathapura, Niranjana * vema_unregister -- Unregisters agent
8841bd671abSVishwanathapura, Niranjana * @cport: pointer to control port
8851bd671abSVishwanathapura, Niranjana *
8861bd671abSVishwanathapura, Niranjana * This deletes the registration by VEMA for MADs
8871bd671abSVishwanathapura, Niranjana */
vema_unregister(struct opa_vnic_ctrl_port * cport)8881bd671abSVishwanathapura, Niranjana static void vema_unregister(struct opa_vnic_ctrl_port *cport)
8891bd671abSVishwanathapura, Niranjana {
890fae7a699SMatthew Wilcox struct opa_vnic_adapter *adapter;
891fae7a699SMatthew Wilcox unsigned long index;
8921bd671abSVishwanathapura, Niranjana int i;
8931bd671abSVishwanathapura, Niranjana
8941bd671abSVishwanathapura, Niranjana for (i = 1; i <= cport->num_ports; i++) {
8951bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_port *port = vema_get_port(cport, i);
8961bd671abSVishwanathapura, Niranjana
8971bd671abSVishwanathapura, Niranjana if (!port->mad_agent)
8981bd671abSVishwanathapura, Niranjana continue;
8991bd671abSVishwanathapura, Niranjana
9001bd671abSVishwanathapura, Niranjana /* Lock ensures no MAD is being processed */
9011bd671abSVishwanathapura, Niranjana mutex_lock(&port->lock);
902fae7a699SMatthew Wilcox xa_for_each(&port->vports, index, adapter)
903fae7a699SMatthew Wilcox opa_vnic_rem_netdev(adapter);
9041bd671abSVishwanathapura, Niranjana mutex_unlock(&port->lock);
9051bd671abSVishwanathapura, Niranjana
9061bd671abSVishwanathapura, Niranjana ib_unregister_mad_agent(port->mad_agent);
9071bd671abSVishwanathapura, Niranjana port->mad_agent = NULL;
9081bd671abSVishwanathapura, Niranjana mutex_destroy(&port->lock);
909fae7a699SMatthew Wilcox xa_destroy(&port->vports);
9101bd671abSVishwanathapura, Niranjana ib_unregister_event_handler(&port->event_handler);
9111bd671abSVishwanathapura, Niranjana }
9121bd671abSVishwanathapura, Niranjana }
9131bd671abSVishwanathapura, Niranjana
9141bd671abSVishwanathapura, Niranjana /**
9151bd671abSVishwanathapura, Niranjana * vema_register -- Registers agent
9161bd671abSVishwanathapura, Niranjana * @cport: pointer to control port
9171bd671abSVishwanathapura, Niranjana *
9181bd671abSVishwanathapura, Niranjana * This function registers the handlers for the VEMA MADs
9191bd671abSVishwanathapura, Niranjana *
9201bd671abSVishwanathapura, Niranjana * Return: returns 0 on success. non zero otherwise
9211bd671abSVishwanathapura, Niranjana */
vema_register(struct opa_vnic_ctrl_port * cport)9221bd671abSVishwanathapura, Niranjana static int vema_register(struct opa_vnic_ctrl_port *cport)
9231bd671abSVishwanathapura, Niranjana {
9241bd671abSVishwanathapura, Niranjana struct ib_mad_reg_req reg_req = {
9251bd671abSVishwanathapura, Niranjana .mgmt_class = OPA_MGMT_CLASS_INTEL_EMA,
9261bd671abSVishwanathapura, Niranjana .mgmt_class_version = OPA_MGMT_BASE_VERSION,
9271bd671abSVishwanathapura, Niranjana .oui = { INTEL_OUI_1, INTEL_OUI_2, INTEL_OUI_3 }
9281bd671abSVishwanathapura, Niranjana };
9291bd671abSVishwanathapura, Niranjana int i;
9301bd671abSVishwanathapura, Niranjana
9311bd671abSVishwanathapura, Niranjana set_bit(IB_MGMT_METHOD_GET, reg_req.method_mask);
9321bd671abSVishwanathapura, Niranjana set_bit(IB_MGMT_METHOD_SET, reg_req.method_mask);
9331bd671abSVishwanathapura, Niranjana
9341bd671abSVishwanathapura, Niranjana /* register ib event handler and mad agent for each port on dev */
9351bd671abSVishwanathapura, Niranjana for (i = 1; i <= cport->num_ports; i++) {
9361bd671abSVishwanathapura, Niranjana struct opa_vnic_vema_port *port = vema_get_port(cport, i);
9371bd671abSVishwanathapura, Niranjana int ret;
9381bd671abSVishwanathapura, Niranjana
9391bd671abSVishwanathapura, Niranjana port->cport = cport;
9401bd671abSVishwanathapura, Niranjana port->port_num = i;
9411bd671abSVishwanathapura, Niranjana
9421bd671abSVishwanathapura, Niranjana INIT_IB_EVENT_HANDLER(&port->event_handler,
9431bd671abSVishwanathapura, Niranjana cport->ibdev, opa_vnic_event);
944dcc9881eSLeon Romanovsky ib_register_event_handler(&port->event_handler);
9451bd671abSVishwanathapura, Niranjana
946fae7a699SMatthew Wilcox xa_init(&port->vports);
9471bd671abSVishwanathapura, Niranjana mutex_init(&port->lock);
9481bd671abSVishwanathapura, Niranjana port->mad_agent = ib_register_mad_agent(cport->ibdev, i,
9491bd671abSVishwanathapura, Niranjana IB_QPT_GSI, ®_req,
9501bd671abSVishwanathapura, Niranjana IB_MGMT_RMPP_VERSION,
9511bd671abSVishwanathapura, Niranjana vema_send, vema_recv,
9521bd671abSVishwanathapura, Niranjana port, 0);
9531bd671abSVishwanathapura, Niranjana if (IS_ERR(port->mad_agent)) {
9541bd671abSVishwanathapura, Niranjana ret = PTR_ERR(port->mad_agent);
9551bd671abSVishwanathapura, Niranjana port->mad_agent = NULL;
9561bd671abSVishwanathapura, Niranjana mutex_destroy(&port->lock);
9571bd671abSVishwanathapura, Niranjana vema_unregister(cport);
9581bd671abSVishwanathapura, Niranjana return ret;
9591bd671abSVishwanathapura, Niranjana }
9601bd671abSVishwanathapura, Niranjana }
9611bd671abSVishwanathapura, Niranjana
9621bd671abSVishwanathapura, Niranjana return 0;
9631bd671abSVishwanathapura, Niranjana }
9641bd671abSVishwanathapura, Niranjana
9651bd671abSVishwanathapura, Niranjana /**
966cb49366fSVishwanathapura, Niranjana * opa_vnic_ctrl_config_dev -- This function sends a trap to the EM
967cb49366fSVishwanathapura, Niranjana * by way of ib_modify_port to indicate support for ethernet on the
968cb49366fSVishwanathapura, Niranjana * fabric.
969cb49366fSVishwanathapura, Niranjana * @cport: pointer to control port
970cb49366fSVishwanathapura, Niranjana * @en: enable or disable ethernet on fabric support
971cb49366fSVishwanathapura, Niranjana */
opa_vnic_ctrl_config_dev(struct opa_vnic_ctrl_port * cport,bool en)972cb49366fSVishwanathapura, Niranjana static void opa_vnic_ctrl_config_dev(struct opa_vnic_ctrl_port *cport, bool en)
973cb49366fSVishwanathapura, Niranjana {
974cb49366fSVishwanathapura, Niranjana struct ib_port_modify pm = { 0 };
975cb49366fSVishwanathapura, Niranjana int i;
976cb49366fSVishwanathapura, Niranjana
977cb49366fSVishwanathapura, Niranjana if (en)
978cb49366fSVishwanathapura, Niranjana pm.set_port_cap_mask = OPA_CAP_MASK3_IsEthOnFabricSupported;
979cb49366fSVishwanathapura, Niranjana else
980cb49366fSVishwanathapura, Niranjana pm.clr_port_cap_mask = OPA_CAP_MASK3_IsEthOnFabricSupported;
981cb49366fSVishwanathapura, Niranjana
982cb49366fSVishwanathapura, Niranjana for (i = 1; i <= cport->num_ports; i++)
983cb49366fSVishwanathapura, Niranjana ib_modify_port(cport->ibdev, i, IB_PORT_OPA_MASK_CHG, &pm);
984cb49366fSVishwanathapura, Niranjana }
985cb49366fSVishwanathapura, Niranjana
986cb49366fSVishwanathapura, Niranjana /**
9871bd671abSVishwanathapura, Niranjana * opa_vnic_vema_add_one -- Handle new ib device
9881bd671abSVishwanathapura, Niranjana * @device: ib device pointer
9891bd671abSVishwanathapura, Niranjana *
9901bd671abSVishwanathapura, Niranjana * Allocate the vnic control port and initialize it.
9911bd671abSVishwanathapura, Niranjana */
opa_vnic_vema_add_one(struct ib_device * device)99211a0ae4cSJason Gunthorpe static int opa_vnic_vema_add_one(struct ib_device *device)
9931bd671abSVishwanathapura, Niranjana {
9941bd671abSVishwanathapura, Niranjana struct opa_vnic_ctrl_port *cport;
9951bd671abSVishwanathapura, Niranjana int rc, size = sizeof(*cport);
9961bd671abSVishwanathapura, Niranjana
9971bd671abSVishwanathapura, Niranjana if (!rdma_cap_opa_vnic(device))
99811a0ae4cSJason Gunthorpe return -EOPNOTSUPP;
9991bd671abSVishwanathapura, Niranjana
10001bd671abSVishwanathapura, Niranjana size += device->phys_port_cnt * sizeof(struct opa_vnic_vema_port);
10011bd671abSVishwanathapura, Niranjana cport = kzalloc(size, GFP_KERNEL);
10021bd671abSVishwanathapura, Niranjana if (!cport)
100311a0ae4cSJason Gunthorpe return -ENOMEM;
10041bd671abSVishwanathapura, Niranjana
10051bd671abSVishwanathapura, Niranjana cport->num_ports = device->phys_port_cnt;
10061bd671abSVishwanathapura, Niranjana cport->ibdev = device;
10071bd671abSVishwanathapura, Niranjana
10081bd671abSVishwanathapura, Niranjana /* Initialize opa vnic management agent (vema) */
10091bd671abSVishwanathapura, Niranjana rc = vema_register(cport);
10101bd671abSVishwanathapura, Niranjana if (!rc)
10111bd671abSVishwanathapura, Niranjana c_info("VNIC client initialized\n");
10121bd671abSVishwanathapura, Niranjana
10131bd671abSVishwanathapura, Niranjana ib_set_client_data(device, &opa_vnic_client, cport);
1014cb49366fSVishwanathapura, Niranjana opa_vnic_ctrl_config_dev(cport, true);
101511a0ae4cSJason Gunthorpe return 0;
10161bd671abSVishwanathapura, Niranjana }
10171bd671abSVishwanathapura, Niranjana
10181bd671abSVishwanathapura, Niranjana /**
10191bd671abSVishwanathapura, Niranjana * opa_vnic_vema_rem_one -- Handle ib device removal
10201bd671abSVishwanathapura, Niranjana * @device: ib device pointer
10211bd671abSVishwanathapura, Niranjana * @client_data: ib client data
10221bd671abSVishwanathapura, Niranjana *
10231bd671abSVishwanathapura, Niranjana * Uninitialize and free the vnic control port.
10241bd671abSVishwanathapura, Niranjana */
opa_vnic_vema_rem_one(struct ib_device * device,void * client_data)10251bd671abSVishwanathapura, Niranjana static void opa_vnic_vema_rem_one(struct ib_device *device,
10261bd671abSVishwanathapura, Niranjana void *client_data)
10271bd671abSVishwanathapura, Niranjana {
10281bd671abSVishwanathapura, Niranjana struct opa_vnic_ctrl_port *cport = client_data;
10291bd671abSVishwanathapura, Niranjana
10301bd671abSVishwanathapura, Niranjana c_info("removing VNIC client\n");
1031cb49366fSVishwanathapura, Niranjana opa_vnic_ctrl_config_dev(cport, false);
10321bd671abSVishwanathapura, Niranjana vema_unregister(cport);
10331bd671abSVishwanathapura, Niranjana kfree(cport);
10341bd671abSVishwanathapura, Niranjana }
10351bd671abSVishwanathapura, Niranjana
opa_vnic_init(void)10361bd671abSVishwanathapura, Niranjana static int __init opa_vnic_init(void)
10371bd671abSVishwanathapura, Niranjana {
10381bd671abSVishwanathapura, Niranjana int rc;
10391bd671abSVishwanathapura, Niranjana
10401bd671abSVishwanathapura, Niranjana rc = ib_register_client(&opa_vnic_client);
10411bd671abSVishwanathapura, Niranjana if (rc)
10421bd671abSVishwanathapura, Niranjana pr_err("VNIC driver register failed %d\n", rc);
10431bd671abSVishwanathapura, Niranjana
10441bd671abSVishwanathapura, Niranjana return rc;
10451bd671abSVishwanathapura, Niranjana }
10461bd671abSVishwanathapura, Niranjana module_init(opa_vnic_init);
10471bd671abSVishwanathapura, Niranjana
opa_vnic_deinit(void)10481bd671abSVishwanathapura, Niranjana static void opa_vnic_deinit(void)
10491bd671abSVishwanathapura, Niranjana {
10501bd671abSVishwanathapura, Niranjana ib_unregister_client(&opa_vnic_client);
10511bd671abSVishwanathapura, Niranjana }
10521bd671abSVishwanathapura, Niranjana module_exit(opa_vnic_deinit);
10531bd671abSVishwanathapura, Niranjana
10541bd671abSVishwanathapura, Niranjana MODULE_LICENSE("Dual BSD/GPL");
1055*4892298cSScott Breyer MODULE_AUTHOR("Cornelis Networks");
1056*4892298cSScott Breyer MODULE_DESCRIPTION("Cornelis OPX Virtual Network driver");
1057