summaryrefslogtreecommitdiff
path: root/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c')
-rw-r--r--drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c136
1 files changed, 68 insertions, 68 deletions
diff --git a/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c b/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c
index cf768dd78d1b..21c6cea8b1db 100644
--- a/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c
+++ b/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c
@@ -1,5 +1,6 @@
/*
* Copyright(c) 2017 Intel Corporation.
+ * Copyright(c) 2021 Cornelis Networks.
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
@@ -46,19 +47,20 @@
*/
/*
- * This file contains OPA Virtual Network Interface Controller (VNIC)
+ * This file contains OPX Virtual Network Interface Controller (VNIC)
* Ethernet Management Agent (EMA) driver
*/
#include <linux/module.h>
+#include <linux/xarray.h>
#include <rdma/ib_addr.h>
-#include <rdma/ib_smi.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/opa_smi.h>
+#include <rdma/opa_port_info.h>
#include "opa_vnic_internal.h"
-#define DRV_VERSION "1.0"
char opa_vnic_driver_name[] = "opa_vnic";
-const char opa_vnic_driver_version[] = DRV_VERSION;
/*
* The trap service level is kept in bits 3 to 7 in the trap_sl_rsvd
@@ -95,7 +97,7 @@ const char opa_vnic_driver_version[] = DRV_VERSION;
* @class_port_info: Class port info information.
* @tid: Transaction id
* @port_num: OPA port number
- * @vport_idr: vnic ports idr
+ * @vports: vnic ports
* @event_handler: ib event handler
* @lock: adapter interface lock
*/
@@ -105,14 +107,14 @@ struct opa_vnic_vema_port {
struct opa_class_port_info class_port_info;
u64 tid;
u8 port_num;
- struct idr vport_idr;
+ struct xarray vports;
struct ib_event_handler event_handler;
/* Lock to query/update network adapter */
struct mutex lock;
};
-static void opa_vnic_vema_add_one(struct ib_device *device);
+static int opa_vnic_vema_add_one(struct ib_device *device);
static void opa_vnic_vema_rem_one(struct ib_device *device,
void *client_data);
@@ -146,7 +148,7 @@ vema_get_vport_adapter(struct opa_vnic_vema_mad *recvd_mad,
{
u8 vport_num = vema_get_vport_num(recvd_mad);
- return idr_find(&port->vport_idr, vport_num);
+ return xa_load(&port->vports, vport_num);
}
/**
@@ -184,6 +186,7 @@ static inline void vema_get_pod_values(struct opa_veswport_info *port_info)
cpu_to_be16(OPA_VNIC_MAX_SMAC_LIMIT);
port_info->vport.oper_state = OPA_VNIC_STATE_DROP_ALL;
port_info->vport.config_state = OPA_VNIC_STATE_DROP_ALL;
+ port_info->vesw.eth_mtu = cpu_to_be16(ETH_DATA_LEN);
}
/**
@@ -204,8 +207,7 @@ static struct opa_vnic_adapter *vema_add_vport(struct opa_vnic_vema_port *port,
int rc;
adapter->cport = cport;
- rc = idr_alloc(&port->vport_idr, adapter, vport_num,
- vport_num + 1, GFP_NOWAIT);
+ rc = xa_insert(&port->vports, vport_num, adapter, GFP_KERNEL);
if (rc < 0) {
opa_vnic_rem_netdev(adapter);
adapter = ERR_PTR(rc);
@@ -232,7 +234,7 @@ static void vema_get_class_port_info(struct opa_vnic_vema_port *port,
port_info = (struct opa_class_port_info *)rsp_mad->data;
memcpy(port_info, &port->class_port_info, sizeof(*port_info));
- port_info->base_version = OPA_MGMT_BASE_VERSION,
+ port_info->base_version = OPA_MGMT_BASE_VERSION;
port_info->class_version = OPA_EMA_CLASS_VERSION;
/*
@@ -546,7 +548,6 @@ static void vema_get(struct opa_vnic_vema_port *port,
vema_get_mac_entries(port, recvd_mad, rsp_mad);
break;
case OPA_EM_ATTR_IFACE_UCAST_MACS:
- /* fall through */
case OPA_EM_ATTR_IFACE_MCAST_MACS:
vema_get_mac_list(port, recvd_mad, rsp_mad, attr_id);
break;
@@ -603,7 +604,7 @@ static void vema_set(struct opa_vnic_vema_port *port,
static void vema_send(struct ib_mad_agent *mad_agent,
struct ib_mad_send_wc *mad_wc)
{
- rdma_destroy_ah(mad_wc->send_buf->ah);
+ rdma_destroy_ah(mad_wc->send_buf->ah, RDMA_DESTROY_AH_SLEEPABLE);
ib_free_send_mad(mad_wc->send_buf);
}
@@ -677,7 +678,7 @@ static void vema_recv(struct ib_mad_agent *mad_agent,
ib_free_send_mad(rsp);
err_rsp:
- rdma_destroy_ah(ah);
+ rdma_destroy_ah(ah, RDMA_DESTROY_AH_SLEEPABLE);
free_recv_mad:
ib_free_recv_mad(mad_wc);
}
@@ -707,7 +708,7 @@ vema_get_port(struct opa_vnic_ctrl_port *cport, u8 port_num)
/**
* opa_vnic_vema_send_trap -- This function sends a trap to the EM
- * @cport: pointer to vnic control port
+ * @adapter: pointer to vnic adapter
* @data: pointer to trap data filled by calling function
* @lid: issuers lid (encap_slid from vesw_port_info)
*
@@ -774,7 +775,7 @@ void opa_vnic_vema_send_trap(struct opa_vnic_adapter *adapter,
}
rdma_ah_set_dlid(&ah_attr, trap_lid);
- ah = rdma_create_ah(port->mad_agent->qp->pd, &ah_attr);
+ ah = rdma_create_ah(port->mad_agent->qp->pd, &ah_attr, 0);
if (IS_ERR(ah)) {
c_err("%s:Couldn't create new AH = %p\n", __func__, ah);
c_err("%s:dlid = %d, sl = %d, port = %d\n", __func__,
@@ -845,52 +846,37 @@ void opa_vnic_vema_send_trap(struct opa_vnic_adapter *adapter,
}
err_sndbuf:
- rdma_destroy_ah(ah);
+ rdma_destroy_ah(ah, 0);
err_exit:
v_err("Aborting trap\n");
}
-static int vema_rem_vport(int id, void *p, void *data)
-{
- struct opa_vnic_adapter *adapter = p;
-
- opa_vnic_rem_netdev(adapter);
- return 0;
-}
-
-static int vema_enable_vport(int id, void *p, void *data)
-{
- struct opa_vnic_adapter *adapter = p;
-
- netif_carrier_on(adapter->netdev);
- return 0;
-}
-
-static int vema_disable_vport(int id, void *p, void *data)
-{
- struct opa_vnic_adapter *adapter = p;
-
- netif_carrier_off(adapter->netdev);
- return 0;
-}
-
static void opa_vnic_event(struct ib_event_handler *handler,
struct ib_event *record)
{
struct opa_vnic_vema_port *port =
container_of(handler, struct opa_vnic_vema_port, event_handler);
struct opa_vnic_ctrl_port *cport = port->cport;
+ struct opa_vnic_adapter *adapter;
+ unsigned long index;
if (record->element.port_num != port->port_num)
return;
c_dbg("OPA_VNIC received event %d on device %s port %d\n",
- record->event, record->device->name, record->element.port_num);
+ record->event, dev_name(&record->device->dev),
+ record->element.port_num);
- if (record->event == IB_EVENT_PORT_ERR)
- idr_for_each(&port->vport_idr, vema_disable_vport, NULL);
- if (record->event == IB_EVENT_PORT_ACTIVE)
- idr_for_each(&port->vport_idr, vema_enable_vport, NULL);
+ if (record->event != IB_EVENT_PORT_ERR &&
+ record->event != IB_EVENT_PORT_ACTIVE)
+ return;
+
+ xa_for_each(&port->vports, index, adapter) {
+ if (record->event == IB_EVENT_PORT_ACTIVE)
+ netif_carrier_on(adapter->netdev);
+ else
+ netif_carrier_off(adapter->netdev);
+ }
}
/**
@@ -901,6 +887,8 @@ static void opa_vnic_event(struct ib_event_handler *handler,
*/
static void vema_unregister(struct opa_vnic_ctrl_port *cport)
{
+ struct opa_vnic_adapter *adapter;
+ unsigned long index;
int i;
for (i = 1; i <= cport->num_ports; i++) {
@@ -911,13 +899,14 @@ static void vema_unregister(struct opa_vnic_ctrl_port *cport)
/* Lock ensures no MAD is being processed */
mutex_lock(&port->lock);
- idr_for_each(&port->vport_idr, vema_rem_vport, NULL);
+ xa_for_each(&port->vports, index, adapter)
+ opa_vnic_rem_netdev(adapter);
mutex_unlock(&port->lock);
ib_unregister_mad_agent(port->mad_agent);
port->mad_agent = NULL;
mutex_destroy(&port->lock);
- idr_destroy(&port->vport_idr);
+ xa_destroy(&port->vports);
ib_unregister_event_handler(&port->event_handler);
}
}
@@ -952,14 +941,9 @@ static int vema_register(struct opa_vnic_ctrl_port *cport)
INIT_IB_EVENT_HANDLER(&port->event_handler,
cport->ibdev, opa_vnic_event);
- ret = ib_register_event_handler(&port->event_handler);
- if (ret) {
- c_err("port %d: event handler register failed\n", i);
- vema_unregister(cport);
- return ret;
- }
+ ib_register_event_handler(&port->event_handler);
- idr_init(&port->vport_idr);
+ xa_init(&port->vports);
mutex_init(&port->lock);
port->mad_agent = ib_register_mad_agent(cport->ibdev, i,
IB_QPT_GSI, &reg_req,
@@ -970,7 +954,6 @@ static int vema_register(struct opa_vnic_ctrl_port *cport)
ret = PTR_ERR(port->mad_agent);
port->mad_agent = NULL;
mutex_destroy(&port->lock);
- idr_destroy(&port->vport_idr);
vema_unregister(cport);
return ret;
}
@@ -980,23 +963,44 @@ static int vema_register(struct opa_vnic_ctrl_port *cport)
}
/**
+ * opa_vnic_ctrl_config_dev -- This function sends a trap to the EM
+ * by way of ib_modify_port to indicate support for ethernet on the
+ * fabric.
+ * @cport: pointer to control port
+ * @en: enable or disable ethernet on fabric support
+ */
+static void opa_vnic_ctrl_config_dev(struct opa_vnic_ctrl_port *cport, bool en)
+{
+ struct ib_port_modify pm = { 0 };
+ int i;
+
+ if (en)
+ pm.set_port_cap_mask = OPA_CAP_MASK3_IsEthOnFabricSupported;
+ else
+ pm.clr_port_cap_mask = OPA_CAP_MASK3_IsEthOnFabricSupported;
+
+ for (i = 1; i <= cport->num_ports; i++)
+ ib_modify_port(cport->ibdev, i, IB_PORT_OPA_MASK_CHG, &pm);
+}
+
+/**
* opa_vnic_vema_add_one -- Handle new ib device
* @device: ib device pointer
*
* Allocate the vnic control port and initialize it.
*/
-static void opa_vnic_vema_add_one(struct ib_device *device)
+static int opa_vnic_vema_add_one(struct ib_device *device)
{
struct opa_vnic_ctrl_port *cport;
int rc, size = sizeof(*cport);
if (!rdma_cap_opa_vnic(device))
- return;
+ return -EOPNOTSUPP;
size += device->phys_port_cnt * sizeof(struct opa_vnic_vema_port);
cport = kzalloc(size, GFP_KERNEL);
if (!cport)
- return;
+ return -ENOMEM;
cport->num_ports = device->phys_port_cnt;
cport->ibdev = device;
@@ -1007,6 +1011,8 @@ static void opa_vnic_vema_add_one(struct ib_device *device)
c_info("VNIC client initialized\n");
ib_set_client_data(device, &opa_vnic_client, cport);
+ opa_vnic_ctrl_config_dev(cport, true);
+ return 0;
}
/**
@@ -1021,10 +1027,8 @@ static void opa_vnic_vema_rem_one(struct ib_device *device,
{
struct opa_vnic_ctrl_port *cport = client_data;
- if (!cport)
- return;
-
c_info("removing VNIC client\n");
+ opa_vnic_ctrl_config_dev(cport, false);
vema_unregister(cport);
kfree(cport);
}
@@ -1033,9 +1037,6 @@ static int __init opa_vnic_init(void)
{
int rc;
- pr_info("OPA Virtual Network Driver - v%s\n",
- opa_vnic_driver_version);
-
rc = ib_register_client(&opa_vnic_client);
if (rc)
pr_err("VNIC driver register failed %d\n", rc);
@@ -1051,6 +1052,5 @@ static void opa_vnic_deinit(void)
module_exit(opa_vnic_deinit);
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Intel OPA Virtual Network driver");
-MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Cornelis Networks");
+MODULE_DESCRIPTION("Cornelis OPX Virtual Network driver");