summaryrefslogtreecommitdiff
path: root/drivers/infiniband/ulp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/ulp')
-rw-r--r--drivers/infiniband/ulp/Makefile1
-rw-r--r--drivers/infiniband/ulp/ipoib/Kconfig2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h7
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c10
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c12
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c13
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c16
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c3
-rw-r--r--drivers/infiniband/ulp/iser/iser_initiator.c16
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c5
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.c120
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.h3
-rw-r--r--drivers/infiniband/ulp/opa_vnic/Kconfig9
-rw-r--r--drivers/infiniband/ulp/opa_vnic/Makefile9
-rw-r--r--drivers/infiniband/ulp/opa_vnic/opa_vnic_encap.c513
-rw-r--r--drivers/infiniband/ulp/opa_vnic/opa_vnic_encap.h524
-rw-r--r--drivers/infiniband/ulp/opa_vnic/opa_vnic_ethtool.c183
-rw-r--r--drivers/infiniband/ulp/opa_vnic/opa_vnic_internal.h329
-rw-r--r--drivers/infiniband/ulp/opa_vnic/opa_vnic_netdev.c400
-rw-r--r--drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c1056
-rw-r--r--drivers/infiniband/ulp/opa_vnic/opa_vnic_vema_iface.c390
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c2
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-clt-trace.h2
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-clt.c34
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-clt.h4
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c2
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-srv-trace.h2
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-srv.c30
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c114
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.c36
30 files changed, 298 insertions, 3549 deletions
diff --git a/drivers/infiniband/ulp/Makefile b/drivers/infiniband/ulp/Makefile
index 4d0004b58377..51b0d41699b8 100644
--- a/drivers/infiniband/ulp/Makefile
+++ b/drivers/infiniband/ulp/Makefile
@@ -4,5 +4,4 @@ obj-$(CONFIG_INFINIBAND_SRP) += srp/
obj-$(CONFIG_INFINIBAND_SRPT) += srpt/
obj-$(CONFIG_INFINIBAND_ISER) += iser/
obj-$(CONFIG_INFINIBAND_ISERT) += isert/
-obj-$(CONFIG_INFINIBAND_OPA_VNIC) += opa_vnic/
obj-$(CONFIG_INFINIBAND_RTRS) += rtrs/
diff --git a/drivers/infiniband/ulp/ipoib/Kconfig b/drivers/infiniband/ulp/ipoib/Kconfig
index 254e31a90a66..b5253a231bdd 100644
--- a/drivers/infiniband/ulp/ipoib/Kconfig
+++ b/drivers/infiniband/ulp/ipoib/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config INFINIBAND_IPOIB
tristate "IP-over-InfiniBand"
- depends on NETDEVICES && INET && (IPV6 || IPV6=n)
+ depends on NETDEVICES && INET
help
Support for the IP-over-InfiniBand protocol (IPoIB). This
transports IP packets over InfiniBand so you can use your IB
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 91f866e3fb8b..143e03b64902 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -87,6 +87,7 @@ enum {
IPOIB_FLAG_INITIALIZED = 1,
IPOIB_FLAG_ADMIN_UP = 2,
IPOIB_PKEY_ASSIGNED = 3,
+ IPOIB_FLAG_MCAST_FLUSH = 4,
IPOIB_FLAG_SUBINTERFACE = 5,
IPOIB_STOP_REAPER = 7,
IPOIB_FLAG_ADMIN_CM = 9,
@@ -414,6 +415,12 @@ struct ipoib_dev_priv {
const struct net_device_ops *rn_ops;
};
+static inline bool ipoib_mcast_allowed(struct ipoib_dev_priv *priv)
+{
+ return test_bit(IPOIB_FLAG_OPER_UP, &priv->flags) &&
+ !test_bit(IPOIB_FLAG_MCAST_FLUSH, &priv->flags);
+}
+
struct ipoib_ah {
struct net_device *dev;
struct ib_ah *ah;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 57fec88a1629..ed0592898384 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -1071,8 +1071,7 @@ static struct ib_qp *ipoib_cm_create_tx_qp(struct net_device *dev, struct ipoib_
struct ib_qp *tx_qp;
if (dev->features & NETIF_F_SG)
- attr.cap.max_send_sge = min_t(u32, priv->ca->attrs.max_send_sge,
- MAX_SKB_FRAGS + 1);
+ attr.cap.max_send_sge = min(priv->ca->attrs.max_send_sge, MAX_SKB_FRAGS + 1);
tx_qp = ib_create_qp(priv->pd, &attr);
tx->max_send_sge = attr.cap.max_send_sge;
@@ -1582,7 +1581,8 @@ static void ipoib_cm_create_srq(struct net_device *dev, int max_sge)
int ipoib_cm_dev_init(struct net_device *dev)
{
struct ipoib_dev_priv *priv = ipoib_priv(dev);
- int max_srq_sge, i;
+ u32 max_srq_sge;
+ int i;
u8 addr;
INIT_LIST_HEAD(&priv->cm.passive_ids);
@@ -1600,9 +1600,9 @@ int ipoib_cm_dev_init(struct net_device *dev)
skb_queue_head_init(&priv->cm.skb_queue);
- ipoib_dbg(priv, "max_srq_sge=%d\n", priv->ca->attrs.max_srq_sge);
+ ipoib_dbg(priv, "max_srq_sge=%u\n", priv->ca->attrs.max_srq_sge);
- max_srq_sge = min_t(int, IPOIB_CM_RX_SG, priv->ca->attrs.max_srq_sge);
+ max_srq_sge = min(priv->ca->attrs.max_srq_sge, IPOIB_CM_RX_SG);
ipoib_cm_create_srq(dev, max_srq_sge);
if (ipoib_cm_has_srq(dev)) {
priv->cm.max_cm_mtu = max_srq_sge * PAGE_SIZE - 0x10;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 5061d52a7b12..81bbb3f7c113 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -1227,17 +1227,19 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
}
if (level == IPOIB_FLUSH_LIGHT) {
- int oper_up;
ipoib_mark_paths_invalid(dev);
- /* Set IPoIB operation as down to prevent races between:
+ /* Set MCAST_FLUSH to prevent races between:
* the flush flow which leaves MCG and on the fly joins
* which can happen during that time. mcast restart task
* should deal with join requests we missed.
+ *
+ * Do not clear OPER_UP for this; restoring it races with
+ * ipoib_ib_dev_down() and can leave OPER_UP set after the
+ * device is down.
*/
- oper_up = test_and_clear_bit(IPOIB_FLAG_OPER_UP, &priv->flags);
+ set_bit(IPOIB_FLAG_MCAST_FLUSH, &priv->flags);
ipoib_mcast_dev_flush(dev);
- if (oper_up)
- set_bit(IPOIB_FLAG_OPER_UP, &priv->flags);
+ clear_bit(IPOIB_FLAG_MCAST_FLUSH, &priv->flags);
ipoib_reap_dead_ahs(priv);
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 402671567736..6c14246befb1 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1297,16 +1297,19 @@ static int ipoib_hard_header(struct sk_buff *skb,
return IPOIB_HARD_LEN;
}
-static void ipoib_set_mcast_list(struct net_device *dev)
+static int ipoib_set_rx_mode_async(struct net_device *dev,
+ struct netdev_hw_addr_list *uc,
+ struct netdev_hw_addr_list *mc)
{
struct ipoib_dev_priv *priv = ipoib_priv(dev);
if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) {
ipoib_dbg(priv, "IPOIB_FLAG_OPER_UP not set");
- return;
+ return 0;
}
queue_work(priv->wq, &priv->restart_task);
+ return 0;
}
static int ipoib_get_iflink(const struct net_device *dev)
@@ -2160,7 +2163,7 @@ static const struct net_device_ops ipoib_netdev_ops_pf = {
.ndo_fix_features = ipoib_fix_features,
.ndo_start_xmit = ipoib_start_xmit,
.ndo_tx_timeout = ipoib_timeout,
- .ndo_set_rx_mode = ipoib_set_mcast_list,
+ .ndo_set_rx_mode_async = ipoib_set_rx_mode_async,
.ndo_get_iflink = ipoib_get_iflink,
.ndo_set_vf_link_state = ipoib_set_vf_link_state,
.ndo_get_vf_config = ipoib_get_vf_config,
@@ -2183,7 +2186,7 @@ static const struct net_device_ops ipoib_netdev_ops_vf = {
.ndo_fix_features = ipoib_fix_features,
.ndo_start_xmit = ipoib_start_xmit,
.ndo_tx_timeout = ipoib_timeout,
- .ndo_set_rx_mode = ipoib_set_mcast_list,
+ .ndo_set_rx_mode_async = ipoib_set_rx_mode_async,
.ndo_get_iflink = ipoib_get_iflink,
.ndo_get_stats64 = ipoib_get_stats,
.ndo_eth_ioctl = ipoib_ioctl,
@@ -2780,6 +2783,7 @@ err_client:
err_sa:
ib_sa_unregister_client(&ipoib_sa_client);
destroy_workqueue(ipoib_workqueue);
+ rcu_barrier();
err_fs:
ipoib_unregister_debugfs();
@@ -2797,6 +2801,7 @@ static void __exit ipoib_cleanup_module(void)
ib_sa_unregister_client(&ipoib_sa_client);
ipoib_unregister_debugfs();
destroy_workqueue(ipoib_workqueue);
+ rcu_barrier();
}
module_init(ipoib_init_module);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 6401af2fd548..379b78374e21 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -74,7 +74,7 @@ static void __ipoib_mcast_schedule_join_thread(struct ipoib_dev_priv *priv,
struct ipoib_mcast *mcast,
bool delay)
{
- if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
+ if (!ipoib_mcast_allowed(priv))
return;
/*
@@ -469,7 +469,7 @@ static int ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast)
int ret = 0;
if (!priv->broadcast ||
- !test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
+ !ipoib_mcast_allowed(priv))
return -EINVAL;
init_completion(&mcast->done);
@@ -555,7 +555,7 @@ void ipoib_mcast_join_task(struct work_struct *work)
unsigned long delay_until = 0;
struct ipoib_mcast *mcast = NULL;
- if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
+ if (!ipoib_mcast_allowed(priv))
return;
if (ib_query_port(priv->ca, priv->port, &port_attr)) {
@@ -577,7 +577,7 @@ void ipoib_mcast_join_task(struct work_struct *work)
netif_addr_unlock_bh(dev);
spin_lock_irq(&priv->lock);
- if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
+ if (!ipoib_mcast_allowed(priv))
goto out;
if (!priv->broadcast) {
@@ -749,7 +749,7 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb)
spin_lock_irqsave(&priv->lock, flags);
- if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags) ||
+ if (!ipoib_mcast_allowed(priv) ||
!priv->broadcast ||
!test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {
++dev->stats.tx_dropped;
@@ -871,7 +871,7 @@ void ipoib_mcast_restart_task(struct work_struct *work)
LIST_HEAD(remove_list);
struct ib_sa_mcmember_rec rec;
- if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
+ if (!ipoib_mcast_allowed(priv))
/*
* shortcut...on shutdown flush is called next, just
* let it do all the work
@@ -965,9 +965,9 @@ void ipoib_mcast_restart_task(struct work_struct *work)
ipoib_mcast_remove_list(&remove_list);
/*
- * Double check that we are still up
+ * Double check that we are still up and not flushing
*/
- if (test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) {
+ if (ipoib_mcast_allowed(priv)) {
spin_lock_irq(&priv->lock);
__ipoib_mcast_schedule_join_thread(priv, NULL, 0);
spin_unlock_irq(&priv->lock);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 3ed1ea566690..2490696a1aab 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -147,8 +147,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
.cap = {
.max_send_wr = ipoib_sendq_size,
.max_recv_wr = ipoib_recvq_size,
- .max_send_sge = min_t(u32, priv->ca->attrs.max_send_sge,
- MAX_SKB_FRAGS + 1),
+ .max_send_sge = min(priv->ca->attrs.max_send_sge, MAX_SKB_FRAGS + 1),
.max_recv_sge = IPOIB_UD_RX_SG
},
.sq_sig_type = IB_SIGNAL_ALL_WR,
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index 12a2d12fef07..7ea6888b479c 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -598,11 +598,8 @@ static int iser_check_remote_inv(struct iser_conn *iser_conn, struct ib_wc *wc,
iser_dbg("conn %p: remote invalidation for rkey %#x\n",
iser_conn, rkey);
- if (unlikely(!iser_conn->snd_w_inv)) {
- iser_err("conn %p: unexpected remote invalidation, terminating connection\n",
- iser_conn);
- return -EPROTO;
- }
+ if (unlikely(!iser_conn->snd_w_inv))
+ goto bad_inv;
task = iscsi_itt_to_ctask(iser_conn->iscsi_conn, hdr->itt);
if (likely(task)) {
@@ -611,12 +608,16 @@ static int iser_check_remote_inv(struct iser_conn *iser_conn, struct ib_wc *wc,
if (iser_task->dir[ISER_DIR_IN]) {
desc = iser_task->rdma_reg[ISER_DIR_IN].desc;
+ if (unlikely(!desc))
+ goto bad_inv;
if (unlikely(iser_inv_desc(desc, rkey)))
return -EINVAL;
}
if (iser_task->dir[ISER_DIR_OUT]) {
desc = iser_task->rdma_reg[ISER_DIR_OUT].desc;
+ if (unlikely(!desc))
+ goto bad_inv;
if (unlikely(iser_inv_desc(desc, rkey)))
return -EINVAL;
}
@@ -627,6 +628,11 @@ static int iser_check_remote_inv(struct iser_conn *iser_conn, struct ib_wc *wc,
}
return 0;
+
+bad_inv:
+ iser_err("conn %p: unexpected remote invalidation, terminating connection\n",
+ iser_conn);
+ return -EPROTO;
}
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index f03b3bb3c0c4..55fe68e5b837 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -244,8 +244,7 @@ static int iser_create_ib_conn_res(struct ib_conn *ib_conn)
max_send_wr = ISER_QP_SIG_MAX_REQ_DTOS + 1;
else
max_send_wr = ISER_QP_MAX_REQ_DTOS + 1;
- max_send_wr = min_t(unsigned int, max_send_wr,
- (unsigned int)ib_dev->attrs.max_qp_wr);
+ max_send_wr = min(max_send_wr, ib_dev->attrs.max_qp_wr);
cq_size = max_send_wr + ISER_QP_MAX_RECV_DTOS;
ib_conn->cq = ib_cq_pool_get(ib_dev, cq_size, -1, IB_POLL_SOFTIRQ);
@@ -589,7 +588,7 @@ static void iser_route_handler(struct rdma_cm_id *cma_id)
goto failure;
memset(&conn_param, 0, sizeof conn_param);
- conn_param.responder_resources = ib_dev->attrs.max_qp_rd_atom;
+ conn_param.responder_resources = min(ib_dev->attrs.max_qp_rd_atom, U8_MAX);
conn_param.initiator_depth = 1;
conn_param.retry_count = 7;
conn_param.rnr_retry_count = 6;
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index 348005e71891..e69db43370ff 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -21,6 +21,7 @@
#include <target/target_core_fabric.h>
#include <target/iscsi/iscsi_transport.h>
#include <linux/semaphore.h>
+#include <linux/wait_bit.h>
#include "ib_isert.h"
@@ -59,6 +60,8 @@ static void isert_recv_done(struct ib_cq *cq, struct ib_wc *wc);
static void isert_send_done(struct ib_cq *cq, struct ib_wc *wc);
static void isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc);
static void isert_login_send_done(struct ib_cq *cq, struct ib_wc *wc);
+static void isert_unmap_tx_desc(struct iser_tx_desc *tx_desc,
+ struct ib_device *ib_dev);
static int isert_sg_tablesize_set(const char *val, const struct kernel_param *kp)
{
@@ -214,9 +217,9 @@ isert_create_device_ib_res(struct isert_device *device)
struct ib_device *ib_dev = device->ib_device;
int ret;
- isert_dbg("devattr->max_send_sge: %d devattr->max_recv_sge %d\n",
+ isert_dbg("devattr->max_send_sge: %u devattr->max_recv_sge %u\n",
ib_dev->attrs.max_send_sge, ib_dev->attrs.max_recv_sge);
- isert_dbg("devattr->max_sge_rd: %d\n", ib_dev->attrs.max_sge_rd);
+ isert_dbg("devattr->max_sge_rd: %u\n", ib_dev->attrs.max_sge_rd);
device->pd = ib_alloc_pd(ib_dev, 0);
if (IS_ERR(device->pd)) {
@@ -308,6 +311,7 @@ isert_init_conn(struct isert_conn *isert_conn)
init_completion(&isert_conn->login_req_comp);
init_waitqueue_head(&isert_conn->rem_wait);
kref_init(&isert_conn->kref);
+ atomic_set(&isert_conn->ctrl_comp_cnt, 0);
mutex_init(&isert_conn->mutex);
INIT_WORK(&isert_conn->release_work, isert_release_work);
}
@@ -381,8 +385,7 @@ isert_set_nego_params(struct isert_conn *isert_conn,
struct ib_device_attr *attr = &isert_conn->device->ib_device->attrs;
/* Set max inflight RDMA READ requests */
- isert_conn->initiator_depth = min_t(u8, param->initiator_depth,
- attr->max_qp_init_rd_atom);
+ isert_conn->initiator_depth = min(param->initiator_depth, attr->max_qp_init_rd_atom);
isert_dbg("Using initiator_depth: %u\n", isert_conn->initiator_depth);
if (param->private_data) {
@@ -496,6 +499,8 @@ isert_connect_release(struct isert_conn *isert_conn)
if (isert_conn->qp)
isert_destroy_qp(isert_conn);
+ isert_unmap_tx_desc(&isert_conn->login_tx_desc, device->ib_device);
+
if (isert_conn->login_desc)
isert_free_login_buf(isert_conn);
@@ -943,27 +948,16 @@ isert_put_login_tx(struct iscsit_conn *conn, struct iscsi_login *login,
}
if (!login->login_failed) {
if (login->login_complete) {
- ret = isert_alloc_rx_descriptors(isert_conn);
- if (ret)
- return ret;
-
- ret = isert_post_recvm(isert_conn,
- ISERT_QP_MAX_RECV_DTOS);
- if (ret)
- return ret;
-
- /* Now we are in FULL_FEATURE phase */
- mutex_lock(&isert_conn->mutex);
- isert_conn->state = ISER_CONN_FULL_FEATURE;
- mutex_unlock(&isert_conn->mutex);
- goto post_send;
+ /* Posted and sent from isert_get_rx_pdu(). */
+ isert_conn->login_rsp_pending = true;
+ return 0;
}
ret = isert_login_post_recv(isert_conn);
if (ret)
return ret;
}
-post_send:
+
ret = isert_login_post_send(isert_conn, tx_desc);
if (ret)
return ret;
@@ -971,6 +965,21 @@ post_send:
return 0;
}
+static int
+isert_check_login_req(struct isert_conn *isert_conn)
+{
+ struct iscsi_hdr *hdr = isert_get_iscsi_hdr(isert_conn->login_desc);
+ u32 dlength = ntoh24(hdr->dlength);
+
+ if (unlikely(dlength > (u32)isert_conn->login_req_len)) {
+ isert_dbg("login PDU declares %u data bytes but only %d were received\n",
+ dlength, isert_conn->login_req_len);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static void
isert_rx_login_req(struct isert_conn *isert_conn)
{
@@ -1333,6 +1342,21 @@ isert_recv_done(struct ib_cq *cq, struct ib_wc *wc)
ib_dma_sync_single_for_cpu(ib_dev, rx_desc->dma_addr,
ISER_RX_SIZE, DMA_FROM_DEVICE);
+ /*
+ * The data segment length declared in the BHS is attacker controlled
+ * and is used further down to read that many bytes out of the fixed
+ * size receive descriptor, so it has to be checked against the number
+ * of bytes that were actually received. Comparing without subtracting
+ * also rejects PDUs shorter than the iSER and iSCSI headers, which
+ * would otherwise be parsed out of stale descriptor contents.
+ */
+ if (unlikely(wc->byte_len < ISER_HEADERS_LEN + ntoh24(hdr->dlength))) {
+ isert_err("PDU declares %u data bytes but only %u bytes were received\n",
+ ntoh24(hdr->dlength), wc->byte_len);
+ iscsit_cause_connection_reinstatement(isert_conn->conn, 0);
+ return;
+ }
+
isert_dbg("DMA: 0x%llx, iSCSI opcode: 0x%02x, ITT: 0x%08x, flags: 0x%02x dlen: %d\n",
rx_desc->dma_addr, hdr->opcode, hdr->itt, hdr->flags,
(int)(wc->byte_len - ISER_HEADERS_LEN));
@@ -1383,13 +1407,23 @@ isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc)
ib_dma_sync_single_for_cpu(ib_dev, isert_conn->login_desc->dma_addr,
ISER_RX_SIZE, DMA_FROM_DEVICE);
+ if (unlikely(wc->byte_len < ISER_HEADERS_LEN)) {
+ isert_dbg("login request length %u is too short\n",
+ wc->byte_len);
+ return;
+ }
+
isert_conn->login_req_len = wc->byte_len - ISER_HEADERS_LEN;
if (isert_conn->conn) {
struct iscsi_login *login = isert_conn->conn->conn_login;
- if (login && !login->first_request)
+ if (login && !login->first_request) {
+ if (isert_check_login_req(isert_conn))
+ return;
+
isert_rx_login_req(isert_conn);
+ }
}
mutex_lock(&isert_conn->mutex);
@@ -1662,6 +1696,8 @@ isert_do_control_comp(struct work_struct *work)
struct isert_conn *isert_conn = isert_cmd->conn;
struct ib_device *ib_dev = isert_conn->cm_id->device;
struct iscsit_cmd *cmd = isert_cmd->iscsit_cmd;
+ /* The switch below may free isert_cmd. */
+ bool counted = isert_cmd->ctrl_counted;
isert_dbg("Cmd %p i_state %d\n", isert_cmd, cmd->i_state);
@@ -1683,6 +1719,14 @@ isert_do_control_comp(struct work_struct *work)
dump_stack();
break;
}
+
+ /*
+ * The count is what keeps isert_conn alive, so drop it last. The wait
+ * queue lives in the global hash table, not in isert_conn, so this is
+ * safe even if the waiter has already freed the connection.
+ */
+ if (counted && atomic_dec_and_test(&isert_conn->ctrl_comp_cnt))
+ wake_up_var(&isert_conn->ctrl_comp_cnt);
}
static void
@@ -1726,6 +1770,12 @@ isert_send_done(struct ib_cq *cq, struct ib_wc *wc)
case ISTATE_SEND_TEXTRSP:
isert_unmap_tx_desc(tx_desc, ib_dev);
+ /* Paired with the wait in isert_wait_conn(). */
+ isert_cmd->ctrl_counted =
+ isert_cmd->iscsit_cmd->i_state != ISTATE_SEND_LOGOUTRSP;
+ if (isert_cmd->ctrl_counted)
+ atomic_inc(&isert_conn->ctrl_comp_cnt);
+
INIT_WORK(&isert_cmd->comp_work, isert_do_control_comp);
queue_work(isert_comp_wq, &isert_cmd->comp_work);
return;
@@ -2354,6 +2404,10 @@ isert_get_login_rx(struct iscsit_conn *conn, struct iscsi_login *login)
if (!login->first_request)
return 0;
+ ret = isert_check_login_req(isert_conn);
+ if (ret)
+ return ret;
+
isert_rx_login_req(isert_conn);
isert_info("before login_comp conn: %p\n", conn);
@@ -2566,6 +2620,10 @@ static void isert_wait_conn(struct iscsit_conn *conn)
isert_wait4cmds(conn);
isert_wait4logout(isert_conn);
+ /* Paired with the count taken in isert_send_done(). */
+ wait_var_event(&isert_conn->ctrl_comp_cnt,
+ !atomic_read(&isert_conn->ctrl_comp_cnt));
+
queue_work(isert_release_wq, &isert_conn->release_work);
}
@@ -2579,8 +2637,30 @@ static void isert_free_conn(struct iscsit_conn *conn)
static void isert_get_rx_pdu(struct iscsit_conn *conn)
{
+ struct isert_conn *isert_conn = conn->context;
struct completion comp;
+ /* The login timeout timer can fail the login after isert_put_login_tx(). */
+ if (!isert_conn->login_rsp_pending)
+ return;
+
+ isert_conn->login_rsp_pending = false;
+
+ /* The session is registered by now; see isert_put_login_tx(). */
+ if (isert_alloc_rx_descriptors(isert_conn))
+ return;
+
+ if (isert_post_recvm(isert_conn, ISERT_QP_MAX_RECV_DTOS))
+ return;
+
+ /* Now we are in FULL_FEATURE phase */
+ mutex_lock(&isert_conn->mutex);
+ isert_conn->state = ISER_CONN_FULL_FEATURE;
+ mutex_unlock(&isert_conn->mutex);
+
+ if (isert_login_post_send(isert_conn, &isert_conn->login_tx_desc))
+ return;
+
init_completion(&comp);
wait_for_completion_interruptible(&comp);
diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h
index 0b2dfd6e7e27..519b17e54bd3 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.h
+++ b/drivers/infiniband/ulp/isert/ib_isert.h
@@ -153,6 +153,7 @@ struct isert_cmd {
struct work_struct comp_work;
struct scatterlist sg;
bool ctx_init_done;
+ bool ctrl_counted;
};
static inline struct isert_cmd *tx_desc_to_cmd(struct iser_tx_desc *desc)
@@ -178,6 +179,7 @@ struct isert_conn {
struct completion login_comp;
struct completion login_req_comp;
struct iser_tx_desc login_tx_desc;
+ bool login_rsp_pending;
struct rdma_cm_id *cm_id;
struct ib_qp *qp;
struct ib_cq *cq;
@@ -186,6 +188,7 @@ struct isert_conn {
struct mutex mutex;
struct kref kref;
struct work_struct release_work;
+ atomic_t ctrl_comp_cnt;
bool logout_posted;
bool snd_w_inv;
wait_queue_head_t rem_wait;
diff --git a/drivers/infiniband/ulp/opa_vnic/Kconfig b/drivers/infiniband/ulp/opa_vnic/Kconfig
deleted file mode 100644
index 4d43d055fa8e..000000000000
--- a/drivers/infiniband/ulp/opa_vnic/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config INFINIBAND_OPA_VNIC
- tristate "Cornelis OPX VNIC support"
- depends on X86_64 && INFINIBAND
- help
- This is Omni-Path Express (OPX) Virtual Network Interface Controller (VNIC)
- driver for Ethernet over Omni-Path feature. It implements the HW
- independent VNIC functionality. It interfaces with Linux stack for
- data path and IB MAD for the control path.
diff --git a/drivers/infiniband/ulp/opa_vnic/Makefile b/drivers/infiniband/ulp/opa_vnic/Makefile
deleted file mode 100644
index 196183817cdc..000000000000
--- a/drivers/infiniband/ulp/opa_vnic/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-# Makefile - Cornelis Omni-Path Express Virtual Network Controller driver
-# Copyright(c) 2017, Intel Corporation.
-# Copyright(c) 2021, Cornelis Networks.
-#
-obj-$(CONFIG_INFINIBAND_OPA_VNIC) += opa_vnic.o
-
-opa_vnic-y := opa_vnic_netdev.o opa_vnic_encap.o opa_vnic_ethtool.o \
- opa_vnic_vema.o opa_vnic_vema_iface.o
diff --git a/drivers/infiniband/ulp/opa_vnic/opa_vnic_encap.c b/drivers/infiniband/ulp/opa_vnic/opa_vnic_encap.c
deleted file mode 100644
index 53dcf06fbee0..000000000000
--- a/drivers/infiniband/ulp/opa_vnic/opa_vnic_encap.c
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * Copyright(c) 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
- * This file contains OPA VNIC encapsulation/decapsulation function.
- */
-
-#include <linux/if_ether.h>
-#include <linux/if_vlan.h>
-
-#include "opa_vnic_internal.h"
-
-/* OPA 16B Header fields */
-#define OPA_16B_LID_MASK 0xFFFFFull
-#define OPA_16B_SLID_HIGH_SHFT 8
-#define OPA_16B_SLID_MASK 0xF00ull
-#define OPA_16B_DLID_MASK 0xF000ull
-#define OPA_16B_DLID_HIGH_SHFT 12
-#define OPA_16B_LEN_SHFT 20
-#define OPA_16B_SC_SHFT 20
-#define OPA_16B_RC_SHFT 25
-#define OPA_16B_PKEY_SHFT 16
-
-#define OPA_VNIC_L4_HDR_SHFT 16
-
-/* L2+L4 hdr len is 20 bytes (5 quad words) */
-#define OPA_VNIC_HDR_QW_LEN 5
-
-static inline void opa_vnic_make_header(u8 *hdr, u32 slid, u32 dlid, u16 len,
- u16 pkey, u16 entropy, u8 sc, u8 rc,
- u8 l4_type, u16 l4_hdr)
-{
- /* h[1]: LT=1, 16B L2=10 */
- u32 h[OPA_VNIC_HDR_QW_LEN] = {0, 0xc0000000, 0, 0, 0};
-
- h[2] = l4_type;
- h[3] = entropy;
- h[4] = l4_hdr << OPA_VNIC_L4_HDR_SHFT;
-
- /* Extract and set 4 upper bits and 20 lower bits of the lids */
- h[0] |= (slid & OPA_16B_LID_MASK);
- h[2] |= ((slid >> (20 - OPA_16B_SLID_HIGH_SHFT)) & OPA_16B_SLID_MASK);
-
- h[1] |= (dlid & OPA_16B_LID_MASK);
- h[2] |= ((dlid >> (20 - OPA_16B_DLID_HIGH_SHFT)) & OPA_16B_DLID_MASK);
-
- h[0] |= (len << OPA_16B_LEN_SHFT);
- h[1] |= (rc << OPA_16B_RC_SHFT);
- h[1] |= (sc << OPA_16B_SC_SHFT);
- h[2] |= ((u32)pkey << OPA_16B_PKEY_SHFT);
-
- memcpy(hdr, h, OPA_VNIC_HDR_LEN);
-}
-
-/*
- * Using a simple hash table for mac table implementation with the last octet
- * of mac address as a key.
- */
-static void opa_vnic_free_mac_tbl(struct hlist_head *mactbl)
-{
- struct opa_vnic_mac_tbl_node *node;
- struct hlist_node *tmp;
- int bkt;
-
- if (!mactbl)
- return;
-
- vnic_hash_for_each_safe(mactbl, bkt, tmp, node, hlist) {
- hash_del(&node->hlist);
- kfree(node);
- }
- kfree(mactbl);
-}
-
-static struct hlist_head *opa_vnic_alloc_mac_tbl(void)
-{
- u32 size = sizeof(struct hlist_head) * OPA_VNIC_MAC_TBL_SIZE;
- struct hlist_head *mactbl;
-
- mactbl = kzalloc(size, GFP_KERNEL);
- if (!mactbl)
- return ERR_PTR(-ENOMEM);
-
- vnic_hash_init(mactbl);
- return mactbl;
-}
-
-/* opa_vnic_release_mac_tbl - empty and free the mac table */
-void opa_vnic_release_mac_tbl(struct opa_vnic_adapter *adapter)
-{
- struct hlist_head *mactbl;
-
- mutex_lock(&adapter->mactbl_lock);
- mactbl = rcu_access_pointer(adapter->mactbl);
- rcu_assign_pointer(adapter->mactbl, NULL);
- synchronize_rcu();
- opa_vnic_free_mac_tbl(mactbl);
- adapter->info.vport.mac_tbl_digest = 0;
- mutex_unlock(&adapter->mactbl_lock);
-}
-
-/*
- * opa_vnic_query_mac_tbl - query the mac table for a section
- *
- * This function implements query of specific function of the mac table.
- * The function also expects the requested range to be valid.
- */
-void opa_vnic_query_mac_tbl(struct opa_vnic_adapter *adapter,
- struct opa_veswport_mactable *tbl)
-{
- struct opa_vnic_mac_tbl_node *node;
- struct hlist_head *mactbl;
- int bkt;
- u16 loffset, lnum_entries;
-
- rcu_read_lock();
- mactbl = rcu_dereference(adapter->mactbl);
- if (!mactbl)
- goto get_mac_done;
-
- loffset = be16_to_cpu(tbl->offset);
- lnum_entries = be16_to_cpu(tbl->num_entries);
-
- vnic_hash_for_each(mactbl, bkt, node, hlist) {
- struct __opa_vnic_mactable_entry *nentry = &node->entry;
- struct opa_veswport_mactable_entry *entry;
-
- if ((node->index < loffset) ||
- (node->index >= (loffset + lnum_entries)))
- continue;
-
- /* populate entry in the tbl corresponding to the index */
- entry = &tbl->tbl_entries[node->index - loffset];
- memcpy(entry->mac_addr, nentry->mac_addr,
- ARRAY_SIZE(entry->mac_addr));
- memcpy(entry->mac_addr_mask, nentry->mac_addr_mask,
- ARRAY_SIZE(entry->mac_addr_mask));
- entry->dlid_sd = cpu_to_be32(nentry->dlid_sd);
- }
- tbl->mac_tbl_digest = cpu_to_be32(adapter->info.vport.mac_tbl_digest);
-get_mac_done:
- rcu_read_unlock();
-}
-
-/*
- * opa_vnic_update_mac_tbl - update mac table section
- *
- * This function updates the specified section of the mac table.
- * The procedure includes following steps.
- * - Allocate a new mac (hash) table.
- * - Add the specified entries to the new table.
- * (except the ones that are requested to be deleted).
- * - Add all the other entries from the old mac table.
- * - If there is a failure, free the new table and return.
- * - Switch to the new table.
- * - Free the old table and return.
- *
- * The function also expects the requested range to be valid.
- */
-int opa_vnic_update_mac_tbl(struct opa_vnic_adapter *adapter,
- struct opa_veswport_mactable *tbl)
-{
- struct opa_vnic_mac_tbl_node *node, *new_node;
- struct hlist_head *new_mactbl, *old_mactbl;
- int i, bkt, rc = 0;
- u8 key;
- u16 loffset, lnum_entries;
-
- mutex_lock(&adapter->mactbl_lock);
- /* allocate new mac table */
- new_mactbl = opa_vnic_alloc_mac_tbl();
- if (IS_ERR(new_mactbl)) {
- mutex_unlock(&adapter->mactbl_lock);
- return PTR_ERR(new_mactbl);
- }
-
- loffset = be16_to_cpu(tbl->offset);
- lnum_entries = be16_to_cpu(tbl->num_entries);
-
- /* add updated entries to the new mac table */
- for (i = 0; i < lnum_entries; i++) {
- struct __opa_vnic_mactable_entry *nentry;
- struct opa_veswport_mactable_entry *entry =
- &tbl->tbl_entries[i];
- u8 *mac_addr = entry->mac_addr;
- u8 empty_mac[ETH_ALEN] = { 0 };
-
- v_dbg("new mac entry %4d: %02x:%02x:%02x:%02x:%02x:%02x %x\n",
- loffset + i, mac_addr[0], mac_addr[1], mac_addr[2],
- mac_addr[3], mac_addr[4], mac_addr[5],
- entry->dlid_sd);
-
- /* if the entry is being removed, do not add it */
- if (!memcmp(mac_addr, empty_mac, ARRAY_SIZE(empty_mac)))
- continue;
-
- node = kzalloc_obj(*node);
- if (!node) {
- rc = -ENOMEM;
- goto updt_done;
- }
-
- node->index = loffset + i;
- nentry = &node->entry;
- memcpy(nentry->mac_addr, entry->mac_addr,
- ARRAY_SIZE(nentry->mac_addr));
- memcpy(nentry->mac_addr_mask, entry->mac_addr_mask,
- ARRAY_SIZE(nentry->mac_addr_mask));
- nentry->dlid_sd = be32_to_cpu(entry->dlid_sd);
- key = node->entry.mac_addr[OPA_VNIC_MAC_HASH_IDX];
- vnic_hash_add(new_mactbl, &node->hlist, key);
- }
-
- /* add other entries from current mac table to new mac table */
- old_mactbl = rcu_access_pointer(adapter->mactbl);
- if (!old_mactbl)
- goto switch_tbl;
-
- vnic_hash_for_each(old_mactbl, bkt, node, hlist) {
- if ((node->index >= loffset) &&
- (node->index < (loffset + lnum_entries)))
- continue;
-
- new_node = kzalloc_obj(*new_node);
- if (!new_node) {
- rc = -ENOMEM;
- goto updt_done;
- }
-
- new_node->index = node->index;
- memcpy(&new_node->entry, &node->entry, sizeof(node->entry));
- key = new_node->entry.mac_addr[OPA_VNIC_MAC_HASH_IDX];
- vnic_hash_add(new_mactbl, &new_node->hlist, key);
- }
-
-switch_tbl:
- /* switch to new table */
- rcu_assign_pointer(adapter->mactbl, new_mactbl);
- synchronize_rcu();
-
- adapter->info.vport.mac_tbl_digest = be32_to_cpu(tbl->mac_tbl_digest);
-updt_done:
- /* upon failure, free the new table; otherwise, free the old table */
- if (rc)
- opa_vnic_free_mac_tbl(new_mactbl);
- else
- opa_vnic_free_mac_tbl(old_mactbl);
-
- mutex_unlock(&adapter->mactbl_lock);
- return rc;
-}
-
-/* opa_vnic_chk_mac_tbl - check mac table for dlid */
-static uint32_t opa_vnic_chk_mac_tbl(struct opa_vnic_adapter *adapter,
- struct ethhdr *mac_hdr)
-{
- struct opa_vnic_mac_tbl_node *node;
- struct hlist_head *mactbl;
- u32 dlid = 0;
- u8 key;
-
- rcu_read_lock();
- mactbl = rcu_dereference(adapter->mactbl);
- if (unlikely(!mactbl))
- goto chk_done;
-
- key = mac_hdr->h_dest[OPA_VNIC_MAC_HASH_IDX];
- vnic_hash_for_each_possible(mactbl, node, hlist, key) {
- struct __opa_vnic_mactable_entry *entry = &node->entry;
-
- /* if related to source mac, skip */
- if (unlikely(OPA_VNIC_DLID_SD_IS_SRC_MAC(entry->dlid_sd)))
- continue;
-
- if (!memcmp(node->entry.mac_addr, mac_hdr->h_dest,
- ARRAY_SIZE(node->entry.mac_addr))) {
- /* mac address found */
- dlid = OPA_VNIC_DLID_SD_GET_DLID(node->entry.dlid_sd);
- break;
- }
- }
-
-chk_done:
- rcu_read_unlock();
- return dlid;
-}
-
-/* opa_vnic_get_dlid - find and return the DLID */
-static uint32_t opa_vnic_get_dlid(struct opa_vnic_adapter *adapter,
- struct sk_buff *skb, u8 def_port)
-{
- struct __opa_veswport_info *info = &adapter->info;
- struct ethhdr *mac_hdr = (struct ethhdr *)skb_mac_header(skb);
- u32 dlid;
-
- dlid = opa_vnic_chk_mac_tbl(adapter, mac_hdr);
- if (dlid)
- return dlid;
-
- if (is_multicast_ether_addr(mac_hdr->h_dest)) {
- dlid = info->vesw.u_mcast_dlid;
- } else {
- if (is_local_ether_addr(mac_hdr->h_dest)) {
- dlid = ((uint32_t)mac_hdr->h_dest[5] << 16) |
- ((uint32_t)mac_hdr->h_dest[4] << 8) |
- mac_hdr->h_dest[3];
- if (unlikely(!dlid))
- v_warn("Null dlid in MAC address\n");
- } else if (def_port != OPA_VNIC_INVALID_PORT) {
- if (def_port < OPA_VESW_MAX_NUM_DEF_PORT)
- dlid = info->vesw.u_ucast_dlid[def_port];
- }
- }
-
- return dlid;
-}
-
-/* opa_vnic_get_sc - return the service class */
-static u8 opa_vnic_get_sc(struct __opa_veswport_info *info,
- struct sk_buff *skb)
-{
- struct ethhdr *mac_hdr = (struct ethhdr *)skb_mac_header(skb);
- u16 vlan_tci;
- u8 sc;
-
- if (!__vlan_get_tag(skb, &vlan_tci)) {
- u8 pcp = OPA_VNIC_VLAN_PCP(vlan_tci);
-
- if (is_multicast_ether_addr(mac_hdr->h_dest))
- sc = info->vport.pcp_to_sc_mc[pcp];
- else
- sc = info->vport.pcp_to_sc_uc[pcp];
- } else {
- if (is_multicast_ether_addr(mac_hdr->h_dest))
- sc = info->vport.non_vlan_sc_mc;
- else
- sc = info->vport.non_vlan_sc_uc;
- }
-
- return sc;
-}
-
-u8 opa_vnic_get_vl(struct opa_vnic_adapter *adapter, struct sk_buff *skb)
-{
- struct ethhdr *mac_hdr = (struct ethhdr *)skb_mac_header(skb);
- struct __opa_veswport_info *info = &adapter->info;
- u8 vl;
-
- if (skb_vlan_tag_present(skb)) {
- u8 pcp = skb_vlan_tag_get(skb) >> VLAN_PRIO_SHIFT;
-
- if (is_multicast_ether_addr(mac_hdr->h_dest))
- vl = info->vport.pcp_to_vl_mc[pcp];
- else
- vl = info->vport.pcp_to_vl_uc[pcp];
- } else {
- if (is_multicast_ether_addr(mac_hdr->h_dest))
- vl = info->vport.non_vlan_vl_mc;
- else
- vl = info->vport.non_vlan_vl_uc;
- }
-
- return vl;
-}
-
-/* opa_vnic_get_rc - return the routing control */
-static u8 opa_vnic_get_rc(struct __opa_veswport_info *info,
- struct sk_buff *skb)
-{
- u8 proto, rout_ctrl;
-
- switch (vlan_get_protocol(skb)) {
- case htons(ETH_P_IPV6):
- proto = ipv6_hdr(skb)->nexthdr;
- if (proto == IPPROTO_TCP)
- rout_ctrl = OPA_VNIC_ENCAP_RC_EXT(info->vesw.rc,
- IPV6_TCP);
- else if (proto == IPPROTO_UDP)
- rout_ctrl = OPA_VNIC_ENCAP_RC_EXT(info->vesw.rc,
- IPV6_UDP);
- else
- rout_ctrl = OPA_VNIC_ENCAP_RC_EXT(info->vesw.rc, IPV6);
- break;
- case htons(ETH_P_IP):
- proto = ip_hdr(skb)->protocol;
- if (proto == IPPROTO_TCP)
- rout_ctrl = OPA_VNIC_ENCAP_RC_EXT(info->vesw.rc,
- IPV4_TCP);
- else if (proto == IPPROTO_UDP)
- rout_ctrl = OPA_VNIC_ENCAP_RC_EXT(info->vesw.rc,
- IPV4_UDP);
- else
- rout_ctrl = OPA_VNIC_ENCAP_RC_EXT(info->vesw.rc, IPV4);
- break;
- default:
- rout_ctrl = OPA_VNIC_ENCAP_RC_EXT(info->vesw.rc, DEFAULT);
- }
-
- return rout_ctrl;
-}
-
-/* opa_vnic_calc_entropy - calculate the packet entropy */
-u8 opa_vnic_calc_entropy(struct sk_buff *skb)
-{
- u32 hash = skb_get_hash(skb);
-
- /* store XOR of all bytes in lower 8 bits */
- hash ^= hash >> 8;
- hash ^= hash >> 16;
-
- /* return lower 8 bits as entropy */
- return (u8)(hash & 0xFF);
-}
-
-/* opa_vnic_get_def_port - get default port based on entropy */
-static inline u8 opa_vnic_get_def_port(struct opa_vnic_adapter *adapter,
- u8 entropy)
-{
- u8 flow_id;
-
- /* Add the upper and lower 4-bits of entropy to get the flow id */
- flow_id = ((entropy & 0xf) + (entropy >> 4));
- return adapter->flow_tbl[flow_id & (OPA_VNIC_FLOW_TBL_SIZE - 1)];
-}
-
-/* Calculate packet length including OPA header, crc and padding */
-static inline int opa_vnic_wire_length(struct sk_buff *skb)
-{
- u32 pad_len;
-
- /* padding for 8 bytes size alignment */
- pad_len = -(skb->len + OPA_VNIC_ICRC_TAIL_LEN) & 0x7;
- pad_len += OPA_VNIC_ICRC_TAIL_LEN;
-
- return (skb->len + pad_len) >> 3;
-}
-
-/* opa_vnic_encap_skb - encapsulate skb packet with OPA header and meta data */
-void opa_vnic_encap_skb(struct opa_vnic_adapter *adapter, struct sk_buff *skb)
-{
- struct __opa_veswport_info *info = &adapter->info;
- struct opa_vnic_skb_mdata *mdata;
- u8 def_port, sc, rc, entropy, *hdr;
- u16 len, l4_hdr;
- u32 dlid;
-
- hdr = skb_push(skb, OPA_VNIC_HDR_LEN);
-
- entropy = opa_vnic_calc_entropy(skb);
- def_port = opa_vnic_get_def_port(adapter, entropy);
- len = opa_vnic_wire_length(skb);
- dlid = opa_vnic_get_dlid(adapter, skb, def_port);
- sc = opa_vnic_get_sc(info, skb);
- rc = opa_vnic_get_rc(info, skb);
- l4_hdr = info->vesw.vesw_id;
-
- mdata = skb_push(skb, sizeof(*mdata));
- mdata->vl = opa_vnic_get_vl(adapter, skb);
- mdata->entropy = entropy;
- mdata->flags = 0;
- if (unlikely(!dlid)) {
- mdata->flags = OPA_VNIC_SKB_MDATA_ENCAP_ERR;
- return;
- }
-
- opa_vnic_make_header(hdr, info->vport.encap_slid, dlid, len,
- info->vesw.pkey, entropy, sc, rc,
- OPA_VNIC_L4_ETHR, l4_hdr);
-}
diff --git a/drivers/infiniband/ulp/opa_vnic/opa_vnic_encap.h b/drivers/infiniband/ulp/opa_vnic/opa_vnic_encap.h
deleted file mode 100644
index 012fc27c5c93..000000000000
--- a/drivers/infiniband/ulp/opa_vnic/opa_vnic_encap.h
+++ /dev/null
@@ -1,524 +0,0 @@
-#ifndef _OPA_VNIC_ENCAP_H
-#define _OPA_VNIC_ENCAP_H
-/*
- * Copyright(c) 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
- * This file contains all OPA VNIC declaration required for encapsulation
- * and decapsulation of Ethernet packets
- */
-
-#include <linux/types.h>
-#include <rdma/ib_mad.h>
-
-/* EMA class version */
-#define OPA_EMA_CLASS_VERSION 0x80
-
-/*
- * Define the Intel vendor management class for OPA
- * ETHERNET MANAGEMENT
- */
-#define OPA_MGMT_CLASS_INTEL_EMA 0x34
-
-/* EM attribute IDs */
-#define OPA_EM_ATTR_CLASS_PORT_INFO 0x0001
-#define OPA_EM_ATTR_VESWPORT_INFO 0x0011
-#define OPA_EM_ATTR_VESWPORT_MAC_ENTRIES 0x0012
-#define OPA_EM_ATTR_IFACE_UCAST_MACS 0x0013
-#define OPA_EM_ATTR_IFACE_MCAST_MACS 0x0014
-#define OPA_EM_ATTR_DELETE_VESW 0x0015
-#define OPA_EM_ATTR_VESWPORT_SUMMARY_COUNTERS 0x0020
-#define OPA_EM_ATTR_VESWPORT_ERROR_COUNTERS 0x0022
-
-/* VNIC configured and operational state values */
-#define OPA_VNIC_STATE_DROP_ALL 0x1
-#define OPA_VNIC_STATE_FORWARDING 0x3
-
-#define OPA_VESW_MAX_NUM_DEF_PORT 16
-#define OPA_VNIC_MAX_NUM_PCP 8
-
-#define OPA_VNIC_EMA_DATA (OPA_MGMT_MAD_SIZE - IB_MGMT_VENDOR_HDR)
-
-/* Defines for vendor specific notice(trap) attributes */
-#define OPA_INTEL_EMA_NOTICE_TYPE_INFO 0x04
-
-/* INTEL OUI */
-#define INTEL_OUI_1 0x00
-#define INTEL_OUI_2 0x06
-#define INTEL_OUI_3 0x6a
-
-/* Trap opcodes sent from VNIC */
-#define OPA_VESWPORT_TRAP_IFACE_UCAST_MAC_CHANGE 0x1
-#define OPA_VESWPORT_TRAP_IFACE_MCAST_MAC_CHANGE 0x2
-#define OPA_VESWPORT_TRAP_ETH_LINK_STATUS_CHANGE 0x3
-
-#define OPA_VNIC_DLID_SD_IS_SRC_MAC(dlid_sd) (!!((dlid_sd) & 0x20))
-#define OPA_VNIC_DLID_SD_GET_DLID(dlid_sd) ((dlid_sd) >> 8)
-
-/* VNIC Ethernet link status */
-#define OPA_VNIC_ETH_LINK_UP 1
-#define OPA_VNIC_ETH_LINK_DOWN 2
-
-/* routing control */
-#define OPA_VNIC_ENCAP_RC_DEFAULT 0
-#define OPA_VNIC_ENCAP_RC_IPV4 4
-#define OPA_VNIC_ENCAP_RC_IPV4_UDP 8
-#define OPA_VNIC_ENCAP_RC_IPV4_TCP 12
-#define OPA_VNIC_ENCAP_RC_IPV6 16
-#define OPA_VNIC_ENCAP_RC_IPV6_TCP 20
-#define OPA_VNIC_ENCAP_RC_IPV6_UDP 24
-
-#define OPA_VNIC_ENCAP_RC_EXT(w, b) (((w) >> OPA_VNIC_ENCAP_RC_ ## b) & 0x7)
-
-/**
- * struct opa_vesw_info - OPA vnic switch information
- * @fabric_id: 10-bit fabric id
- * @vesw_id: 12-bit virtual ethernet switch id
- * @rsvd0: reserved bytes
- * @def_port_mask: bitmask of default ports
- * @rsvd1: reserved bytes
- * @pkey: partition key
- * @rsvd2: reserved bytes
- * @u_mcast_dlid: unknown multicast dlid
- * @u_ucast_dlid: array of unknown unicast dlids
- * @rsvd3: reserved bytes
- * @rc: routing control
- * @eth_mtu: Ethernet MTU
- * @rsvd4: reserved bytes
- */
-struct opa_vesw_info {
- __be16 fabric_id;
- __be16 vesw_id;
-
- u8 rsvd0[6];
- __be16 def_port_mask;
-
- u8 rsvd1[2];
- __be16 pkey;
-
- u8 rsvd2[4];
- __be32 u_mcast_dlid;
- __be32 u_ucast_dlid[OPA_VESW_MAX_NUM_DEF_PORT];
-
- __be32 rc;
-
- u8 rsvd3[56];
- __be16 eth_mtu;
- u8 rsvd4[2];
-} __packed;
-
-/**
- * struct opa_per_veswport_info - OPA vnic per port information
- * @port_num: port number
- * @eth_link_status: current ethernet link state
- * @rsvd0: reserved bytes
- * @base_mac_addr: base mac address
- * @config_state: configured port state
- * @oper_state: operational port state
- * @max_mac_tbl_ent: max number of mac table entries
- * @max_smac_ent: max smac entries in mac table
- * @mac_tbl_digest: mac table digest
- * @rsvd1: reserved bytes
- * @encap_slid: base slid for the port
- * @pcp_to_sc_uc: sc by pcp index for unicast ethernet packets
- * @pcp_to_vl_uc: vl by pcp index for unicast ethernet packets
- * @pcp_to_sc_mc: sc by pcp index for multicast ethernet packets
- * @pcp_to_vl_mc: vl by pcp index for multicast ethernet packets
- * @non_vlan_sc_uc: sc for non-vlan unicast ethernet packets
- * @non_vlan_vl_uc: vl for non-vlan unicast ethernet packets
- * @non_vlan_sc_mc: sc for non-vlan multicast ethernet packets
- * @non_vlan_vl_mc: vl for non-vlan multicast ethernet packets
- * @rsvd2: reserved bytes
- * @uc_macs_gen_count: generation count for unicast macs list
- * @mc_macs_gen_count: generation count for multicast macs list
- * @rsvd3: reserved bytes
- */
-struct opa_per_veswport_info {
- __be32 port_num;
-
- u8 eth_link_status;
- u8 rsvd0[3];
-
- u8 base_mac_addr[ETH_ALEN];
- u8 config_state;
- u8 oper_state;
-
- __be16 max_mac_tbl_ent;
- __be16 max_smac_ent;
- __be32 mac_tbl_digest;
- u8 rsvd1[4];
-
- __be32 encap_slid;
-
- u8 pcp_to_sc_uc[OPA_VNIC_MAX_NUM_PCP];
- u8 pcp_to_vl_uc[OPA_VNIC_MAX_NUM_PCP];
- u8 pcp_to_sc_mc[OPA_VNIC_MAX_NUM_PCP];
- u8 pcp_to_vl_mc[OPA_VNIC_MAX_NUM_PCP];
-
- u8 non_vlan_sc_uc;
- u8 non_vlan_vl_uc;
- u8 non_vlan_sc_mc;
- u8 non_vlan_vl_mc;
-
- u8 rsvd2[48];
-
- __be16 uc_macs_gen_count;
- __be16 mc_macs_gen_count;
-
- u8 rsvd3[8];
-} __packed;
-
-/**
- * struct opa_veswport_info - OPA vnic port information
- * @vesw: OPA vnic switch information
- * @vport: OPA vnic per port information
- *
- * On host, each of the virtual ethernet ports belongs
- * to a different virtual ethernet switches.
- */
-struct opa_veswport_info {
- struct opa_vesw_info vesw;
- struct opa_per_veswport_info vport;
-};
-
-/**
- * struct opa_veswport_mactable_entry - single entry in the forwarding table
- * @mac_addr: MAC address
- * @mac_addr_mask: MAC address bit mask
- * @dlid_sd: Matching DLID and side data
- *
- * On the host each virtual ethernet port will have
- * a forwarding table. These tables are used to
- * map a MAC to a LID and other data. For more
- * details see struct opa_veswport_mactable_entries.
- * This is the structure of a single mactable entry
- */
-struct opa_veswport_mactable_entry {
- u8 mac_addr[ETH_ALEN];
- u8 mac_addr_mask[ETH_ALEN];
- __be32 dlid_sd;
-} __packed;
-
-/**
- * struct opa_veswport_mactable - Forwarding table array
- * @offset: mac table starting offset
- * @num_entries: Number of entries to get or set
- * @mac_tbl_digest: mac table digest
- * @tbl_entries: Array of table entries
- *
- * The EM sends down this structure in a MAD indicating
- * the starting offset in the forwarding table that this
- * entry is to be loaded into and the number of entries
- * that that this MAD instance contains
- * The mac_tbl_digest has been added to this MAD structure. It will be set by
- * the EM and it will be used by the EM to check if there are any
- * discrepancies with this value and the value
- * maintained by the EM in the case of VNIC port being deleted or unloaded
- * A new instantiation of a VNIC will always have a value of zero.
- * This value is stored as part of the vnic adapter structure and will be
- * accessed by the GET and SET routines for both the mactable entries and the
- * veswport info.
- */
-struct opa_veswport_mactable {
- __be16 offset;
- __be16 num_entries;
- __be32 mac_tbl_digest;
- struct opa_veswport_mactable_entry tbl_entries[];
-} __packed;
-
-/**
- * struct opa_veswport_summary_counters - summary counters
- * @vp_instance: vport instance on the OPA port
- * @vesw_id: virtual ethernet switch id
- * @veswport_num: virtual ethernet switch port number
- * @tx_errors: transmit errors
- * @rx_errors: receive errors
- * @tx_packets: transmit packets
- * @rx_packets: receive packets
- * @tx_bytes: transmit bytes
- * @rx_bytes: receive bytes
- * @tx_unicast: unicast packets transmitted
- * @tx_mcastbcast: multicast/broadcast packets transmitted
- * @tx_untagged: non-vlan packets transmitted
- * @tx_vlan: vlan packets transmitted
- * @tx_64_size: transmit packet length is 64 bytes
- * @tx_65_127: transmit packet length is >=65 and < 127 bytes
- * @tx_128_255: transmit packet length is >=128 and < 255 bytes
- * @tx_256_511: transmit packet length is >=256 and < 511 bytes
- * @tx_512_1023: transmit packet length is >=512 and < 1023 bytes
- * @tx_1024_1518: transmit packet length is >=1024 and < 1518 bytes
- * @tx_1519_max: transmit packet length >= 1519 bytes
- * @rx_unicast: unicast packets received
- * @rx_mcastbcast: multicast/broadcast packets received
- * @rx_untagged: non-vlan packets received
- * @rx_vlan: vlan packets received
- * @rx_64_size: received packet length is 64 bytes
- * @rx_65_127: received packet length is >=65 and < 127 bytes
- * @rx_128_255: received packet length is >=128 and < 255 bytes
- * @rx_256_511: received packet length is >=256 and < 511 bytes
- * @rx_512_1023: received packet length is >=512 and < 1023 bytes
- * @rx_1024_1518: received packet length is >=1024 and < 1518 bytes
- * @rx_1519_max: received packet length >= 1519 bytes
- * @reserved: reserved bytes
- *
- * All the above are counters of corresponding conditions.
- */
-struct opa_veswport_summary_counters {
- __be16 vp_instance;
- __be16 vesw_id;
- __be32 veswport_num;
-
- __be64 tx_errors;
- __be64 rx_errors;
- __be64 tx_packets;
- __be64 rx_packets;
- __be64 tx_bytes;
- __be64 rx_bytes;
-
- __be64 tx_unicast;
- __be64 tx_mcastbcast;
-
- __be64 tx_untagged;
- __be64 tx_vlan;
-
- __be64 tx_64_size;
- __be64 tx_65_127;
- __be64 tx_128_255;
- __be64 tx_256_511;
- __be64 tx_512_1023;
- __be64 tx_1024_1518;
- __be64 tx_1519_max;
-
- __be64 rx_unicast;
- __be64 rx_mcastbcast;
-
- __be64 rx_untagged;
- __be64 rx_vlan;
-
- __be64 rx_64_size;
- __be64 rx_65_127;
- __be64 rx_128_255;
- __be64 rx_256_511;
- __be64 rx_512_1023;
- __be64 rx_1024_1518;
- __be64 rx_1519_max;
-
- __be64 reserved[16];
-} __packed;
-
-/**
- * struct opa_veswport_error_counters - error counters
- * @vp_instance: vport instance on the OPA port
- * @vesw_id: virtual ethernet switch id
- * @veswport_num: virtual ethernet switch port number
- * @tx_errors: transmit errors
- * @rx_errors: receive errors
- * @rsvd0: reserved bytes
- * @tx_smac_filt: smac filter errors
- * @rsvd1: reserved bytes
- * @rsvd2: reserved bytes
- * @rsvd3: reserved bytes
- * @tx_dlid_zero: transmit packets with invalid dlid
- * @rsvd4: reserved bytes
- * @tx_logic: other transmit errors
- * @rsvd5: reserved bytes
- * @tx_drop_state: packet tansmission in non-forward port state
- * @rx_bad_veswid: received packet with invalid vesw id
- * @rsvd6: reserved bytes
- * @rx_runt: received ethernet packet with length < 64 bytes
- * @rx_oversize: received ethernet packet with length > MTU size
- * @rsvd7: reserved bytes
- * @rx_eth_down: received packets when interface is down
- * @rx_drop_state: received packets in non-forwarding port state
- * @rx_logic: other receive errors
- * @rsvd8: reserved bytes
- * @rsvd9: reserved bytes
- *
- * All the above are counters of corresponding error conditions.
- */
-struct opa_veswport_error_counters {
- __be16 vp_instance;
- __be16 vesw_id;
- __be32 veswport_num;
-
- __be64 tx_errors;
- __be64 rx_errors;
-
- __be64 rsvd0;
- __be64 tx_smac_filt;
- __be64 rsvd1;
- __be64 rsvd2;
- __be64 rsvd3;
- __be64 tx_dlid_zero;
- __be64 rsvd4;
- __be64 tx_logic;
- __be64 rsvd5;
- __be64 tx_drop_state;
-
- __be64 rx_bad_veswid;
- __be64 rsvd6;
- __be64 rx_runt;
- __be64 rx_oversize;
- __be64 rsvd7;
- __be64 rx_eth_down;
- __be64 rx_drop_state;
- __be64 rx_logic;
- __be64 rsvd8;
-
- __be64 rsvd9[16];
-} __packed;
-
-/**
- * struct opa_veswport_trap - Trap message sent to EM by VNIC
- * @fabric_id: 10 bit fabric id
- * @veswid: 12 bit virtual ethernet switch id
- * @veswportnum: logical port number on the Virtual switch
- * @opaportnum: physical port num (redundant on host)
- * @veswportindex: switch port index on opa port 0 based
- * @opcode: operation
- * @reserved: 32 bit for alignment
- *
- * The VNIC will send trap messages to the Ethernet manager to
- * inform it about changes to the VNIC config, behaviour etc.
- * This is the format of the trap payload.
- */
-struct opa_veswport_trap {
- __be16 fabric_id;
- __be16 veswid;
- __be32 veswportnum;
- __be16 opaportnum;
- u8 veswportindex;
- u8 opcode;
- __be32 reserved;
-} __packed;
-
-/**
- * struct opa_vnic_iface_mac_entry - single entry in the mac list
- * @mac_addr: MAC address
- */
-struct opa_vnic_iface_mac_entry {
- u8 mac_addr[ETH_ALEN];
-};
-
-/**
- * struct opa_veswport_iface_macs - Msg to set globally administered MAC
- * @start_idx: position of first entry (0 based)
- * @num_macs_in_msg: number of MACs in this message
- * @tot_macs_in_lst: The total number of MACs the agent has
- * @gen_count: gen_count to indicate change
- * @entry: The mac list entry
- *
- * Same attribute IDS and attribute modifiers as in locally administered
- * addresses used to set globally administered addresses
- */
-struct opa_veswport_iface_macs {
- __be16 start_idx;
- __be16 num_macs_in_msg;
- __be16 tot_macs_in_lst;
- __be16 gen_count;
- struct opa_vnic_iface_mac_entry entry[];
-} __packed;
-
-/**
- * struct opa_vnic_vema_mad - Generic VEMA MAD
- * @mad_hdr: Generic MAD header
- * @rmpp_hdr: RMPP header for vendor specific MADs
- * @reserved: reserved bytes
- * @oui: Unique org identifier
- * @data: MAD data
- */
-struct opa_vnic_vema_mad {
- struct ib_mad_hdr mad_hdr;
- struct ib_rmpp_hdr rmpp_hdr;
- u8 reserved;
- u8 oui[3];
- u8 data[OPA_VNIC_EMA_DATA];
-};
-
-/**
- * struct opa_vnic_notice_attr - Generic Notice MAD
- * @gen_type: Generic/Specific bit and type of notice
- * @oui_1: Vendor ID byte 1
- * @oui_2: Vendor ID byte 2
- * @oui_3: Vendor ID byte 3
- * @trap_num: Trap number
- * @toggle_count: Notice toggle bit and count value
- * @issuer_lid: Trap issuer's lid
- * @reserved: reserved bytes
- * @issuer_gid: Issuer GID (only if Report method)
- * @raw_data: Trap message body
- */
-struct opa_vnic_notice_attr {
- u8 gen_type;
- u8 oui_1;
- u8 oui_2;
- u8 oui_3;
- __be16 trap_num;
- __be16 toggle_count;
- __be32 issuer_lid;
- __be32 reserved;
- u8 issuer_gid[16];
- u8 raw_data[64];
-} __packed;
-
-/**
- * struct opa_vnic_vema_mad_trap - Generic VEMA MAD Trap
- * @mad_hdr: Generic MAD header
- * @rmpp_hdr: RMPP header for vendor specific MADs
- * @reserved: reserved bytes
- * @oui: Unique org identifier
- * @notice: Notice structure
- */
-struct opa_vnic_vema_mad_trap {
- struct ib_mad_hdr mad_hdr;
- struct ib_rmpp_hdr rmpp_hdr;
- u8 reserved;
- u8 oui[3];
- struct opa_vnic_notice_attr notice;
-};
-
-#endif /* _OPA_VNIC_ENCAP_H */
diff --git a/drivers/infiniband/ulp/opa_vnic/opa_vnic_ethtool.c b/drivers/infiniband/ulp/opa_vnic/opa_vnic_ethtool.c
deleted file mode 100644
index 316959940d2f..000000000000
--- a/drivers/infiniband/ulp/opa_vnic/opa_vnic_ethtool.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright(c) 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
- * This file contains OPA VNIC ethtool functions
- */
-
-#include <linux/ethtool.h>
-
-#include "opa_vnic_internal.h"
-
-enum {NETDEV_STATS, VNIC_STATS};
-
-struct vnic_stats {
- char stat_string[ETH_GSTRING_LEN];
- struct {
- int sizeof_stat;
- int stat_offset;
- };
-};
-
-#define VNIC_STAT(m) { sizeof_field(struct opa_vnic_stats, m), \
- offsetof(struct opa_vnic_stats, m) }
-
-static struct vnic_stats vnic_gstrings_stats[] = {
- /* NETDEV stats */
- {"rx_packets", VNIC_STAT(netstats.rx_packets)},
- {"tx_packets", VNIC_STAT(netstats.tx_packets)},
- {"rx_bytes", VNIC_STAT(netstats.rx_bytes)},
- {"tx_bytes", VNIC_STAT(netstats.tx_bytes)},
- {"rx_errors", VNIC_STAT(netstats.rx_errors)},
- {"tx_errors", VNIC_STAT(netstats.tx_errors)},
- {"rx_dropped", VNIC_STAT(netstats.rx_dropped)},
- {"tx_dropped", VNIC_STAT(netstats.tx_dropped)},
-
- /* SUMMARY counters */
- {"tx_unicast", VNIC_STAT(tx_grp.unicast)},
- {"tx_mcastbcast", VNIC_STAT(tx_grp.mcastbcast)},
- {"tx_untagged", VNIC_STAT(tx_grp.untagged)},
- {"tx_vlan", VNIC_STAT(tx_grp.vlan)},
-
- {"tx_64_size", VNIC_STAT(tx_grp.s_64)},
- {"tx_65_127", VNIC_STAT(tx_grp.s_65_127)},
- {"tx_128_255", VNIC_STAT(tx_grp.s_128_255)},
- {"tx_256_511", VNIC_STAT(tx_grp.s_256_511)},
- {"tx_512_1023", VNIC_STAT(tx_grp.s_512_1023)},
- {"tx_1024_1518", VNIC_STAT(tx_grp.s_1024_1518)},
- {"tx_1519_max", VNIC_STAT(tx_grp.s_1519_max)},
-
- {"rx_unicast", VNIC_STAT(rx_grp.unicast)},
- {"rx_mcastbcast", VNIC_STAT(rx_grp.mcastbcast)},
- {"rx_untagged", VNIC_STAT(rx_grp.untagged)},
- {"rx_vlan", VNIC_STAT(rx_grp.vlan)},
-
- {"rx_64_size", VNIC_STAT(rx_grp.s_64)},
- {"rx_65_127", VNIC_STAT(rx_grp.s_65_127)},
- {"rx_128_255", VNIC_STAT(rx_grp.s_128_255)},
- {"rx_256_511", VNIC_STAT(rx_grp.s_256_511)},
- {"rx_512_1023", VNIC_STAT(rx_grp.s_512_1023)},
- {"rx_1024_1518", VNIC_STAT(rx_grp.s_1024_1518)},
- {"rx_1519_max", VNIC_STAT(rx_grp.s_1519_max)},
-
- /* ERROR counters */
- {"rx_fifo_errors", VNIC_STAT(netstats.rx_fifo_errors)},
- {"rx_length_errors", VNIC_STAT(netstats.rx_length_errors)},
-
- {"tx_fifo_errors", VNIC_STAT(netstats.tx_fifo_errors)},
- {"tx_carrier_errors", VNIC_STAT(netstats.tx_carrier_errors)},
-
- {"tx_dlid_zero", VNIC_STAT(tx_dlid_zero)},
- {"tx_drop_state", VNIC_STAT(tx_drop_state)},
- {"rx_drop_state", VNIC_STAT(rx_drop_state)},
- {"rx_oversize", VNIC_STAT(rx_oversize)},
- {"rx_runt", VNIC_STAT(rx_runt)},
-};
-
-#define VNIC_STATS_LEN ARRAY_SIZE(vnic_gstrings_stats)
-
-/* vnic_get_drvinfo - get driver info */
-static void vnic_get_drvinfo(struct net_device *netdev,
- struct ethtool_drvinfo *drvinfo)
-{
- strscpy(drvinfo->driver, opa_vnic_driver_name, sizeof(drvinfo->driver));
- strscpy(drvinfo->bus_info, dev_name(netdev->dev.parent),
- sizeof(drvinfo->bus_info));
-}
-
-/* vnic_get_sset_count - get string set count */
-static int vnic_get_sset_count(struct net_device *netdev, int sset)
-{
- return (sset == ETH_SS_STATS) ? VNIC_STATS_LEN : -EOPNOTSUPP;
-}
-
-/* vnic_get_ethtool_stats - get statistics */
-static void vnic_get_ethtool_stats(struct net_device *netdev,
- struct ethtool_stats *stats, u64 *data)
-{
- struct opa_vnic_adapter *adapter = opa_vnic_priv(netdev);
- struct opa_vnic_stats vstats;
- int i;
-
- memset(&vstats, 0, sizeof(vstats));
- spin_lock(&adapter->stats_lock);
- adapter->rn_ops->ndo_get_stats64(netdev, &vstats.netstats);
- spin_unlock(&adapter->stats_lock);
- for (i = 0; i < VNIC_STATS_LEN; i++) {
- char *p = (char *)&vstats + vnic_gstrings_stats[i].stat_offset;
-
- data[i] = (vnic_gstrings_stats[i].sizeof_stat ==
- sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
- }
-}
-
-/* vnic_get_strings - get strings */
-static void vnic_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
-{
- int i;
-
- if (stringset != ETH_SS_STATS)
- return;
-
- for (i = 0; i < VNIC_STATS_LEN; i++)
- ethtool_puts(&data, vnic_gstrings_stats[i].stat_string);
-}
-
-/* ethtool ops */
-static const struct ethtool_ops opa_vnic_ethtool_ops = {
- .get_drvinfo = vnic_get_drvinfo,
- .get_link = ethtool_op_get_link,
- .get_strings = vnic_get_strings,
- .get_sset_count = vnic_get_sset_count,
- .get_ethtool_stats = vnic_get_ethtool_stats,
-};
-
-/* opa_vnic_set_ethtool_ops - set ethtool ops */
-void opa_vnic_set_ethtool_ops(struct net_device *netdev)
-{
- netdev->ethtool_ops = &opa_vnic_ethtool_ops;
-}
diff --git a/drivers/infiniband/ulp/opa_vnic/opa_vnic_internal.h b/drivers/infiniband/ulp/opa_vnic/opa_vnic_internal.h
deleted file mode 100644
index dd942dd642bd..000000000000
--- a/drivers/infiniband/ulp/opa_vnic/opa_vnic_internal.h
+++ /dev/null
@@ -1,329 +0,0 @@
-#ifndef _OPA_VNIC_INTERNAL_H
-#define _OPA_VNIC_INTERNAL_H
-/*
- * Copyright(c) 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
- * This file contains OPA VNIC driver internal declarations
- */
-
-#include <linux/bitops.h>
-#include <linux/etherdevice.h>
-#include <linux/hashtable.h>
-#include <linux/sizes.h>
-#include <rdma/opa_vnic.h>
-
-#include "opa_vnic_encap.h"
-
-#define OPA_VNIC_VLAN_PCP(vlan_tci) \
- (((vlan_tci) & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT)
-
-/* Flow to default port redirection table size */
-#define OPA_VNIC_FLOW_TBL_SIZE 32
-
-/* Invalid port number */
-#define OPA_VNIC_INVALID_PORT 0xff
-
-struct opa_vnic_adapter;
-
-/*
- * struct __opa_vesw_info - OPA vnic virtual switch info
- *
- * Same as opa_vesw_info without bitwise attribute.
- */
-struct __opa_vesw_info {
- u16 fabric_id;
- u16 vesw_id;
-
- u8 rsvd0[6];
- u16 def_port_mask;
-
- u8 rsvd1[2];
- u16 pkey;
-
- u8 rsvd2[4];
- u32 u_mcast_dlid;
- u32 u_ucast_dlid[OPA_VESW_MAX_NUM_DEF_PORT];
-
- u32 rc;
-
- u8 rsvd3[56];
- u16 eth_mtu;
- u8 rsvd4[2];
-} __packed;
-
-/*
- * struct __opa_per_veswport_info - OPA vnic per port info
- *
- * Same as opa_per_veswport_info without bitwise attribute.
- */
-struct __opa_per_veswport_info {
- u32 port_num;
-
- u8 eth_link_status;
- u8 rsvd0[3];
-
- u8 base_mac_addr[ETH_ALEN];
- u8 config_state;
- u8 oper_state;
-
- u16 max_mac_tbl_ent;
- u16 max_smac_ent;
- u32 mac_tbl_digest;
- u8 rsvd1[4];
-
- u32 encap_slid;
-
- u8 pcp_to_sc_uc[OPA_VNIC_MAX_NUM_PCP];
- u8 pcp_to_vl_uc[OPA_VNIC_MAX_NUM_PCP];
- u8 pcp_to_sc_mc[OPA_VNIC_MAX_NUM_PCP];
- u8 pcp_to_vl_mc[OPA_VNIC_MAX_NUM_PCP];
-
- u8 non_vlan_sc_uc;
- u8 non_vlan_vl_uc;
- u8 non_vlan_sc_mc;
- u8 non_vlan_vl_mc;
-
- u8 rsvd2[48];
-
- u16 uc_macs_gen_count;
- u16 mc_macs_gen_count;
-
- u8 rsvd3[8];
-} __packed;
-
-/*
- * struct __opa_veswport_info - OPA vnic port info
- *
- * Same as opa_veswport_info without bitwise attribute.
- */
-struct __opa_veswport_info {
- struct __opa_vesw_info vesw;
- struct __opa_per_veswport_info vport;
-};
-
-/*
- * struct __opa_veswport_trap - OPA vnic trap info
- *
- * Same as opa_veswport_trap without bitwise attribute.
- */
-struct __opa_veswport_trap {
- u16 fabric_id;
- u16 veswid;
- u32 veswportnum;
- u16 opaportnum;
- u8 veswportindex;
- u8 opcode;
- u32 reserved;
-} __packed;
-
-/**
- * struct opa_vnic_ctrl_port - OPA virtual NIC control port
- * @ibdev: pointer to ib device
- * @ops: opa vnic control operations
- * @num_ports: number of opa ports
- */
-struct opa_vnic_ctrl_port {
- struct ib_device *ibdev;
- struct opa_vnic_ctrl_ops *ops;
- u8 num_ports;
-};
-
-/**
- * struct opa_vnic_adapter - OPA VNIC netdev private data structure
- * @netdev: pointer to associated netdev
- * @ibdev: ib device
- * @cport: pointer to opa vnic control port
- * @rn_ops: rdma netdev's net_device_ops
- * @port_num: OPA port number
- * @vport_num: vesw port number
- * @lock: adapter lock
- * @info: virtual ethernet switch port information
- * @vema_mac_addr: mac address configured by vema
- * @umac_hash: unicast maclist hash
- * @mmac_hash: multicast maclist hash
- * @mactbl: hash table of MAC entries
- * @mactbl_lock: mac table lock
- * @stats_lock: statistics lock
- * @flow_tbl: flow to default port redirection table
- * @trap_timeout: trap timeout
- * @trap_count: no. of traps allowed within timeout period
- */
-struct opa_vnic_adapter {
- struct net_device *netdev;
- struct ib_device *ibdev;
- struct opa_vnic_ctrl_port *cport;
- const struct net_device_ops *rn_ops;
-
- u8 port_num;
- u8 vport_num;
-
- /* Lock used around concurrent updates to netdev */
- struct mutex lock;
-
- struct __opa_veswport_info info;
- u8 vema_mac_addr[ETH_ALEN];
- u32 umac_hash;
- u32 mmac_hash;
- struct hlist_head __rcu *mactbl;
-
- /* Lock used to protect updates to mac table */
- struct mutex mactbl_lock;
-
- /* Lock used to protect access to vnic counters */
- spinlock_t stats_lock;
-
- u8 flow_tbl[OPA_VNIC_FLOW_TBL_SIZE];
-
- unsigned long trap_timeout;
- u8 trap_count;
-};
-
-/* Same as opa_veswport_mactable_entry, but without bitwise attribute */
-struct __opa_vnic_mactable_entry {
- u8 mac_addr[ETH_ALEN];
- u8 mac_addr_mask[ETH_ALEN];
- u32 dlid_sd;
-} __packed;
-
-/**
- * struct opa_vnic_mac_tbl_node - OPA VNIC mac table node
- * @hlist: hash list handle
- * @index: index of entry in the mac table
- * @entry: entry in the table
- */
-struct opa_vnic_mac_tbl_node {
- struct hlist_node hlist;
- u16 index;
- struct __opa_vnic_mactable_entry entry;
-};
-
-#define v_dbg(format, arg...) \
- netdev_dbg(adapter->netdev, format, ## arg)
-#define v_err(format, arg...) \
- netdev_err(adapter->netdev, format, ## arg)
-#define v_info(format, arg...) \
- netdev_info(adapter->netdev, format, ## arg)
-#define v_warn(format, arg...) \
- netdev_warn(adapter->netdev, format, ## arg)
-
-#define c_err(format, arg...) \
- dev_err(&cport->ibdev->dev, format, ## arg)
-#define c_info(format, arg...) \
- dev_info(&cport->ibdev->dev, format, ## arg)
-#define c_dbg(format, arg...) \
- dev_dbg(&cport->ibdev->dev, format, ## arg)
-
-/* The maximum allowed entries in the mac table */
-#define OPA_VNIC_MAC_TBL_MAX_ENTRIES 2048
-/* Limit of smac entries in mac table */
-#define OPA_VNIC_MAX_SMAC_LIMIT 256
-
-/* The last octet of the MAC address is used as the key to the hash table */
-#define OPA_VNIC_MAC_HASH_IDX 5
-
-/* The VNIC MAC hash table is of size 2^8 */
-#define OPA_VNIC_MAC_TBL_HASH_BITS 8
-#define OPA_VNIC_MAC_TBL_SIZE BIT(OPA_VNIC_MAC_TBL_HASH_BITS)
-
-/* VNIC HASH MACROS */
-#define vnic_hash_init(hashtable) __hash_init(hashtable, OPA_VNIC_MAC_TBL_SIZE)
-
-#define vnic_hash_add(hashtable, node, key) \
- hlist_add_head(node, \
- &hashtable[hash_min(key, ilog2(OPA_VNIC_MAC_TBL_SIZE))])
-
-#define vnic_hash_for_each_safe(name, bkt, tmp, obj, member) \
- for ((bkt) = 0, obj = NULL; \
- !obj && (bkt) < OPA_VNIC_MAC_TBL_SIZE; (bkt)++) \
- hlist_for_each_entry_safe(obj, tmp, &name[bkt], member)
-
-#define vnic_hash_for_each_possible(name, obj, member, key) \
- hlist_for_each_entry(obj, \
- &name[hash_min(key, ilog2(OPA_VNIC_MAC_TBL_SIZE))], member)
-
-#define vnic_hash_for_each(name, bkt, obj, member) \
- for ((bkt) = 0, obj = NULL; \
- !obj && (bkt) < OPA_VNIC_MAC_TBL_SIZE; (bkt)++) \
- hlist_for_each_entry(obj, &name[bkt], member)
-
-extern char opa_vnic_driver_name[];
-
-struct opa_vnic_adapter *opa_vnic_add_netdev(struct ib_device *ibdev,
- u8 port_num, u8 vport_num);
-void opa_vnic_rem_netdev(struct opa_vnic_adapter *adapter);
-void opa_vnic_encap_skb(struct opa_vnic_adapter *adapter, struct sk_buff *skb);
-u8 opa_vnic_get_vl(struct opa_vnic_adapter *adapter, struct sk_buff *skb);
-u8 opa_vnic_calc_entropy(struct sk_buff *skb);
-void opa_vnic_process_vema_config(struct opa_vnic_adapter *adapter);
-void opa_vnic_release_mac_tbl(struct opa_vnic_adapter *adapter);
-void opa_vnic_query_mac_tbl(struct opa_vnic_adapter *adapter,
- struct opa_veswport_mactable *tbl);
-int opa_vnic_update_mac_tbl(struct opa_vnic_adapter *adapter,
- struct opa_veswport_mactable *tbl);
-void opa_vnic_query_ucast_macs(struct opa_vnic_adapter *adapter,
- struct opa_veswport_iface_macs *macs);
-void opa_vnic_query_mcast_macs(struct opa_vnic_adapter *adapter,
- struct opa_veswport_iface_macs *macs);
-void opa_vnic_get_summary_counters(struct opa_vnic_adapter *adapter,
- struct opa_veswport_summary_counters *cntrs);
-void opa_vnic_get_error_counters(struct opa_vnic_adapter *adapter,
- struct opa_veswport_error_counters *cntrs);
-void opa_vnic_get_vesw_info(struct opa_vnic_adapter *adapter,
- struct opa_vesw_info *info);
-void opa_vnic_set_vesw_info(struct opa_vnic_adapter *adapter,
- struct opa_vesw_info *info);
-void opa_vnic_get_per_veswport_info(struct opa_vnic_adapter *adapter,
- struct opa_per_veswport_info *info);
-void opa_vnic_set_per_veswport_info(struct opa_vnic_adapter *adapter,
- struct opa_per_veswport_info *info);
-void opa_vnic_vema_report_event(struct opa_vnic_adapter *adapter, u8 event);
-void opa_vnic_set_ethtool_ops(struct net_device *netdev);
-void opa_vnic_vema_send_trap(struct opa_vnic_adapter *adapter,
- struct __opa_veswport_trap *data, u32 lid);
-
-#endif /* _OPA_VNIC_INTERNAL_H */
diff --git a/drivers/infiniband/ulp/opa_vnic/opa_vnic_netdev.c b/drivers/infiniband/ulp/opa_vnic/opa_vnic_netdev.c
deleted file mode 100644
index 1c3e7251f0f4..000000000000
--- a/drivers/infiniband/ulp/opa_vnic/opa_vnic_netdev.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * Copyright(c) 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
- * This file contains OPA Virtual Network Interface Controller (VNIC) driver
- * netdev functionality.
- */
-
-#include <linux/if_vlan.h>
-#include <linux/crc32.h>
-
-#include "opa_vnic_internal.h"
-
-#define OPA_TX_TIMEOUT_MS 1000
-
-#define OPA_VNIC_SKB_HEADROOM \
- ALIGN((OPA_VNIC_HDR_LEN + OPA_VNIC_SKB_MDATA_LEN), 8)
-
-/* This function is overloaded for opa_vnic specific implementation */
-static void opa_vnic_get_stats64(struct net_device *netdev,
- struct rtnl_link_stats64 *stats)
-{
- struct opa_vnic_adapter *adapter = opa_vnic_priv(netdev);
- struct opa_vnic_stats vstats;
-
- memset(&vstats, 0, sizeof(vstats));
- spin_lock(&adapter->stats_lock);
- adapter->rn_ops->ndo_get_stats64(netdev, &vstats.netstats);
- spin_unlock(&adapter->stats_lock);
- memcpy(stats, &vstats.netstats, sizeof(*stats));
-}
-
-/* opa_netdev_start_xmit - transmit function */
-static netdev_tx_t opa_netdev_start_xmit(struct sk_buff *skb,
- struct net_device *netdev)
-{
- struct opa_vnic_adapter *adapter = opa_vnic_priv(netdev);
-
- v_dbg("xmit: queue %d skb len %d\n", skb->queue_mapping, skb->len);
- /* pad to ensure mininum ethernet packet length */
- if (unlikely(skb->len < ETH_ZLEN)) {
- if (skb_padto(skb, ETH_ZLEN))
- return NETDEV_TX_OK;
-
- skb_put(skb, ETH_ZLEN - skb->len);
- }
-
- opa_vnic_encap_skb(adapter, skb);
- return adapter->rn_ops->ndo_start_xmit(skb, netdev);
-}
-
-static u16 opa_vnic_select_queue(struct net_device *netdev, struct sk_buff *skb,
- struct net_device *sb_dev)
-{
- struct opa_vnic_adapter *adapter = opa_vnic_priv(netdev);
- struct opa_vnic_skb_mdata *mdata;
- int rc;
-
- /* pass entropy and vl as metadata in skb */
- mdata = skb_push(skb, sizeof(*mdata));
- mdata->entropy = opa_vnic_calc_entropy(skb);
- mdata->vl = opa_vnic_get_vl(adapter, skb);
- rc = adapter->rn_ops->ndo_select_queue(netdev, skb, sb_dev);
- skb_pull(skb, sizeof(*mdata));
- return rc;
-}
-
-static void opa_vnic_update_state(struct opa_vnic_adapter *adapter, bool up)
-{
- struct __opa_veswport_info *info = &adapter->info;
-
- mutex_lock(&adapter->lock);
- /* Operational state can only be DROP_ALL or FORWARDING */
- if ((info->vport.config_state == OPA_VNIC_STATE_FORWARDING) && up) {
- info->vport.oper_state = OPA_VNIC_STATE_FORWARDING;
- info->vport.eth_link_status = OPA_VNIC_ETH_LINK_UP;
- } else {
- info->vport.oper_state = OPA_VNIC_STATE_DROP_ALL;
- info->vport.eth_link_status = OPA_VNIC_ETH_LINK_DOWN;
- }
-
- if (info->vport.config_state == OPA_VNIC_STATE_FORWARDING)
- netif_dormant_off(adapter->netdev);
- else
- netif_dormant_on(adapter->netdev);
- mutex_unlock(&adapter->lock);
-}
-
-/* opa_vnic_process_vema_config - process vema configuration updates */
-void opa_vnic_process_vema_config(struct opa_vnic_adapter *adapter)
-{
- struct __opa_veswport_info *info = &adapter->info;
- struct rdma_netdev *rn = netdev_priv(adapter->netdev);
- u8 port_num[OPA_VESW_MAX_NUM_DEF_PORT] = { 0 };
- struct net_device *netdev = adapter->netdev;
- u8 i, port_count = 0;
- u16 port_mask;
-
- /* If the base_mac_addr is changed, update the interface mac address */
- if (memcmp(info->vport.base_mac_addr, adapter->vema_mac_addr,
- ARRAY_SIZE(info->vport.base_mac_addr))) {
- struct sockaddr saddr;
-
- memcpy(saddr.sa_data, info->vport.base_mac_addr,
- ARRAY_SIZE(info->vport.base_mac_addr));
- mutex_lock(&adapter->lock);
- eth_commit_mac_addr_change(netdev, &saddr);
- memcpy(adapter->vema_mac_addr,
- info->vport.base_mac_addr, ETH_ALEN);
- mutex_unlock(&adapter->lock);
- }
-
- rn->set_id(netdev, info->vesw.vesw_id);
-
- /* Handle MTU limit change */
- rtnl_lock();
- netdev->max_mtu = max_t(unsigned int, info->vesw.eth_mtu,
- netdev->min_mtu);
- if (netdev->mtu > netdev->max_mtu)
- dev_set_mtu(netdev, netdev->max_mtu);
- rtnl_unlock();
-
- /* Update flow to default port redirection table */
- port_mask = info->vesw.def_port_mask;
- for (i = 0; i < OPA_VESW_MAX_NUM_DEF_PORT; i++) {
- if (port_mask & 1)
- port_num[port_count++] = i;
- port_mask >>= 1;
- }
-
- /*
- * Build the flow table. Flow table is required when destination LID
- * is not available. Up to OPA_VNIC_FLOW_TBL_SIZE flows supported.
- * Each flow need a default port number to get its dlid from the
- * u_ucast_dlid array.
- */
- for (i = 0; i < OPA_VNIC_FLOW_TBL_SIZE; i++)
- adapter->flow_tbl[i] = port_count ? port_num[i % port_count] :
- OPA_VNIC_INVALID_PORT;
-
- /* update state */
- opa_vnic_update_state(adapter, !!(netdev->flags & IFF_UP));
-}
-
-/*
- * Set the power on default values in adapter's vema interface structure.
- */
-static inline void opa_vnic_set_pod_values(struct opa_vnic_adapter *adapter)
-{
- adapter->info.vport.max_mac_tbl_ent = OPA_VNIC_MAC_TBL_MAX_ENTRIES;
- adapter->info.vport.max_smac_ent = OPA_VNIC_MAX_SMAC_LIMIT;
- adapter->info.vport.config_state = OPA_VNIC_STATE_DROP_ALL;
- adapter->info.vport.eth_link_status = OPA_VNIC_ETH_LINK_DOWN;
- adapter->info.vesw.eth_mtu = ETH_DATA_LEN;
-}
-
-/* opa_vnic_set_mac_addr - change mac address */
-static int opa_vnic_set_mac_addr(struct net_device *netdev, void *addr)
-{
- struct opa_vnic_adapter *adapter = opa_vnic_priv(netdev);
- struct sockaddr *sa = addr;
- int rc;
-
- if (!memcmp(netdev->dev_addr, sa->sa_data, ETH_ALEN))
- return 0;
-
- mutex_lock(&adapter->lock);
- rc = eth_mac_addr(netdev, addr);
- mutex_unlock(&adapter->lock);
- if (rc)
- return rc;
-
- adapter->info.vport.uc_macs_gen_count++;
- opa_vnic_vema_report_event(adapter,
- OPA_VESWPORT_TRAP_IFACE_UCAST_MAC_CHANGE);
- return 0;
-}
-
-/*
- * opa_vnic_mac_send_event - post event on possible mac list exchange
- * Send trap when digest from uc/mc mac list differs from previous run.
- * Digest is evaluated similar to how cksum does.
- */
-static void opa_vnic_mac_send_event(struct net_device *netdev, u8 event)
-{
- struct opa_vnic_adapter *adapter = opa_vnic_priv(netdev);
- struct netdev_hw_addr *ha;
- struct netdev_hw_addr_list *hw_list;
- u32 *ref_crc;
- u32 l, crc = 0;
-
- switch (event) {
- case OPA_VESWPORT_TRAP_IFACE_UCAST_MAC_CHANGE:
- hw_list = &netdev->uc;
- adapter->info.vport.uc_macs_gen_count++;
- ref_crc = &adapter->umac_hash;
- break;
- case OPA_VESWPORT_TRAP_IFACE_MCAST_MAC_CHANGE:
- hw_list = &netdev->mc;
- adapter->info.vport.mc_macs_gen_count++;
- ref_crc = &adapter->mmac_hash;
- break;
- default:
- return;
- }
- netdev_hw_addr_list_for_each(ha, hw_list) {
- crc = crc32_le(crc, ha->addr, ETH_ALEN);
- }
- l = netdev_hw_addr_list_count(hw_list) * ETH_ALEN;
- crc = ~crc32_le(crc, (void *)&l, sizeof(l));
-
- if (crc != *ref_crc) {
- *ref_crc = crc;
- opa_vnic_vema_report_event(adapter, event);
- }
-}
-
-/* opa_vnic_set_rx_mode - handle uc/mc mac list change */
-static void opa_vnic_set_rx_mode(struct net_device *netdev)
-{
- opa_vnic_mac_send_event(netdev,
- OPA_VESWPORT_TRAP_IFACE_UCAST_MAC_CHANGE);
-
- opa_vnic_mac_send_event(netdev,
- OPA_VESWPORT_TRAP_IFACE_MCAST_MAC_CHANGE);
-}
-
-/* opa_netdev_open - activate network interface */
-static int opa_netdev_open(struct net_device *netdev)
-{
- struct opa_vnic_adapter *adapter = opa_vnic_priv(netdev);
- int rc;
-
- rc = adapter->rn_ops->ndo_open(adapter->netdev);
- if (rc) {
- v_dbg("open failed %d\n", rc);
- return rc;
- }
-
- /* Update status and send trap */
- opa_vnic_update_state(adapter, true);
- opa_vnic_vema_report_event(adapter,
- OPA_VESWPORT_TRAP_ETH_LINK_STATUS_CHANGE);
- return 0;
-}
-
-/* opa_netdev_close - disable network interface */
-static int opa_netdev_close(struct net_device *netdev)
-{
- struct opa_vnic_adapter *adapter = opa_vnic_priv(netdev);
- int rc;
-
- rc = adapter->rn_ops->ndo_stop(adapter->netdev);
- if (rc) {
- v_dbg("close failed %d\n", rc);
- return rc;
- }
-
- /* Update status and send trap */
- opa_vnic_update_state(adapter, false);
- opa_vnic_vema_report_event(adapter,
- OPA_VESWPORT_TRAP_ETH_LINK_STATUS_CHANGE);
- return 0;
-}
-
-/* netdev ops */
-static const struct net_device_ops opa_netdev_ops = {
- .ndo_open = opa_netdev_open,
- .ndo_stop = opa_netdev_close,
- .ndo_start_xmit = opa_netdev_start_xmit,
- .ndo_get_stats64 = opa_vnic_get_stats64,
- .ndo_set_rx_mode = opa_vnic_set_rx_mode,
- .ndo_select_queue = opa_vnic_select_queue,
- .ndo_set_mac_address = opa_vnic_set_mac_addr,
-};
-
-/* opa_vnic_add_netdev - create vnic netdev interface */
-struct opa_vnic_adapter *opa_vnic_add_netdev(struct ib_device *ibdev,
- u8 port_num, u8 vport_num)
-{
- struct opa_vnic_adapter *adapter;
- struct net_device *netdev;
- struct rdma_netdev *rn;
- int rc;
-
- netdev = ibdev->ops.alloc_rdma_netdev(ibdev, port_num,
- RDMA_NETDEV_OPA_VNIC,
- "veth%d", NET_NAME_UNKNOWN,
- ether_setup);
- if (!netdev)
- return ERR_PTR(-ENOMEM);
- else if (IS_ERR(netdev))
- return ERR_CAST(netdev);
-
- rn = netdev_priv(netdev);
- adapter = kzalloc_obj(*adapter);
- if (!adapter) {
- rc = -ENOMEM;
- goto adapter_err;
- }
-
- rn->clnt_priv = adapter;
- rn->hca = ibdev;
- rn->port_num = port_num;
- adapter->netdev = netdev;
- adapter->ibdev = ibdev;
- adapter->port_num = port_num;
- adapter->vport_num = vport_num;
- adapter->rn_ops = netdev->netdev_ops;
-
- netdev->netdev_ops = &opa_netdev_ops;
- netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
- netdev->hard_header_len += OPA_VNIC_SKB_HEADROOM;
- mutex_init(&adapter->lock);
- mutex_init(&adapter->mactbl_lock);
- spin_lock_init(&adapter->stats_lock);
-
- SET_NETDEV_DEV(netdev, ibdev->dev.parent);
-
- opa_vnic_set_ethtool_ops(netdev);
-
- opa_vnic_set_pod_values(adapter);
-
- rc = register_netdev(netdev);
- if (rc)
- goto netdev_err;
-
- netif_carrier_off(netdev);
- netif_dormant_on(netdev);
- v_info("initialized\n");
-
- return adapter;
-netdev_err:
- mutex_destroy(&adapter->lock);
- mutex_destroy(&adapter->mactbl_lock);
- kfree(adapter);
-adapter_err:
- rn->free_rdma_netdev(netdev);
-
- return ERR_PTR(rc);
-}
-
-/* opa_vnic_rem_netdev - remove vnic netdev interface */
-void opa_vnic_rem_netdev(struct opa_vnic_adapter *adapter)
-{
- struct net_device *netdev = adapter->netdev;
- struct rdma_netdev *rn = netdev_priv(netdev);
-
- v_info("removing\n");
- unregister_netdev(netdev);
- opa_vnic_release_mac_tbl(adapter);
- mutex_destroy(&adapter->lock);
- mutex_destroy(&adapter->mactbl_lock);
- kfree(adapter);
- rn->free_rdma_netdev(netdev);
-}
diff --git a/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c b/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c
deleted file mode 100644
index 21c6cea8b1db..000000000000
--- a/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c
+++ /dev/null
@@ -1,1056 +0,0 @@
-/*
- * 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.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
- * 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_verbs.h>
-#include <rdma/opa_smi.h>
-#include <rdma/opa_port_info.h>
-
-#include "opa_vnic_internal.h"
-
-char opa_vnic_driver_name[] = "opa_vnic";
-
-/*
- * The trap service level is kept in bits 3 to 7 in the trap_sl_rsvd
- * field in the class port info MAD.
- */
-#define GET_TRAP_SL_FROM_CLASS_PORT_INFO(x) (((x) >> 3) & 0x1f)
-
-/* Cap trap bursts to a reasonable limit good for normal cases */
-#define OPA_VNIC_TRAP_BURST_LIMIT 4
-
-/*
- * VNIC trap limit timeout.
- * Inverse of cap2_mask response time out (1.0737 secs) = 0.9
- * secs approx IB spec 13.4.6.2.1 PortInfoSubnetTimeout and
- * 13.4.9 Traps.
- */
-#define OPA_VNIC_TRAP_TIMEOUT ((4096 * (1UL << 18)) / 1000)
-
-#define OPA_VNIC_UNSUP_ATTR \
- cpu_to_be16(IB_MGMT_MAD_STATUS_UNSUPPORTED_METHOD_ATTRIB)
-
-#define OPA_VNIC_INVAL_ATTR \
- cpu_to_be16(IB_MGMT_MAD_STATUS_INVALID_ATTRIB_VALUE)
-
-#define OPA_VNIC_CLASS_CAP_TRAP 0x1
-
-/* Maximum number of VNIC ports supported */
-#define OPA_VNIC_MAX_NUM_VPORT 255
-
-/**
- * struct opa_vnic_vema_port -- VNIC VEMA port details
- * @cport: pointer to port
- * @mad_agent: pointer to mad agent for port
- * @class_port_info: Class port info information.
- * @tid: Transaction id
- * @port_num: OPA port number
- * @vports: vnic ports
- * @event_handler: ib event handler
- * @lock: adapter interface lock
- */
-struct opa_vnic_vema_port {
- struct opa_vnic_ctrl_port *cport;
- struct ib_mad_agent *mad_agent;
- struct opa_class_port_info class_port_info;
- u64 tid;
- u8 port_num;
- struct xarray vports;
- struct ib_event_handler event_handler;
-
- /* Lock to query/update network adapter */
- struct mutex lock;
-};
-
-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);
-
-static struct ib_client opa_vnic_client = {
- .name = opa_vnic_driver_name,
- .add = opa_vnic_vema_add_one,
- .remove = opa_vnic_vema_rem_one,
-};
-
-/**
- * vema_get_vport_num -- Get the vnic from the mad
- * @recvd_mad: Received mad
- *
- * Return: returns value of the vnic port number
- */
-static inline u8 vema_get_vport_num(struct opa_vnic_vema_mad *recvd_mad)
-{
- return be32_to_cpu(recvd_mad->mad_hdr.attr_mod) & 0xff;
-}
-
-/**
- * vema_get_vport_adapter -- Get vnic port adapter from recvd mad
- * @recvd_mad: received mad
- * @port: ptr to port struct on which MAD was recvd
- *
- * Return: vnic adapter
- */
-static inline struct opa_vnic_adapter *
-vema_get_vport_adapter(struct opa_vnic_vema_mad *recvd_mad,
- struct opa_vnic_vema_port *port)
-{
- u8 vport_num = vema_get_vport_num(recvd_mad);
-
- return xa_load(&port->vports, vport_num);
-}
-
-/**
- * vema_mac_tbl_req_ok -- Check if mac request has correct values
- * @mac_tbl: mac table
- *
- * This function checks for the validity of the offset and number of
- * entries required.
- *
- * Return: true if offset and num_entries are valid
- */
-static inline bool vema_mac_tbl_req_ok(struct opa_veswport_mactable *mac_tbl)
-{
- u16 offset, num_entries;
- u16 req_entries = ((OPA_VNIC_EMA_DATA - sizeof(*mac_tbl)) /
- sizeof(mac_tbl->tbl_entries[0]));
-
- offset = be16_to_cpu(mac_tbl->offset);
- num_entries = be16_to_cpu(mac_tbl->num_entries);
-
- return ((num_entries <= req_entries) &&
- (offset + num_entries <= OPA_VNIC_MAC_TBL_MAX_ENTRIES));
-}
-
-/*
- * Return the power on default values in the port info structure
- * in big endian format as required by MAD.
- */
-static inline void vema_get_pod_values(struct opa_veswport_info *port_info)
-{
- memset(port_info, 0, sizeof(*port_info));
- port_info->vport.max_mac_tbl_ent =
- cpu_to_be16(OPA_VNIC_MAC_TBL_MAX_ENTRIES);
- port_info->vport.max_smac_ent =
- 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);
-}
-
-/**
- * vema_add_vport -- Add a new vnic port
- * @port: ptr to opa_vnic_vema_port struct
- * @vport_num: vnic port number (to be added)
- *
- * Return a pointer to the vnic adapter structure
- */
-static struct opa_vnic_adapter *vema_add_vport(struct opa_vnic_vema_port *port,
- u8 vport_num)
-{
- struct opa_vnic_ctrl_port *cport = port->cport;
- struct opa_vnic_adapter *adapter;
-
- adapter = opa_vnic_add_netdev(cport->ibdev, port->port_num, vport_num);
- if (!IS_ERR(adapter)) {
- int rc;
-
- adapter->cport = cport;
- rc = xa_insert(&port->vports, vport_num, adapter, GFP_KERNEL);
- if (rc < 0) {
- opa_vnic_rem_netdev(adapter);
- adapter = ERR_PTR(rc);
- }
- }
-
- return adapter;
-}
-
-/**
- * vema_get_class_port_info -- Get class info for port
- * @port: Port on whic MAD was received
- * @recvd_mad: pointer to the received mad
- * @rsp_mad: pointer to respose mad
- *
- * This function copies the latest class port info value set for the
- * port and stores it for generating traps
- */
-static void 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)
-{
- struct opa_class_port_info *port_info;
-
- 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->class_version = OPA_EMA_CLASS_VERSION;
-
- /*
- * Set capability mask bit indicating agent generates traps,
- * and set the maximum number of VNIC ports supported.
- */
- port_info->cap_mask = cpu_to_be16((OPA_VNIC_CLASS_CAP_TRAP |
- (OPA_VNIC_MAX_NUM_VPORT << 8)));
-
- /*
- * Since a get routine is always sent by the EM first we
- * set the expected response time to
- * 4.096 usec * 2^18 == 1.0737 sec here.
- */
- port_info->cap_mask2_resp_time = cpu_to_be32(18);
-}
-
-/**
- * vema_set_class_port_info -- Get class info for port
- * @port: Port on whic MAD was received
- * @recvd_mad: pointer to the received mad
- * @rsp_mad: pointer to respose mad
- *
- * This function updates the port class info for the specific vnic
- * and sets up the response mad data
- */
-static void 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)
-{
- memcpy(&port->class_port_info, recvd_mad->data,
- sizeof(port->class_port_info));
-
- vema_get_class_port_info(port, recvd_mad, rsp_mad);
-}
-
-/**
- * vema_get_veswport_info -- Get veswport info
- * @port: source port on which MAD was received
- * @recvd_mad: pointer to the received mad
- * @rsp_mad: pointer to respose mad
- */
-static void vema_get_veswport_info(struct opa_vnic_vema_port *port,
- struct opa_vnic_vema_mad *recvd_mad,
- struct opa_vnic_vema_mad *rsp_mad)
-{
- struct opa_veswport_info *port_info =
- (struct opa_veswport_info *)rsp_mad->data;
- struct opa_vnic_adapter *adapter;
-
- adapter = vema_get_vport_adapter(recvd_mad, port);
- if (adapter) {
- memset(port_info, 0, sizeof(*port_info));
- opa_vnic_get_vesw_info(adapter, &port_info->vesw);
- opa_vnic_get_per_veswport_info(adapter,
- &port_info->vport);
- } else {
- vema_get_pod_values(port_info);
- }
-}
-
-/**
- * vema_set_veswport_info -- Set veswport info
- * @port: source port on which MAD was received
- * @recvd_mad: pointer to the received mad
- * @rsp_mad: pointer to respose mad
- *
- * This function gets the port class infor for vnic
- */
-static void vema_set_veswport_info(struct opa_vnic_vema_port *port,
- struct opa_vnic_vema_mad *recvd_mad,
- struct opa_vnic_vema_mad *rsp_mad)
-{
- struct opa_vnic_ctrl_port *cport = port->cport;
- struct opa_veswport_info *port_info;
- struct opa_vnic_adapter *adapter;
- u8 vport_num;
-
- vport_num = vema_get_vport_num(recvd_mad);
-
- adapter = vema_get_vport_adapter(recvd_mad, port);
- if (!adapter) {
- adapter = vema_add_vport(port, vport_num);
- if (IS_ERR(adapter)) {
- c_err("failed to add vport %d: %ld\n",
- vport_num, PTR_ERR(adapter));
- goto err_exit;
- }
- }
-
- port_info = (struct opa_veswport_info *)recvd_mad->data;
- opa_vnic_set_vesw_info(adapter, &port_info->vesw);
- opa_vnic_set_per_veswport_info(adapter, &port_info->vport);
-
- /* Process the new config settings */
- opa_vnic_process_vema_config(adapter);
-
- vema_get_veswport_info(port, recvd_mad, rsp_mad);
- return;
-
-err_exit:
- rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
-}
-
-/**
- * vema_get_mac_entries -- Get MAC entries in VNIC MAC table
- * @port: source port on which MAD was received
- * @recvd_mad: pointer to the received mad
- * @rsp_mad: pointer to respose mad
- *
- * This function gets the MAC entries that are programmed into
- * the VNIC MAC forwarding table. It checks for the validity of
- * the index into the MAC table and the number of entries that
- * are to be retrieved.
- */
-static void vema_get_mac_entries(struct opa_vnic_vema_port *port,
- struct opa_vnic_vema_mad *recvd_mad,
- struct opa_vnic_vema_mad *rsp_mad)
-{
- struct opa_veswport_mactable *mac_tbl_in, *mac_tbl_out;
- struct opa_vnic_adapter *adapter;
-
- adapter = vema_get_vport_adapter(recvd_mad, port);
- if (!adapter) {
- rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
- return;
- }
-
- mac_tbl_in = (struct opa_veswport_mactable *)recvd_mad->data;
- mac_tbl_out = (struct opa_veswport_mactable *)rsp_mad->data;
-
- if (vema_mac_tbl_req_ok(mac_tbl_in)) {
- mac_tbl_out->offset = mac_tbl_in->offset;
- mac_tbl_out->num_entries = mac_tbl_in->num_entries;
- opa_vnic_query_mac_tbl(adapter, mac_tbl_out);
- } else {
- rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
- }
-}
-
-/**
- * vema_set_mac_entries -- Set MAC entries in VNIC MAC table
- * @port: source port on which MAD was received
- * @recvd_mad: pointer to the received mad
- * @rsp_mad: pointer to respose mad
- *
- * This function sets the MAC entries in the VNIC forwarding table
- * It checks for the validity of the index and the number of forwarding
- * table entries to be programmed.
- */
-static void vema_set_mac_entries(struct opa_vnic_vema_port *port,
- struct opa_vnic_vema_mad *recvd_mad,
- struct opa_vnic_vema_mad *rsp_mad)
-{
- struct opa_veswport_mactable *mac_tbl;
- struct opa_vnic_adapter *adapter;
-
- adapter = vema_get_vport_adapter(recvd_mad, port);
- if (!adapter) {
- rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
- return;
- }
-
- mac_tbl = (struct opa_veswport_mactable *)recvd_mad->data;
- if (vema_mac_tbl_req_ok(mac_tbl)) {
- if (opa_vnic_update_mac_tbl(adapter, mac_tbl))
- rsp_mad->mad_hdr.status = OPA_VNIC_UNSUP_ATTR;
- } else {
- rsp_mad->mad_hdr.status = OPA_VNIC_UNSUP_ATTR;
- }
- vema_get_mac_entries(port, recvd_mad, rsp_mad);
-}
-
-/**
- * vema_set_delete_vesw -- Reset VESW info to POD values
- * @port: source port on which MAD was received
- * @recvd_mad: pointer to the received mad
- * @rsp_mad: pointer to respose mad
- *
- * This function clears all the fields of veswport info for the requested vesw
- * and sets them back to the power-on default values. It does not delete the
- * vesw.
- */
-static void vema_set_delete_vesw(struct opa_vnic_vema_port *port,
- struct opa_vnic_vema_mad *recvd_mad,
- struct opa_vnic_vema_mad *rsp_mad)
-{
- struct opa_veswport_info *port_info =
- (struct opa_veswport_info *)rsp_mad->data;
- struct opa_vnic_adapter *adapter;
-
- adapter = vema_get_vport_adapter(recvd_mad, port);
- if (!adapter) {
- rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
- return;
- }
-
- vema_get_pod_values(port_info);
- opa_vnic_set_vesw_info(adapter, &port_info->vesw);
- opa_vnic_set_per_veswport_info(adapter, &port_info->vport);
-
- /* Process the new config settings */
- opa_vnic_process_vema_config(adapter);
-
- opa_vnic_release_mac_tbl(adapter);
-
- vema_get_veswport_info(port, recvd_mad, rsp_mad);
-}
-
-/**
- * vema_get_mac_list -- Get the unicast/multicast macs.
- * @port: source port on which MAD was received
- * @recvd_mad: Received mad contains fields to set vnic parameters
- * @rsp_mad: Response mad to be built
- * @attr_id: Attribute ID indicating multicast or unicast mac list
- */
-static void 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)
-{
- struct opa_veswport_iface_macs *macs_in, *macs_out;
- int max_entries = (OPA_VNIC_EMA_DATA - sizeof(*macs_out)) / ETH_ALEN;
- struct opa_vnic_adapter *adapter;
-
- adapter = vema_get_vport_adapter(recvd_mad, port);
- if (!adapter) {
- rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
- return;
- }
-
- macs_in = (struct opa_veswport_iface_macs *)recvd_mad->data;
- macs_out = (struct opa_veswport_iface_macs *)rsp_mad->data;
-
- macs_out->start_idx = macs_in->start_idx;
- if (macs_in->num_macs_in_msg)
- macs_out->num_macs_in_msg = macs_in->num_macs_in_msg;
- else
- macs_out->num_macs_in_msg = cpu_to_be16(max_entries);
-
- if (attr_id == OPA_EM_ATTR_IFACE_MCAST_MACS)
- opa_vnic_query_mcast_macs(adapter, macs_out);
- else
- opa_vnic_query_ucast_macs(adapter, macs_out);
-}
-
-/**
- * vema_get_summary_counters -- Gets summary counters.
- * @port: source port on which MAD was received
- * @recvd_mad: Received mad contains fields to set vnic parameters
- * @rsp_mad: Response mad to be built
- */
-static void vema_get_summary_counters(struct opa_vnic_vema_port *port,
- struct opa_vnic_vema_mad *recvd_mad,
- struct opa_vnic_vema_mad *rsp_mad)
-{
- struct opa_veswport_summary_counters *cntrs;
- struct opa_vnic_adapter *adapter;
-
- adapter = vema_get_vport_adapter(recvd_mad, port);
- if (adapter) {
- cntrs = (struct opa_veswport_summary_counters *)rsp_mad->data;
- opa_vnic_get_summary_counters(adapter, cntrs);
- } else {
- rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
- }
-}
-
-/**
- * vema_get_error_counters -- Gets summary counters.
- * @port: source port on which MAD was received
- * @recvd_mad: Received mad contains fields to set vnic parameters
- * @rsp_mad: Response mad to be built
- */
-static void vema_get_error_counters(struct opa_vnic_vema_port *port,
- struct opa_vnic_vema_mad *recvd_mad,
- struct opa_vnic_vema_mad *rsp_mad)
-{
- struct opa_veswport_error_counters *cntrs;
- struct opa_vnic_adapter *adapter;
-
- adapter = vema_get_vport_adapter(recvd_mad, port);
- if (adapter) {
- cntrs = (struct opa_veswport_error_counters *)rsp_mad->data;
- opa_vnic_get_error_counters(adapter, cntrs);
- } else {
- rsp_mad->mad_hdr.status = OPA_VNIC_INVAL_ATTR;
- }
-}
-
-/**
- * vema_get -- Process received get MAD
- * @port: source port on which MAD was received
- * @recvd_mad: Received mad
- * @rsp_mad: Response mad to be built
- */
-static void vema_get(struct opa_vnic_vema_port *port,
- struct opa_vnic_vema_mad *recvd_mad,
- struct opa_vnic_vema_mad *rsp_mad)
-{
- u16 attr_id = be16_to_cpu(recvd_mad->mad_hdr.attr_id);
-
- switch (attr_id) {
- case OPA_EM_ATTR_CLASS_PORT_INFO:
- vema_get_class_port_info(port, recvd_mad, rsp_mad);
- break;
- case OPA_EM_ATTR_VESWPORT_INFO:
- vema_get_veswport_info(port, recvd_mad, rsp_mad);
- break;
- case OPA_EM_ATTR_VESWPORT_MAC_ENTRIES:
- vema_get_mac_entries(port, recvd_mad, rsp_mad);
- break;
- case OPA_EM_ATTR_IFACE_UCAST_MACS:
- case OPA_EM_ATTR_IFACE_MCAST_MACS:
- vema_get_mac_list(port, recvd_mad, rsp_mad, attr_id);
- break;
- case OPA_EM_ATTR_VESWPORT_SUMMARY_COUNTERS:
- vema_get_summary_counters(port, recvd_mad, rsp_mad);
- break;
- case OPA_EM_ATTR_VESWPORT_ERROR_COUNTERS:
- vema_get_error_counters(port, recvd_mad, rsp_mad);
- break;
- default:
- rsp_mad->mad_hdr.status = OPA_VNIC_UNSUP_ATTR;
- break;
- }
-}
-
-/**
- * vema_set -- Process received set MAD
- * @port: source port on which MAD was received
- * @recvd_mad: Received mad contains fields to set vnic parameters
- * @rsp_mad: Response mad to be built
- */
-static void vema_set(struct opa_vnic_vema_port *port,
- struct opa_vnic_vema_mad *recvd_mad,
- struct opa_vnic_vema_mad *rsp_mad)
-{
- u16 attr_id = be16_to_cpu(recvd_mad->mad_hdr.attr_id);
-
- switch (attr_id) {
- case OPA_EM_ATTR_CLASS_PORT_INFO:
- vema_set_class_port_info(port, recvd_mad, rsp_mad);
- break;
- case OPA_EM_ATTR_VESWPORT_INFO:
- vema_set_veswport_info(port, recvd_mad, rsp_mad);
- break;
- case OPA_EM_ATTR_VESWPORT_MAC_ENTRIES:
- vema_set_mac_entries(port, recvd_mad, rsp_mad);
- break;
- case OPA_EM_ATTR_DELETE_VESW:
- vema_set_delete_vesw(port, recvd_mad, rsp_mad);
- break;
- default:
- rsp_mad->mad_hdr.status = OPA_VNIC_UNSUP_ATTR;
- break;
- }
-}
-
-/**
- * vema_send -- Send handler for VEMA MAD agent
- * @mad_agent: pointer to the mad agent
- * @mad_wc: pointer to mad send work completion information
- *
- * Free all the data structures associated with the sent MAD
- */
-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_SLEEPABLE);
- ib_free_send_mad(mad_wc->send_buf);
-}
-
-/**
- * vema_recv -- Recv handler for VEMA MAD agent
- * @mad_agent: pointer to the mad agent
- * @send_buf: Send buffer if found, else NULL
- * @mad_wc: pointer to mad send work completion information
- *
- * Handle only set and get methods and respond to other methods
- * as unsupported. Allocate response buffer and address handle
- * for the response MAD.
- */
-static void vema_recv(struct ib_mad_agent *mad_agent,
- struct ib_mad_send_buf *send_buf,
- struct ib_mad_recv_wc *mad_wc)
-{
- struct opa_vnic_vema_port *port;
- struct ib_ah *ah;
- struct ib_mad_send_buf *rsp;
- struct opa_vnic_vema_mad *vema_mad;
-
- if (!mad_wc || !mad_wc->recv_buf.mad)
- return;
-
- port = mad_agent->context;
- ah = ib_create_ah_from_wc(mad_agent->qp->pd, mad_wc->wc,
- mad_wc->recv_buf.grh, mad_agent->port_num);
- if (IS_ERR(ah))
- goto free_recv_mad;
-
- rsp = ib_create_send_mad(mad_agent, mad_wc->wc->src_qp,
- mad_wc->wc->pkey_index, 0,
- IB_MGMT_VENDOR_HDR, OPA_VNIC_EMA_DATA,
- GFP_KERNEL, OPA_MGMT_BASE_VERSION);
- if (IS_ERR(rsp))
- goto err_rsp;
-
- rsp->ah = ah;
- vema_mad = rsp->mad;
- memcpy(vema_mad, mad_wc->recv_buf.mad, IB_MGMT_VENDOR_HDR);
- vema_mad->mad_hdr.method = IB_MGMT_METHOD_GET_RESP;
- vema_mad->mad_hdr.status = 0;
-
- /* Lock ensures network adapter is not removed */
- mutex_lock(&port->lock);
-
- switch (mad_wc->recv_buf.mad->mad_hdr.method) {
- case IB_MGMT_METHOD_GET:
- vema_get(port, (struct opa_vnic_vema_mad *)mad_wc->recv_buf.mad,
- vema_mad);
- break;
- case IB_MGMT_METHOD_SET:
- vema_set(port, (struct opa_vnic_vema_mad *)mad_wc->recv_buf.mad,
- vema_mad);
- break;
- default:
- vema_mad->mad_hdr.status = OPA_VNIC_UNSUP_ATTR;
- break;
- }
- mutex_unlock(&port->lock);
-
- if (!ib_post_send_mad(rsp, NULL)) {
- /*
- * with post send successful ah and send mad
- * will be destroyed in send handler
- */
- goto free_recv_mad;
- }
-
- ib_free_send_mad(rsp);
-
-err_rsp:
- rdma_destroy_ah(ah, RDMA_DESTROY_AH_SLEEPABLE);
-free_recv_mad:
- ib_free_recv_mad(mad_wc);
-}
-
-/**
- * vema_get_port -- Gets the opa_vnic_vema_port
- * @cport: pointer to control dev
- * @port_num: Port number
- *
- * This function loops through the ports and returns
- * the opa_vnic_vema port structure that is associated
- * with the OPA port number
- *
- * Return: ptr to requested opa_vnic_vema_port strucure
- * if success, NULL if not
- */
-static struct opa_vnic_vema_port *
-vema_get_port(struct opa_vnic_ctrl_port *cport, u8 port_num)
-{
- struct opa_vnic_vema_port *port = (void *)cport + sizeof(*cport);
-
- if (port_num > cport->num_ports)
- return NULL;
-
- return port + (port_num - 1);
-}
-
-/**
- * opa_vnic_vema_send_trap -- This function sends a trap to the EM
- * @adapter: pointer to vnic adapter
- * @data: pointer to trap data filled by calling function
- * @lid: issuers lid (encap_slid from vesw_port_info)
- *
- * This function is called from the VNIC driver to send a trap if there
- * is somethng the EM should be notified about. These events currently
- * are
- * 1) UNICAST INTERFACE MACADDRESS changes
- * 2) MULTICAST INTERFACE MACADDRESS changes
- * 3) ETHERNET LINK STATUS changes
- * While allocating the send mad the remote site qpn used is 1
- * as this is the well known QP.
- *
- */
-void opa_vnic_vema_send_trap(struct opa_vnic_adapter *adapter,
- struct __opa_veswport_trap *data, u32 lid)
-{
- struct opa_vnic_ctrl_port *cport = adapter->cport;
- struct ib_mad_send_buf *send_buf;
- struct opa_vnic_vema_port *port;
- struct ib_device *ibp;
- struct opa_vnic_vema_mad_trap *trap_mad;
- struct opa_class_port_info *class;
- struct rdma_ah_attr ah_attr;
- struct ib_ah *ah;
- struct opa_veswport_trap *trap;
- u32 trap_lid;
- u16 pkey_idx;
-
- if (!cport)
- goto err_exit;
- ibp = cport->ibdev;
- port = vema_get_port(cport, data->opaportnum);
- if (!port || !port->mad_agent)
- goto err_exit;
-
- if (time_before(jiffies, adapter->trap_timeout)) {
- if (adapter->trap_count == OPA_VNIC_TRAP_BURST_LIMIT) {
- v_warn("Trap rate exceeded\n");
- goto err_exit;
- } else {
- adapter->trap_count++;
- }
- } else {
- adapter->trap_count = 0;
- }
-
- class = &port->class_port_info;
- /* Set up address handle */
- memset(&ah_attr, 0, sizeof(ah_attr));
- ah_attr.type = rdma_ah_find_type(ibp, port->port_num);
- rdma_ah_set_sl(&ah_attr,
- GET_TRAP_SL_FROM_CLASS_PORT_INFO(class->trap_sl_rsvd));
- rdma_ah_set_port_num(&ah_attr, port->port_num);
- trap_lid = be32_to_cpu(class->trap_lid);
- /*
- * check for trap lid validity, must not be zero
- * The trap sink could change after we fashion the MAD but since traps
- * are not guaranteed we won't use a lock as anyway the change will take
- * place even with locking.
- */
- if (!trap_lid) {
- c_err("%s: Invalid dlid\n", __func__);
- goto err_exit;
- }
-
- rdma_ah_set_dlid(&ah_attr, trap_lid);
- 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__,
- rdma_ah_get_dlid(&ah_attr), rdma_ah_get_sl(&ah_attr),
- rdma_ah_get_port_num(&ah_attr));
- goto err_exit;
- }
-
- if (ib_find_pkey(ibp, data->opaportnum, IB_DEFAULT_PKEY_FULL,
- &pkey_idx) < 0) {
- c_err("%s:full key not found, defaulting to partial\n",
- __func__);
- if (ib_find_pkey(ibp, data->opaportnum, IB_DEFAULT_PKEY_PARTIAL,
- &pkey_idx) < 0)
- pkey_idx = 1;
- }
-
- send_buf = ib_create_send_mad(port->mad_agent, 1, pkey_idx, 0,
- IB_MGMT_VENDOR_HDR, IB_MGMT_MAD_DATA,
- GFP_ATOMIC, OPA_MGMT_BASE_VERSION);
- if (IS_ERR(send_buf)) {
- c_err("%s:Couldn't allocate send buf\n", __func__);
- goto err_sndbuf;
- }
-
- send_buf->ah = ah;
-
- /* Set up common MAD hdr */
- trap_mad = send_buf->mad;
- trap_mad->mad_hdr.base_version = OPA_MGMT_BASE_VERSION;
- trap_mad->mad_hdr.mgmt_class = OPA_MGMT_CLASS_INTEL_EMA;
- trap_mad->mad_hdr.class_version = OPA_EMA_CLASS_VERSION;
- trap_mad->mad_hdr.method = IB_MGMT_METHOD_TRAP;
- port->tid++;
- trap_mad->mad_hdr.tid = cpu_to_be64(port->tid);
- trap_mad->mad_hdr.attr_id = IB_SMP_ATTR_NOTICE;
-
- /* Set up vendor OUI */
- trap_mad->oui[0] = INTEL_OUI_1;
- trap_mad->oui[1] = INTEL_OUI_2;
- trap_mad->oui[2] = INTEL_OUI_3;
-
- /* Setup notice attribute portion */
- trap_mad->notice.gen_type = OPA_INTEL_EMA_NOTICE_TYPE_INFO << 1;
- trap_mad->notice.oui_1 = INTEL_OUI_1;
- trap_mad->notice.oui_2 = INTEL_OUI_2;
- trap_mad->notice.oui_3 = INTEL_OUI_3;
- trap_mad->notice.issuer_lid = cpu_to_be32(lid);
-
- /* copy the actual trap data */
- trap = (struct opa_veswport_trap *)trap_mad->notice.raw_data;
- trap->fabric_id = cpu_to_be16(data->fabric_id);
- trap->veswid = cpu_to_be16(data->veswid);
- trap->veswportnum = cpu_to_be32(data->veswportnum);
- trap->opaportnum = cpu_to_be16(data->opaportnum);
- trap->veswportindex = data->veswportindex;
- trap->opcode = data->opcode;
-
- /* If successful send set up rate limit timeout else bail */
- if (ib_post_send_mad(send_buf, NULL)) {
- ib_free_send_mad(send_buf);
- } else {
- if (adapter->trap_count)
- return;
- adapter->trap_timeout = jiffies +
- usecs_to_jiffies(OPA_VNIC_TRAP_TIMEOUT);
- return;
- }
-
-err_sndbuf:
- rdma_destroy_ah(ah, 0);
-err_exit:
- v_err("Aborting trap\n");
-}
-
-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, dev_name(&record->device->dev),
- record->element.port_num);
-
- 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);
- }
-}
-
-/**
- * vema_unregister -- Unregisters agent
- * @cport: pointer to control port
- *
- * This deletes the registration by VEMA for MADs
- */
-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++) {
- struct opa_vnic_vema_port *port = vema_get_port(cport, i);
-
- if (!port->mad_agent)
- continue;
-
- /* Lock ensures no MAD is being processed */
- mutex_lock(&port->lock);
- 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);
- xa_destroy(&port->vports);
- ib_unregister_event_handler(&port->event_handler);
- }
-}
-
-/**
- * vema_register -- Registers agent
- * @cport: pointer to control port
- *
- * This function registers the handlers for the VEMA MADs
- *
- * Return: returns 0 on success. non zero otherwise
- */
-static int vema_register(struct opa_vnic_ctrl_port *cport)
-{
- struct ib_mad_reg_req reg_req = {
- .mgmt_class = OPA_MGMT_CLASS_INTEL_EMA,
- .mgmt_class_version = OPA_MGMT_BASE_VERSION,
- .oui = { INTEL_OUI_1, INTEL_OUI_2, INTEL_OUI_3 }
- };
- int i;
-
- set_bit(IB_MGMT_METHOD_GET, reg_req.method_mask);
- set_bit(IB_MGMT_METHOD_SET, reg_req.method_mask);
-
- /* register ib event handler and mad agent for each port on dev */
- for (i = 1; i <= cport->num_ports; i++) {
- struct opa_vnic_vema_port *port = vema_get_port(cport, i);
- int ret;
-
- port->cport = cport;
- port->port_num = i;
-
- INIT_IB_EVENT_HANDLER(&port->event_handler,
- cport->ibdev, opa_vnic_event);
- ib_register_event_handler(&port->event_handler);
-
- xa_init(&port->vports);
- mutex_init(&port->lock);
- port->mad_agent = ib_register_mad_agent(cport->ibdev, i,
- IB_QPT_GSI, &reg_req,
- IB_MGMT_RMPP_VERSION,
- vema_send, vema_recv,
- port, 0);
- if (IS_ERR(port->mad_agent)) {
- ret = PTR_ERR(port->mad_agent);
- port->mad_agent = NULL;
- mutex_destroy(&port->lock);
- vema_unregister(cport);
- return ret;
- }
- }
-
- return 0;
-}
-
-/**
- * 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 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 -EOPNOTSUPP;
-
- size += device->phys_port_cnt * sizeof(struct opa_vnic_vema_port);
- cport = kzalloc(size, GFP_KERNEL);
- if (!cport)
- return -ENOMEM;
-
- cport->num_ports = device->phys_port_cnt;
- cport->ibdev = device;
-
- /* Initialize opa vnic management agent (vema) */
- rc = vema_register(cport);
- if (!rc)
- c_info("VNIC client initialized\n");
-
- ib_set_client_data(device, &opa_vnic_client, cport);
- opa_vnic_ctrl_config_dev(cport, true);
- return 0;
-}
-
-/**
- * opa_vnic_vema_rem_one -- Handle ib device removal
- * @device: ib device pointer
- * @client_data: ib client data
- *
- * Uninitialize and free the vnic control port.
- */
-static void opa_vnic_vema_rem_one(struct ib_device *device,
- void *client_data)
-{
- struct opa_vnic_ctrl_port *cport = client_data;
-
- c_info("removing VNIC client\n");
- opa_vnic_ctrl_config_dev(cport, false);
- vema_unregister(cport);
- kfree(cport);
-}
-
-static int __init opa_vnic_init(void)
-{
- int rc;
-
- rc = ib_register_client(&opa_vnic_client);
- if (rc)
- pr_err("VNIC driver register failed %d\n", rc);
-
- return rc;
-}
-module_init(opa_vnic_init);
-
-static void opa_vnic_deinit(void)
-{
- ib_unregister_client(&opa_vnic_client);
-}
-module_exit(opa_vnic_deinit);
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_AUTHOR("Cornelis Networks");
-MODULE_DESCRIPTION("Cornelis OPX Virtual Network driver");
diff --git a/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema_iface.c b/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema_iface.c
deleted file mode 100644
index 292c037aa239..000000000000
--- a/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema_iface.c
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * Copyright(c) 2017 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * - Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
- * This file contains OPA VNIC EMA Interface functions.
- */
-
-#include "opa_vnic_internal.h"
-
-/**
- * opa_vnic_vema_report_event - sent trap to report the specified event
- * @adapter: vnic port adapter
- * @event: event to be reported
- *
- * This function calls vema api to sent a trap for the given event.
- */
-void opa_vnic_vema_report_event(struct opa_vnic_adapter *adapter, u8 event)
-{
- struct __opa_veswport_info *info = &adapter->info;
- struct __opa_veswport_trap trap_data;
-
- trap_data.fabric_id = info->vesw.fabric_id;
- trap_data.veswid = info->vesw.vesw_id;
- trap_data.veswportnum = info->vport.port_num;
- trap_data.opaportnum = adapter->port_num;
- trap_data.veswportindex = adapter->vport_num;
- trap_data.opcode = event;
-
- opa_vnic_vema_send_trap(adapter, &trap_data, info->vport.encap_slid);
-}
-
-/**
- * opa_vnic_get_summary_counters - get summary counters
- * @adapter: vnic port adapter
- * @cntrs: pointer to destination summary counters structure
- *
- * This function populates the summary counters that is maintained by the
- * given adapter to destination address provided.
- */
-void opa_vnic_get_summary_counters(struct opa_vnic_adapter *adapter,
- struct opa_veswport_summary_counters *cntrs)
-{
- struct opa_vnic_stats vstats;
- __be64 *dst;
- u64 *src;
-
- memset(&vstats, 0, sizeof(vstats));
- spin_lock(&adapter->stats_lock);
- adapter->rn_ops->ndo_get_stats64(adapter->netdev, &vstats.netstats);
- spin_unlock(&adapter->stats_lock);
-
- cntrs->vp_instance = cpu_to_be16(adapter->vport_num);
- cntrs->vesw_id = cpu_to_be16(adapter->info.vesw.vesw_id);
- cntrs->veswport_num = cpu_to_be32(adapter->port_num);
-
- cntrs->tx_errors = cpu_to_be64(vstats.netstats.tx_errors);
- cntrs->rx_errors = cpu_to_be64(vstats.netstats.rx_errors);
- cntrs->tx_packets = cpu_to_be64(vstats.netstats.tx_packets);
- cntrs->rx_packets = cpu_to_be64(vstats.netstats.rx_packets);
- cntrs->tx_bytes = cpu_to_be64(vstats.netstats.tx_bytes);
- cntrs->rx_bytes = cpu_to_be64(vstats.netstats.rx_bytes);
-
- /*
- * This loop depends on layout of
- * opa_veswport_summary_counters opa_vnic_stats structures.
- */
- for (dst = &cntrs->tx_unicast, src = &vstats.tx_grp.unicast;
- dst < &cntrs->reserved[0]; dst++, src++) {
- *dst = cpu_to_be64(*src);
- }
-}
-
-/**
- * opa_vnic_get_error_counters - get error counters
- * @adapter: vnic port adapter
- * @cntrs: pointer to destination error counters structure
- *
- * This function populates the error counters that is maintained by the
- * given adapter to destination address provided.
- */
-void opa_vnic_get_error_counters(struct opa_vnic_adapter *adapter,
- struct opa_veswport_error_counters *cntrs)
-{
- struct opa_vnic_stats vstats;
-
- memset(&vstats, 0, sizeof(vstats));
- spin_lock(&adapter->stats_lock);
- adapter->rn_ops->ndo_get_stats64(adapter->netdev, &vstats.netstats);
- spin_unlock(&adapter->stats_lock);
-
- cntrs->vp_instance = cpu_to_be16(adapter->vport_num);
- cntrs->vesw_id = cpu_to_be16(adapter->info.vesw.vesw_id);
- cntrs->veswport_num = cpu_to_be32(adapter->port_num);
-
- cntrs->tx_errors = cpu_to_be64(vstats.netstats.tx_errors);
- cntrs->rx_errors = cpu_to_be64(vstats.netstats.rx_errors);
- cntrs->tx_dlid_zero = cpu_to_be64(vstats.tx_dlid_zero);
- cntrs->tx_drop_state = cpu_to_be64(vstats.tx_drop_state);
- cntrs->tx_logic = cpu_to_be64(vstats.netstats.tx_fifo_errors +
- vstats.netstats.tx_carrier_errors);
-
- cntrs->rx_bad_veswid = cpu_to_be64(vstats.netstats.rx_nohandler);
- cntrs->rx_runt = cpu_to_be64(vstats.rx_runt);
- cntrs->rx_oversize = cpu_to_be64(vstats.rx_oversize);
- cntrs->rx_drop_state = cpu_to_be64(vstats.rx_drop_state);
- cntrs->rx_logic = cpu_to_be64(vstats.netstats.rx_fifo_errors);
-}
-
-/**
- * opa_vnic_get_vesw_info -- Get the vesw information
- * @adapter: vnic port adapter
- * @info: pointer to destination vesw info structure
- *
- * This function copies the vesw info that is maintained by the
- * given adapter to destination address provided.
- */
-void opa_vnic_get_vesw_info(struct opa_vnic_adapter *adapter,
- struct opa_vesw_info *info)
-{
- struct __opa_vesw_info *src = &adapter->info.vesw;
- int i;
-
- info->fabric_id = cpu_to_be16(src->fabric_id);
- info->vesw_id = cpu_to_be16(src->vesw_id);
- memcpy(info->rsvd0, src->rsvd0, ARRAY_SIZE(src->rsvd0));
- info->def_port_mask = cpu_to_be16(src->def_port_mask);
- memcpy(info->rsvd1, src->rsvd1, ARRAY_SIZE(src->rsvd1));
- info->pkey = cpu_to_be16(src->pkey);
-
- memcpy(info->rsvd2, src->rsvd2, ARRAY_SIZE(src->rsvd2));
- info->u_mcast_dlid = cpu_to_be32(src->u_mcast_dlid);
- for (i = 0; i < OPA_VESW_MAX_NUM_DEF_PORT; i++)
- info->u_ucast_dlid[i] = cpu_to_be32(src->u_ucast_dlid[i]);
-
- info->rc = cpu_to_be32(src->rc);
-
- memcpy(info->rsvd3, src->rsvd3, ARRAY_SIZE(src->rsvd3));
- info->eth_mtu = cpu_to_be16(src->eth_mtu);
- memcpy(info->rsvd4, src->rsvd4, ARRAY_SIZE(src->rsvd4));
-}
-
-/**
- * opa_vnic_set_vesw_info -- Set the vesw information
- * @adapter: vnic port adapter
- * @info: pointer to vesw info structure
- *
- * This function updates the vesw info that is maintained by the
- * given adapter with vesw info provided. Reserved fields are stored
- * and returned back to EM as is.
- */
-void opa_vnic_set_vesw_info(struct opa_vnic_adapter *adapter,
- struct opa_vesw_info *info)
-{
- struct __opa_vesw_info *dst = &adapter->info.vesw;
- int i;
-
- dst->fabric_id = be16_to_cpu(info->fabric_id);
- dst->vesw_id = be16_to_cpu(info->vesw_id);
- memcpy(dst->rsvd0, info->rsvd0, ARRAY_SIZE(info->rsvd0));
- dst->def_port_mask = be16_to_cpu(info->def_port_mask);
- memcpy(dst->rsvd1, info->rsvd1, ARRAY_SIZE(info->rsvd1));
- dst->pkey = be16_to_cpu(info->pkey);
-
- memcpy(dst->rsvd2, info->rsvd2, ARRAY_SIZE(info->rsvd2));
- dst->u_mcast_dlid = be32_to_cpu(info->u_mcast_dlid);
- for (i = 0; i < OPA_VESW_MAX_NUM_DEF_PORT; i++)
- dst->u_ucast_dlid[i] = be32_to_cpu(info->u_ucast_dlid[i]);
-
- dst->rc = be32_to_cpu(info->rc);
-
- memcpy(dst->rsvd3, info->rsvd3, ARRAY_SIZE(info->rsvd3));
- dst->eth_mtu = be16_to_cpu(info->eth_mtu);
- memcpy(dst->rsvd4, info->rsvd4, ARRAY_SIZE(info->rsvd4));
-}
-
-/**
- * opa_vnic_get_per_veswport_info -- Get the vesw per port information
- * @adapter: vnic port adapter
- * @info: pointer to destination vport info structure
- *
- * This function copies the vesw per port info that is maintained by the
- * given adapter to destination address provided.
- * Note that the read only fields are not copied.
- */
-void opa_vnic_get_per_veswport_info(struct opa_vnic_adapter *adapter,
- struct opa_per_veswport_info *info)
-{
- struct __opa_per_veswport_info *src = &adapter->info.vport;
-
- info->port_num = cpu_to_be32(src->port_num);
- info->eth_link_status = src->eth_link_status;
- memcpy(info->rsvd0, src->rsvd0, ARRAY_SIZE(src->rsvd0));
-
- memcpy(info->base_mac_addr, src->base_mac_addr,
- ARRAY_SIZE(info->base_mac_addr));
- info->config_state = src->config_state;
- info->oper_state = src->oper_state;
- info->max_mac_tbl_ent = cpu_to_be16(src->max_mac_tbl_ent);
- info->max_smac_ent = cpu_to_be16(src->max_smac_ent);
- info->mac_tbl_digest = cpu_to_be32(src->mac_tbl_digest);
- memcpy(info->rsvd1, src->rsvd1, ARRAY_SIZE(src->rsvd1));
-
- info->encap_slid = cpu_to_be32(src->encap_slid);
- memcpy(info->pcp_to_sc_uc, src->pcp_to_sc_uc,
- ARRAY_SIZE(info->pcp_to_sc_uc));
- memcpy(info->pcp_to_vl_uc, src->pcp_to_vl_uc,
- ARRAY_SIZE(info->pcp_to_vl_uc));
- memcpy(info->pcp_to_sc_mc, src->pcp_to_sc_mc,
- ARRAY_SIZE(info->pcp_to_sc_mc));
- memcpy(info->pcp_to_vl_mc, src->pcp_to_vl_mc,
- ARRAY_SIZE(info->pcp_to_vl_mc));
- info->non_vlan_sc_uc = src->non_vlan_sc_uc;
- info->non_vlan_vl_uc = src->non_vlan_vl_uc;
- info->non_vlan_sc_mc = src->non_vlan_sc_mc;
- info->non_vlan_vl_mc = src->non_vlan_vl_mc;
- memcpy(info->rsvd2, src->rsvd2, ARRAY_SIZE(src->rsvd2));
-
- info->uc_macs_gen_count = cpu_to_be16(src->uc_macs_gen_count);
- info->mc_macs_gen_count = cpu_to_be16(src->mc_macs_gen_count);
- memcpy(info->rsvd3, src->rsvd3, ARRAY_SIZE(src->rsvd3));
-}
-
-/**
- * opa_vnic_set_per_veswport_info -- Set vesw per port information
- * @adapter: vnic port adapter
- * @info: pointer to vport info structure
- *
- * This function updates the vesw per port info that is maintained by the
- * given adapter with vesw per port info provided. Reserved fields are
- * stored and returned back to EM as is.
- */
-void opa_vnic_set_per_veswport_info(struct opa_vnic_adapter *adapter,
- struct opa_per_veswport_info *info)
-{
- struct __opa_per_veswport_info *dst = &adapter->info.vport;
-
- dst->port_num = be32_to_cpu(info->port_num);
- memcpy(dst->rsvd0, info->rsvd0, ARRAY_SIZE(info->rsvd0));
-
- memcpy(dst->base_mac_addr, info->base_mac_addr,
- ARRAY_SIZE(dst->base_mac_addr));
- dst->config_state = info->config_state;
- memcpy(dst->rsvd1, info->rsvd1, ARRAY_SIZE(info->rsvd1));
-
- dst->encap_slid = be32_to_cpu(info->encap_slid);
- memcpy(dst->pcp_to_sc_uc, info->pcp_to_sc_uc,
- ARRAY_SIZE(dst->pcp_to_sc_uc));
- memcpy(dst->pcp_to_vl_uc, info->pcp_to_vl_uc,
- ARRAY_SIZE(dst->pcp_to_vl_uc));
- memcpy(dst->pcp_to_sc_mc, info->pcp_to_sc_mc,
- ARRAY_SIZE(dst->pcp_to_sc_mc));
- memcpy(dst->pcp_to_vl_mc, info->pcp_to_vl_mc,
- ARRAY_SIZE(dst->pcp_to_vl_mc));
- dst->non_vlan_sc_uc = info->non_vlan_sc_uc;
- dst->non_vlan_vl_uc = info->non_vlan_vl_uc;
- dst->non_vlan_sc_mc = info->non_vlan_sc_mc;
- dst->non_vlan_vl_mc = info->non_vlan_vl_mc;
- memcpy(dst->rsvd2, info->rsvd2, ARRAY_SIZE(info->rsvd2));
- memcpy(dst->rsvd3, info->rsvd3, ARRAY_SIZE(info->rsvd3));
-}
-
-/**
- * opa_vnic_query_mcast_macs - query multicast mac list
- * @adapter: vnic port adapter
- * @macs: pointer mac list
- *
- * This function populates the provided mac list with the configured
- * multicast addresses in the adapter.
- */
-void opa_vnic_query_mcast_macs(struct opa_vnic_adapter *adapter,
- struct opa_veswport_iface_macs *macs)
-{
- u16 start_idx, num_macs, idx = 0, count = 0;
- struct netdev_hw_addr *ha;
-
- start_idx = be16_to_cpu(macs->start_idx);
- num_macs = be16_to_cpu(macs->num_macs_in_msg);
- netdev_for_each_mc_addr(ha, adapter->netdev) {
- struct opa_vnic_iface_mac_entry *entry = &macs->entry[count];
-
- if (start_idx > idx++)
- continue;
- else if (num_macs == count)
- break;
- memcpy(entry, ha->addr, sizeof(*entry));
- count++;
- }
-
- macs->tot_macs_in_lst = cpu_to_be16(netdev_mc_count(adapter->netdev));
- macs->num_macs_in_msg = cpu_to_be16(count);
- macs->gen_count = cpu_to_be16(adapter->info.vport.mc_macs_gen_count);
-}
-
-/**
- * opa_vnic_query_ucast_macs - query unicast mac list
- * @adapter: vnic port adapter
- * @macs: pointer mac list
- *
- * This function populates the provided mac list with the configured
- * unicast addresses in the adapter.
- */
-void opa_vnic_query_ucast_macs(struct opa_vnic_adapter *adapter,
- struct opa_veswport_iface_macs *macs)
-{
- u16 start_idx, tot_macs, num_macs, idx = 0, count = 0, em_macs = 0;
- struct netdev_hw_addr *ha;
-
- start_idx = be16_to_cpu(macs->start_idx);
- num_macs = be16_to_cpu(macs->num_macs_in_msg);
- /* loop through dev_addrs list first */
- for_each_dev_addr(adapter->netdev, ha) {
- struct opa_vnic_iface_mac_entry *entry = &macs->entry[count];
-
- /* Do not include EM specified MAC address */
- if (!memcmp(adapter->info.vport.base_mac_addr, ha->addr,
- ARRAY_SIZE(adapter->info.vport.base_mac_addr))) {
- em_macs++;
- continue;
- }
-
- if (start_idx > idx++)
- continue;
- else if (num_macs == count)
- break;
- memcpy(entry, ha->addr, sizeof(*entry));
- count++;
- }
-
- /* loop through uc list */
- netdev_for_each_uc_addr(ha, adapter->netdev) {
- struct opa_vnic_iface_mac_entry *entry = &macs->entry[count];
-
- if (start_idx > idx++)
- continue;
- else if (num_macs == count)
- break;
- memcpy(entry, ha->addr, sizeof(*entry));
- count++;
- }
-
- tot_macs = netdev_hw_addr_list_count(&adapter->netdev->dev_addrs) +
- netdev_uc_count(adapter->netdev) - em_macs;
- macs->tot_macs_in_lst = cpu_to_be16(tot_macs);
- macs->num_macs_in_msg = cpu_to_be16(count);
- macs->gen_count = cpu_to_be16(adapter->info.vport.uc_macs_gen_count);
-}
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c b/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c
index 287e0ea43287..f8b833bd81ad 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c
@@ -37,8 +37,6 @@ static void rtrs_clt_path_stats_release(struct kobject *kobj)
stats = container_of(kobj, struct rtrs_clt_stats, kobj_stats);
free_percpu(stats->pcpu_stats);
-
- kfree(stats);
}
static struct kobj_type ktype_stats = {
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt-trace.h b/drivers/infiniband/ulp/rtrs/rtrs-clt-trace.h
index 7738e2676855..29e23404bb7b 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt-trace.h
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt-trace.h
@@ -55,7 +55,7 @@ DECLARE_EVENT_CLASS(rtrs_clt_conn_class,
__entry->max_reconnect_attempts = clt->max_reconnect_attempts;
__entry->fail_cnt = clt_path->stats->reconnects.fail_cnt;
__entry->success_cnt = clt_path->stats->reconnects.successful_cnt;
- memcpy(__entry->sessname, kobject_name(&clt_path->kobj), NAME_MAX);
+ strscpy(__entry->sessname, kobject_name(&clt_path->kobj) ?: "", NAME_MAX);
),
TP_printk("RTRS-CLT: sess='%s' state=%s attempts='%d' max-attempts='%d' fail='%d' success='%d'",
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
index 3362362f9e2e..eac38b57b00d 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
@@ -1536,7 +1536,7 @@ static struct rtrs_clt_path *alloc_path(struct rtrs_clt_sess *clt,
int cpu;
size_t total_con;
- clt_path = kzalloc_obj(*clt_path);
+ clt_path = kzalloc_flex(*clt_path, stats, 1);
if (!clt_path)
goto err;
@@ -1552,10 +1552,6 @@ static struct rtrs_clt_path *alloc_path(struct rtrs_clt_sess *clt,
clt_path->s.con_num = total_con;
clt_path->s.irq_con_num = con_num + 1;
- clt_path->stats = kzalloc_obj(*clt_path->stats);
- if (!clt_path->stats)
- goto err_free_con;
-
mutex_init(&clt_path->init_mutex);
uuid_gen(&clt_path->s.uuid);
memcpy(&clt_path->s.dst_addr, path->dst,
@@ -1583,7 +1579,7 @@ static struct rtrs_clt_path *alloc_path(struct rtrs_clt_sess *clt,
clt_path->mp_skip_entry = alloc_percpu(typeof(*clt_path->mp_skip_entry));
if (!clt_path->mp_skip_entry)
- goto err_free_stats;
+ goto err_free_con;
for_each_possible_cpu(cpu)
INIT_LIST_HEAD(per_cpu_ptr(clt_path->mp_skip_entry, cpu));
@@ -1596,8 +1592,6 @@ static struct rtrs_clt_path *alloc_path(struct rtrs_clt_sess *clt,
err_free_percpu:
free_percpu(clt_path->mp_skip_entry);
-err_free_stats:
- kfree(clt_path->stats);
err_free_con:
kfree(clt_path->s.con);
err_free_path:
@@ -1681,8 +1675,7 @@ static int create_con_cq_qp(struct rtrs_clt_con *con)
* + 2 for drain and heartbeat
* in case qp gets into error state.
*/
- max_send_wr =
- min_t(int, wr_limit, SERVICE_CON_QUEUE_DEPTH * 2 + 2);
+ max_send_wr = min(wr_limit, SERVICE_CON_QUEUE_DEPTH * 2 + 2);
max_recv_wr = max_send_wr;
} else {
/*
@@ -1698,11 +1691,9 @@ static int create_con_cq_qp(struct rtrs_clt_con *con)
wr_limit = clt_path->s.dev->ib_dev->attrs.max_qp_wr;
/* Shared between connections */
clt_path->s.dev_ref++;
- max_send_wr = min_t(int, wr_limit,
- /* QD * (REQ + RSP + FR REGS or INVS) + drain */
- clt_path->queue_depth * 4 + 1);
- max_recv_wr = min_t(int, wr_limit,
- clt_path->queue_depth * 3 + 1);
+ /* QD * (REQ + RSP + FR REGS or INVS) + drain */
+ max_send_wr = min(wr_limit, clt_path->queue_depth * 4 + 1);
+ max_recv_wr = min(wr_limit, clt_path->queue_depth * 3 + 1);
max_send_sge = 2;
}
atomic_set(&con->c.sq_wr_avail, max_send_wr);
@@ -1741,6 +1732,8 @@ static void destroy_con_cq_qp(struct rtrs_clt_con *con)
/*
* Be careful here: destroy_con_cq_qp() can be called even
* create_con_cq_qp() failed, see comments there.
+ * Caller must set con->destroyed under this lock first so a
+ * racing ADDR_RESOLVED cannot ib_cq_pool_get() after we PUT/SKIP.
*/
lockdep_assert_held(&con->con_mutex);
rtrs_cq_qp_destroy(&con->c);
@@ -1775,6 +1768,10 @@ static int rtrs_rdma_addr_resolved(struct rtrs_clt_con *con)
int err;
mutex_lock(&con->con_mutex);
+ if (con->destroyed) {
+ mutex_unlock(&con->con_mutex);
+ return -ECONNABORTED;
+ }
err = create_con_cq_qp(con);
mutex_unlock(&con->con_mutex);
if (err) {
@@ -2230,6 +2227,7 @@ static void rtrs_clt_stop_and_destroy_conns(struct rtrs_clt_path *clt_path)
break;
con = to_clt_con(clt_path->s.con[cid]);
mutex_lock(&con->con_mutex);
+ con->destroyed = true;
destroy_con_cq_qp(con);
mutex_unlock(&con->con_mutex);
destroy_cm(con);
@@ -2396,6 +2394,7 @@ destroy:
if (con->c.cm_id) {
stop_cm(con);
mutex_lock(&con->con_mutex);
+ con->destroyed = true;
destroy_con_cq_qp(con);
mutex_unlock(&con->con_mutex);
destroy_cm(con);
@@ -2863,7 +2862,6 @@ struct rtrs_clt_sess *rtrs_clt_open(struct rtrs_clt_ops *ops,
list_del_rcu(&clt_path->s.entry);
rtrs_clt_close_conns(clt_path, true);
free_percpu(clt_path->stats->pcpu_stats);
- kfree(clt_path->stats);
free_path(clt_path);
goto close_all_path;
}
@@ -2873,7 +2871,6 @@ struct rtrs_clt_sess *rtrs_clt_open(struct rtrs_clt_ops *ops,
list_del_rcu(&clt_path->s.entry);
rtrs_clt_close_conns(clt_path, true);
free_percpu(clt_path->stats->pcpu_stats);
- kfree(clt_path->stats);
free_path(clt_path);
goto close_all_path;
}
@@ -3166,7 +3163,6 @@ close_path:
rtrs_clt_remove_path_from_arr(clt_path);
rtrs_clt_close_conns(clt_path, true);
free_percpu(clt_path->stats->pcpu_stats);
- kfree(clt_path->stats);
free_path(clt_path);
return err;
@@ -3219,7 +3215,7 @@ static int __init rtrs_client_init(void)
pr_err("Failed to create rtrs-client dev class\n");
return ret;
}
- rtrs_wq = alloc_workqueue("rtrs_client_wq", 0, 0);
+ rtrs_wq = alloc_workqueue("rtrs_client_wq", WQ_PERCPU, 0);
if (!rtrs_wq) {
class_unregister(&rtrs_clt_dev_class);
return -ENOMEM;
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.h b/drivers/infiniband/ulp/rtrs/rtrs-clt.h
index 986239ed2d3b..ad64f4517c4b 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.h
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.h
@@ -75,6 +75,8 @@ struct rtrs_clt_con {
unsigned int cpu;
struct mutex con_mutex;
int cm_err;
+ /* Set under con_mutex before CQ/QP teardown. */
+ bool destroyed;
};
/**
@@ -142,12 +144,12 @@ struct rtrs_clt_path {
u32 flags;
struct kobject kobj;
u8 for_new_clt;
- struct rtrs_clt_stats *stats;
/* cache hca_port and hca_name to display in sysfs */
u8 hca_port;
char hca_name[IB_DEVICE_NAME_MAX];
struct list_head __percpu
*mp_skip_entry;
+ struct rtrs_clt_stats stats[];
};
struct rtrs_clt_sess {
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c b/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c
index 51727c7d710c..9dd9141c86a5 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c
@@ -295,8 +295,8 @@ remove_group:
put_kobj:
kobject_del(&srv_path->kobj);
destroy_root:
- kobject_put(&srv_path->kobj);
rtrs_srv_destroy_once_sysfs_root_folders(srv_path);
+ kobject_put(&srv_path->kobj);
return err;
}
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv-trace.h b/drivers/infiniband/ulp/rtrs/rtrs-srv-trace.h
index 587d3e033081..a7d7b971e6c8 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-srv-trace.h
+++ b/drivers/infiniband/ulp/rtrs/rtrs-srv-trace.h
@@ -61,7 +61,7 @@ TRACE_EVENT(send_io_resp_imm,
__entry->msg_id = id->msg_id;
__entry->wr_cnt = atomic_read(&con->c.wr_cnt);
__entry->signal_interval = s->signal_interval;
- memcpy(__entry->sessname, kobject_name(&srv_path->kobj), NAME_MAX);
+ strscpy(__entry->sessname, kobject_name(&srv_path->kobj) ?: "", NAME_MAX);
),
TP_printk("sess='%s' state='%s' dir=%s err='%d' inval='%d' glob-inval='%d' msgid='%u' wrcnt='%d' sig-interval='%u'",
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
index 0140bfaed721..5314599d29fe 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
@@ -225,8 +225,9 @@ static int rdma_write_sg(struct rtrs_srv_op *id)
/* WR will fail with length error
* if this is 0
*/
- if (plist->length == 0) {
- rtrs_err(s, "Invalid RDMA-Write sg list length 0\n");
+ if (plist->length == 0 || plist->length > max_chunk_size) {
+ rtrs_err(s, "Invalid RDMA-Write sg list length %u\n",
+ plist->length);
return -EINVAL;
}
@@ -1059,6 +1060,11 @@ static void process_read(struct rtrs_srv_con *con,
"Processing read request failed, invalid message\n");
return;
}
+ usr_len = le16_to_cpu(msg->usr_len);
+ if (usr_len > off) {
+ pr_debug("rtrs-srv: Invalid usr_len %zu > off %u\n", usr_len, off);
+ return;
+ }
rtrs_srv_get_ops_ids(srv_path);
rtrs_srv_update_rdma_stats(srv_path->stats, off, READ);
id = srv_path->ops_ids[buf_id];
@@ -1066,7 +1072,6 @@ static void process_read(struct rtrs_srv_con *con,
id->dir = READ;
id->msg_id = buf_id;
id->rd_msg = msg;
- usr_len = le16_to_cpu(msg->usr_len);
data_len = off - usr_len;
data = page_address(srv->chunks[buf_id]);
ret = ctx->ops.rdma_ev(srv->priv, id, data, data_len,
@@ -1112,6 +1117,11 @@ static void process_write(struct rtrs_srv_con *con,
rtrs_srv_state_str(srv_path->state));
return;
}
+ usr_len = le16_to_cpu(req->usr_len);
+ if (usr_len > off) {
+ pr_debug("rtrs-srv: Invalid usr_len %zu > off %u\n", usr_len, off);
+ return;
+ }
rtrs_srv_get_ops_ids(srv_path);
rtrs_srv_update_rdma_stats(srv_path->stats, off, WRITE);
id = srv_path->ops_ids[buf_id];
@@ -1119,7 +1129,6 @@ static void process_write(struct rtrs_srv_con *con,
id->dir = WRITE;
id->msg_id = buf_id;
- usr_len = le16_to_cpu(req->usr_len);
data_len = off - usr_len;
data = page_address(srv->chunks[buf_id]);
ret = ctx->ops.rdma_ev(srv->priv, id, data, data_len,
@@ -1731,21 +1740,16 @@ static int create_con(struct rtrs_srv_path *srv_path,
* All receive and all send (each requiring invalidate)
* + 2 for drain and heartbeat
*/
- max_send_wr = min_t(int, wr_limit,
- SERVICE_CON_QUEUE_DEPTH * 2 + 2);
+ max_send_wr = min(wr_limit, SERVICE_CON_QUEUE_DEPTH * 2 + 2);
max_recv_wr = max_send_wr;
s->signal_interval = min_not_zero(srv->queue_depth,
(size_t)SERVICE_CON_QUEUE_DEPTH);
} else {
/* when always_invlaidate enalbed, we need linv+rinv+mr+imm */
if (always_invalidate)
- max_send_wr =
- min_t(int, wr_limit,
- srv->queue_depth * (1 + 4) + 1);
+ max_send_wr = min(wr_limit, srv->queue_depth * (1 + 4) + 1);
else
- max_send_wr =
- min_t(int, wr_limit,
- srv->queue_depth * (1 + 2) + 1);
+ max_send_wr = min(wr_limit, srv->queue_depth * (1 + 2) + 1);
max_recv_wr = srv->queue_depth + 1;
}
@@ -2385,7 +2389,7 @@ static int __init rtrs_server_init(void)
if (err)
goto out_err;
- rtrs_wq = alloc_workqueue("rtrs_server_wq", 0, 0);
+ rtrs_wq = alloc_workqueue("rtrs_server_wq", WQ_PERCPU, 0);
if (!rtrs_wq) {
err = -ENOMEM;
goto out_dev_class;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 30339dcabb4d..955f36efeebd 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -43,6 +43,7 @@
#include <linux/jiffies.h>
#include <linux/lockdep.h>
#include <linux/inet.h>
+#include <net/net_namespace.h>
#include <rdma/ib_cache.h>
#include <linux/atomic.h>
@@ -556,7 +557,7 @@ static int srp_create_ch_ib(struct srp_rdma_ch *ch)
init_attr->cap.max_send_wr = m * target->queue_size;
init_attr->cap.max_recv_wr = target->queue_size + 1;
init_attr->cap.max_recv_sge = 1;
- init_attr->cap.max_send_sge = min(SRP_MAX_SGE, attr->max_send_sge);
+ init_attr->cap.max_send_sge = min(attr->max_send_sge, SRP_MAX_SGE);
init_attr->sq_sig_type = IB_SIGNAL_REQ_WR;
init_attr->qp_type = IB_QPT_RC;
init_attr->send_cq = send_cq;
@@ -1037,24 +1038,30 @@ static void srp_del_scsi_host_attr(struct Scsi_Host *shost)
static void srp_remove_target(struct srp_target_port *target)
{
+ struct scsi_device *sdev;
struct srp_rdma_ch *ch;
int i;
WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
srp_del_scsi_host_attr(target->scsi_host);
- srp_rport_get(target->rport);
- srp_remove_host(target->scsi_host);
- scsi_remove_host(target->scsi_host);
+ /*
+ * Remove all logical units. This must happen before the
+ * srp_disconnect_target() call because scsi_remove_device() may trigger
+ * submission of SCSI commands. See also sd_shutdown().
+ */
+ shost_for_each_device(sdev, target->scsi_host)
+ scsi_remove_device(sdev);
srp_stop_rport_timers(target->rport);
srp_disconnect_target(target);
- kobj_ns_drop(KOBJ_NS_TYPE_NET, target->net);
+ kobj_ns_drop(KOBJ_NS_TYPE_NET, to_ns_common(target->net));
for (i = 0; i < target->ch_count; i++) {
ch = &target->ch[i];
srp_free_ch_ib(target, ch);
}
cancel_work_sync(&target->tl_err_work);
- srp_rport_put(target->rport);
+ srp_remove_host(target->scsi_host);
+ scsi_remove_host(target->scsi_host);
kfree(target->ch);
target->ch = NULL;
@@ -1931,7 +1938,8 @@ static int srp_post_recv(struct srp_rdma_ch *ch, struct srp_iu *iu)
return ib_post_recv(ch->qp, &wr, NULL);
}
-static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp)
+static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp,
+ u32 byte_len)
{
struct srp_target_port *target = ch->target;
struct srp_request *req;
@@ -1943,7 +1951,8 @@ static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp)
ch->req_lim += be32_to_cpu(rsp->req_lim_delta);
if (rsp->tag == ch->tsk_mgmt_tag) {
ch->tsk_mgmt_status = -1;
- if (be32_to_cpu(rsp->resp_data_len) >= 4)
+ if (be32_to_cpu(rsp->resp_data_len) >= 4 &&
+ byte_len >= sizeof(*rsp) + 4)
ch->tsk_mgmt_status = rsp->data[3];
complete(&ch->tsk_mgmt_done);
} else {
@@ -1972,10 +1981,27 @@ static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp)
scmnd->result = rsp->status;
if (rsp->flags & SRP_RSP_FLAG_SNSVALID) {
- memcpy(scmnd->sense_buffer, rsp->data +
- be32_to_cpu(rsp->resp_data_len),
- min_t(int, be32_to_cpu(rsp->sense_data_len),
- SCSI_SENSE_BUFFERSIZE));
+ u32 resp_len = be32_to_cpu(rsp->resp_data_len);
+ u32 sense_len = be32_to_cpu(rsp->sense_data_len);
+
+ /*
+ * The sense data starts resp_data_len bytes past the
+ * response data area; both lengths come from the
+ * target-controlled response. Copy the sense data
+ * only if it has not been truncated, that is, only if
+ * the full sense region fits within the bytes actually
+ * received. Otherwise the copy source would run past
+ * the receive buffer (sized to the target-chosen
+ * max_ti_iu_len), reading out of bounds.
+ */
+ if (sizeof(*rsp) + (u64)resp_len + sense_len <= byte_len)
+ memcpy(scmnd->sense_buffer,
+ rsp->data + resp_len,
+ min(sense_len, SCSI_SENSE_BUFFERSIZE));
+ else
+ shost_printk(KERN_ERR, target->scsi_host,
+ "dropping truncated sense data (resp_data_len %u sense_data_len %u, %u bytes received)\n",
+ resp_len, sense_len, byte_len);
}
if (unlikely(rsp->flags & SRP_RSP_FLAG_DIUNDER))
@@ -2026,13 +2052,20 @@ static int srp_response_common(struct srp_rdma_ch *ch, s32 req_delta,
}
static void srp_process_cred_req(struct srp_rdma_ch *ch,
- struct srp_cred_req *req)
+ struct srp_cred_req *req, u32 byte_len)
{
- struct srp_cred_rsp rsp = {
- .opcode = SRP_CRED_RSP,
- .tag = req->tag,
- };
- s32 delta = be32_to_cpu(req->req_lim_delta);
+ struct srp_cred_rsp rsp = { .opcode = SRP_CRED_RSP };
+ s32 delta;
+
+ if (byte_len < sizeof(*req)) {
+ shost_printk(KERN_ERR, ch->target->scsi_host, PFX
+ "dropping truncated SRP_CRED_REQ (%u bytes received, %zu expected)\n",
+ byte_len, sizeof(*req));
+ return;
+ }
+
+ rsp.tag = req->tag;
+ delta = be32_to_cpu(req->req_lim_delta);
if (srp_response_common(ch, delta, &rsp, sizeof(rsp)))
shost_printk(KERN_ERR, ch->target->scsi_host, PFX
@@ -2040,14 +2073,21 @@ static void srp_process_cred_req(struct srp_rdma_ch *ch,
}
static void srp_process_aer_req(struct srp_rdma_ch *ch,
- struct srp_aer_req *req)
+ struct srp_aer_req *req, u32 byte_len)
{
struct srp_target_port *target = ch->target;
- struct srp_aer_rsp rsp = {
- .opcode = SRP_AER_RSP,
- .tag = req->tag,
- };
- s32 delta = be32_to_cpu(req->req_lim_delta);
+ struct srp_aer_rsp rsp = { .opcode = SRP_AER_RSP };
+ s32 delta;
+
+ if (byte_len < sizeof(*req)) {
+ shost_printk(KERN_ERR, target->scsi_host, PFX
+ "dropping truncated SRP_AER_REQ (%u bytes received, %zu expected)\n",
+ byte_len, sizeof(*req));
+ return;
+ }
+
+ rsp.tag = req->tag;
+ delta = be32_to_cpu(req->req_lim_delta);
shost_printk(KERN_ERR, target->scsi_host, PFX
"ignoring AER for LUN %llu\n", scsilun_to_int(&req->lun));
@@ -2085,15 +2125,15 @@ static void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc)
switch (opcode) {
case SRP_RSP:
- srp_process_rsp(ch, iu->buf);
+ srp_process_rsp(ch, iu->buf, wc->byte_len);
break;
case SRP_CRED_REQ:
- srp_process_cred_req(ch, iu->buf);
+ srp_process_cred_req(ch, iu->buf, wc->byte_len);
break;
case SRP_AER_REQ:
- srp_process_aer_req(ch, iu->buf);
+ srp_process_aer_req(ch, iu->buf, wc->byte_len);
break;
case SRP_T_LOGOUT:
@@ -3170,10 +3210,24 @@ static struct attribute *srp_class_attrs[];
ATTRIBUTE_GROUPS(srp_class);
+/*
+ * SRP hosts are named after their ib device, so tag the class by the ib
+ * device's net namespace.
+ */
+static const struct ns_common *srp_net_namespace(const struct device *dev)
+{
+ struct srp_host *host = container_of(dev, struct srp_host, dev);
+ struct net *net = rdma_dev_net(host->srp_dev->dev);
+
+ return net ? to_ns_common(net) : NULL;
+}
+
static struct class srp_class = {
.name = "infiniband_srp",
.dev_groups = srp_class_groups,
- .dev_release = srp_release_dev
+ .dev_release = srp_release_dev,
+ .ns_type = &net_ns_type_operations,
+ .namespace = srp_net_namespace,
};
/**
@@ -3713,7 +3767,7 @@ static ssize_t add_target_store(struct device *dev,
target = host_to_target(target_host);
- target->net = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
+ target->net = to_net_ns(kobj_ns_grab_current(KOBJ_NS_TYPE_NET));
target->io_class = SRP_REV16A_IB_IO_CLASS;
target->scsi_host = target_host;
target->srp_host = host;
@@ -3905,7 +3959,7 @@ put:
* earlier in this function.
*/
if (target->state != SRP_TARGET_REMOVED)
- kobj_ns_drop(KOBJ_NS_TYPE_NET, target->net);
+ kobj_ns_drop(KOBJ_NS_TYPE_NET, to_ns_common(target->net));
scsi_host_put(target->scsi_host);
}
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index e00b87acf481..7197d95f2216 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -77,8 +77,8 @@ module_param(srp_max_req_size, int, 0444);
MODULE_PARM_DESC(srp_max_req_size,
"Maximum size of SRP request messages in bytes.");
-static int srpt_srq_size = DEFAULT_SRPT_SRQ_SIZE;
-module_param(srpt_srq_size, int, 0444);
+static unsigned int srpt_srq_size = DEFAULT_SRPT_SRQ_SIZE;
+module_param(srpt_srq_size, uint, 0444);
MODULE_PARM_DESC(srpt_srq_size,
"Shared receive queue (SRQ) size.");
@@ -405,8 +405,7 @@ static void srpt_get_ioc(struct srpt_port *sport, u32 slot,
if (sdev->use_srq)
send_queue_depth = sdev->srq_size;
else
- send_queue_depth = min(MAX_SRPT_RQ_SIZE,
- sdev->device->attrs.max_qp_wr);
+ send_queue_depth = min(sdev->device->attrs.max_qp_wr, MAX_SRPT_RQ_SIZE);
memset(iocp, 0, sizeof(*iocp));
strcpy(iocp->id_string, SRPT_ID_STRING);
@@ -960,6 +959,7 @@ static int srpt_alloc_rw_ctxs(struct srpt_send_ioctx *ioctx,
struct srpt_rdma_ch *ch = ioctx->ch;
struct scatterlist *prev = NULL;
unsigned prev_nents;
+ u8 n_rdma, n_rw_ctx;
int ret, i;
if (nbufs == 1) {
@@ -970,6 +970,9 @@ static int srpt_alloc_rw_ctxs(struct srpt_send_ioctx *ioctx,
return -ENOMEM;
}
+ n_rw_ctx = ioctx->n_rw_ctx;
+ n_rdma = ioctx->n_rdma;
+
for (i = ioctx->n_rw_ctx; i < nbufs; i++, db++) {
struct srpt_rw_ctx *ctx = &ioctx->rw_ctxs[i];
u64 remote_addr = be64_to_cpu(db->va);
@@ -1016,6 +1019,9 @@ unwind:
}
if (ioctx->rw_ctxs != &ioctx->s_rw_ctx)
kfree(ioctx->rw_ctxs);
+ ioctx->rw_ctxs = NULL;
+ ioctx->n_rw_ctx = n_rw_ctx;
+ ioctx->n_rdma = n_rdma;
return ret;
}
@@ -1129,9 +1135,10 @@ static int srpt_get_desc_tbl(struct srpt_recv_ioctx *recv_ioctx,
struct srp_imm_buf *imm_buf = srpt_get_desc_buf(srp_cmd);
void *data = (void *)srp_cmd + imm_data_offset;
uint32_t len = be32_to_cpu(imm_buf->len);
- uint32_t req_size = imm_data_offset + len;
+ uint32_t req_size;
- if (req_size > srp_max_req_size) {
+ if (check_add_overflow((uint32_t)imm_data_offset, len, &req_size) ||
+ req_size > srp_max_req_size) {
pr_err("Immediate data (length %d + %d) exceeds request size %d\n",
imm_data_offset, len, srp_max_req_size);
return -EINVAL;
@@ -1595,7 +1602,7 @@ static void srpt_handle_cmd(struct srpt_rdma_ch *ch,
rc = target_init_cmd(cmd, ch->sess, &send_ioctx->sense_data[0],
scsilun_to_int(&srp_cmd->lun), data_len,
- TCM_SIMPLE_TAG, dir, TARGET_SCF_ACK_KREF);
+ cmd->sam_task_attr, dir, TARGET_SCF_ACK_KREF);
if (rc != 0) {
pr_debug("target_submit_cmd() returned %d for tag %#llx\n", rc,
srp_cmd->tag);
@@ -1850,7 +1857,7 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
struct srpt_port *sport = ch->sport;
struct srpt_device *sdev = sport->sdev;
const struct ib_device_attr *attrs = &sdev->device->attrs;
- int sq_size = sport->port_attrib.srp_sq_size;
+ u32 sq_size = sport->port_attrib.srp_sq_size;
int i, ret;
WARN_ON(ch->rq_size < 1);
@@ -1911,13 +1918,13 @@ retry:
bool retry = sq_size > MIN_SRPT_SQ_SIZE;
if (retry) {
- pr_debug("failed to create queue pair with sq_size = %d (%d) - retrying\n",
+ pr_debug("failed to create queue pair with sq_size = %u (%d) - retrying\n",
sq_size, ret);
ib_cq_pool_put(ch->cq, ch->cq_size);
sq_size = max(sq_size / 2, MIN_SRPT_SQ_SIZE);
goto retry;
} else {
- pr_err("failed to create queue pair with sq_size = %d (%d)\n",
+ pr_err("failed to create queue pair with sq_size = %u (%d)\n",
sq_size, ret);
goto err_destroy_cq;
}
@@ -1925,7 +1932,7 @@ retry:
atomic_set(&ch->sq_wr_avail, qp_init->cap.max_send_wr);
- pr_debug("%s: max_cqe= %d max_sge= %d sq_size = %d ch= %p\n",
+ pr_debug("%s: max_cqe= %d max_sge= %d sq_size = %u ch= %p\n",
__func__, ch->cq->cqe, qp_init->cap.max_send_sge,
qp_init->cap.max_send_wr, ch);
@@ -2298,7 +2305,7 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev,
* depth to avoid that the initiator driver has to report QUEUE_FULL
* to the SCSI mid-layer.
*/
- ch->rq_size = min(MAX_SRPT_RQ_SIZE, sdev->device->attrs.max_qp_wr);
+ ch->rq_size = min(sdev->device->attrs.max_qp_wr, MAX_SRPT_RQ_SIZE);
spin_lock_init(&ch->spinlock);
ch->state = CH_CONNECTING;
INIT_LIST_HEAD(&ch->cmd_wait_list);
@@ -3136,7 +3143,7 @@ static int srpt_alloc_srq(struct srpt_device *sdev)
return PTR_ERR(srq);
}
- pr_debug("create SRQ #wr= %d max_allow=%d dev= %s\n", sdev->srq_size,
+ pr_debug("create SRQ #wr= %d max_allow=%u dev= %s\n", sdev->srq_size,
sdev->device->attrs.max_srq_wr, dev_name(&device->dev));
sdev->req_buf_cache = srpt_cache_get(srp_max_req_size);
@@ -3925,6 +3932,7 @@ static const struct target_core_fabric_ops srpt_template = {
.tfc_wwn_attrs = srpt_wwn_attrs,
.tfc_tpg_attrib_attrs = srpt_tpg_attrib_attrs,
+ .default_compl_type = TARGET_QUEUE_COMPL,
.default_submit_type = TARGET_DIRECT_SUBMIT,
.direct_submit_supp = 1,
};
@@ -3950,7 +3958,7 @@ static int __init srpt_init_module(void)
if (srpt_srq_size < MIN_SRPT_SRQ_SIZE
|| srpt_srq_size > MAX_SRPT_SRQ_SIZE) {
- pr_err("invalid value %d for kernel module parameter srpt_srq_size -- must be in the range [%d..%d].\n",
+ pr_err("invalid value %u for kernel module parameter srpt_srq_size -- must be in the range [%d..%d].\n",
srpt_srq_size, MIN_SRPT_SRQ_SIZE, MAX_SRPT_SRQ_SIZE);
goto out;
}