cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ipoib_main.c (6054B)


      1// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
      2/*
      3 * Copyright(c) 2020 Intel Corporation.
      4 *
      5 */
      6
      7/*
      8 * This file contains HFI1 support for ipoib functionality
      9 */
     10
     11#include "ipoib.h"
     12#include "hfi.h"
     13
     14static u32 qpn_from_mac(const u8 *mac_arr)
     15{
     16	return (u32)mac_arr[1] << 16 | mac_arr[2] << 8 | mac_arr[3];
     17}
     18
     19static int hfi1_ipoib_dev_init(struct net_device *dev)
     20{
     21	struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
     22	int ret;
     23
     24	dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
     25	if (!dev->tstats)
     26		return -ENOMEM;
     27
     28	ret = priv->netdev_ops->ndo_init(dev);
     29	if (ret)
     30		goto out_ret;
     31
     32	ret = hfi1_netdev_add_data(priv->dd,
     33				   qpn_from_mac(priv->netdev->dev_addr),
     34				   dev);
     35	if (ret < 0) {
     36		priv->netdev_ops->ndo_uninit(dev);
     37		goto out_ret;
     38	}
     39
     40	return 0;
     41out_ret:
     42	free_percpu(dev->tstats);
     43	dev->tstats = NULL;
     44	return ret;
     45}
     46
     47static void hfi1_ipoib_dev_uninit(struct net_device *dev)
     48{
     49	struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
     50
     51	free_percpu(dev->tstats);
     52	dev->tstats = NULL;
     53
     54	hfi1_netdev_remove_data(priv->dd, qpn_from_mac(priv->netdev->dev_addr));
     55
     56	priv->netdev_ops->ndo_uninit(dev);
     57}
     58
     59static int hfi1_ipoib_dev_open(struct net_device *dev)
     60{
     61	struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
     62	int ret;
     63
     64	ret = priv->netdev_ops->ndo_open(dev);
     65	if (!ret) {
     66		struct hfi1_ibport *ibp = to_iport(priv->device,
     67						   priv->port_num);
     68		struct rvt_qp *qp;
     69		u32 qpn = qpn_from_mac(priv->netdev->dev_addr);
     70
     71		rcu_read_lock();
     72		qp = rvt_lookup_qpn(ib_to_rvt(priv->device), &ibp->rvp, qpn);
     73		if (!qp) {
     74			rcu_read_unlock();
     75			priv->netdev_ops->ndo_stop(dev);
     76			return -EINVAL;
     77		}
     78		rvt_get_qp(qp);
     79		priv->qp = qp;
     80		rcu_read_unlock();
     81
     82		hfi1_netdev_enable_queues(priv->dd);
     83		hfi1_ipoib_napi_tx_enable(dev);
     84	}
     85
     86	return ret;
     87}
     88
     89static int hfi1_ipoib_dev_stop(struct net_device *dev)
     90{
     91	struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
     92
     93	if (!priv->qp)
     94		return 0;
     95
     96	hfi1_ipoib_napi_tx_disable(dev);
     97	hfi1_netdev_disable_queues(priv->dd);
     98
     99	rvt_put_qp(priv->qp);
    100	priv->qp = NULL;
    101
    102	return priv->netdev_ops->ndo_stop(dev);
    103}
    104
    105static const struct net_device_ops hfi1_ipoib_netdev_ops = {
    106	.ndo_init         = hfi1_ipoib_dev_init,
    107	.ndo_uninit       = hfi1_ipoib_dev_uninit,
    108	.ndo_open         = hfi1_ipoib_dev_open,
    109	.ndo_stop         = hfi1_ipoib_dev_stop,
    110	.ndo_get_stats64  = dev_get_tstats64,
    111};
    112
    113static int hfi1_ipoib_mcast_attach(struct net_device *dev,
    114				   struct ib_device *device,
    115				   union ib_gid *mgid,
    116				   u16 mlid,
    117				   int set_qkey,
    118				   u32 qkey)
    119{
    120	struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
    121	u32 qpn = (u32)qpn_from_mac(priv->netdev->dev_addr);
    122	struct hfi1_ibport *ibp = to_iport(priv->device, priv->port_num);
    123	struct rvt_qp *qp;
    124	int ret = -EINVAL;
    125
    126	rcu_read_lock();
    127
    128	qp = rvt_lookup_qpn(ib_to_rvt(priv->device), &ibp->rvp, qpn);
    129	if (qp) {
    130		rvt_get_qp(qp);
    131		rcu_read_unlock();
    132		if (set_qkey)
    133			priv->qkey = qkey;
    134
    135		/* attach QP to multicast group */
    136		ret = ib_attach_mcast(&qp->ibqp, mgid, mlid);
    137		rvt_put_qp(qp);
    138	} else {
    139		rcu_read_unlock();
    140	}
    141
    142	return ret;
    143}
    144
    145static int hfi1_ipoib_mcast_detach(struct net_device *dev,
    146				   struct ib_device *device,
    147				   union ib_gid *mgid,
    148				   u16 mlid)
    149{
    150	struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
    151	u32 qpn = (u32)qpn_from_mac(priv->netdev->dev_addr);
    152	struct hfi1_ibport *ibp = to_iport(priv->device, priv->port_num);
    153	struct rvt_qp *qp;
    154	int ret = -EINVAL;
    155
    156	rcu_read_lock();
    157
    158	qp = rvt_lookup_qpn(ib_to_rvt(priv->device), &ibp->rvp, qpn);
    159	if (qp) {
    160		rvt_get_qp(qp);
    161		rcu_read_unlock();
    162		ret = ib_detach_mcast(&qp->ibqp, mgid, mlid);
    163		rvt_put_qp(qp);
    164	} else {
    165		rcu_read_unlock();
    166	}
    167	return ret;
    168}
    169
    170static void hfi1_ipoib_netdev_dtor(struct net_device *dev)
    171{
    172	struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
    173
    174	hfi1_ipoib_txreq_deinit(priv);
    175	hfi1_ipoib_rxq_deinit(priv->netdev);
    176
    177	free_percpu(dev->tstats);
    178	dev->tstats = NULL;
    179}
    180
    181static void hfi1_ipoib_set_id(struct net_device *dev, int id)
    182{
    183	struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
    184
    185	priv->pkey_index = (u16)id;
    186	ib_query_pkey(priv->device,
    187		      priv->port_num,
    188		      priv->pkey_index,
    189		      &priv->pkey);
    190}
    191
    192static int hfi1_ipoib_setup_rn(struct ib_device *device,
    193			       u32 port_num,
    194			       struct net_device *netdev,
    195			       void *param)
    196{
    197	struct hfi1_devdata *dd = dd_from_ibdev(device);
    198	struct rdma_netdev *rn = netdev_priv(netdev);
    199	struct hfi1_ipoib_dev_priv *priv;
    200	int rc;
    201
    202	rn->send = hfi1_ipoib_send;
    203	rn->tx_timeout = hfi1_ipoib_tx_timeout;
    204	rn->attach_mcast = hfi1_ipoib_mcast_attach;
    205	rn->detach_mcast = hfi1_ipoib_mcast_detach;
    206	rn->set_id = hfi1_ipoib_set_id;
    207	rn->hca = device;
    208	rn->port_num = port_num;
    209	rn->mtu = netdev->mtu;
    210
    211	priv = hfi1_ipoib_priv(netdev);
    212	priv->dd = dd;
    213	priv->netdev = netdev;
    214	priv->device = device;
    215	priv->port_num = port_num;
    216	priv->netdev_ops = netdev->netdev_ops;
    217
    218	ib_query_pkey(device, port_num, priv->pkey_index, &priv->pkey);
    219
    220	rc = hfi1_ipoib_txreq_init(priv);
    221	if (rc) {
    222		dd_dev_err(dd, "IPoIB netdev TX init - failed(%d)\n", rc);
    223		return rc;
    224	}
    225
    226	rc = hfi1_ipoib_rxq_init(netdev);
    227	if (rc) {
    228		dd_dev_err(dd, "IPoIB netdev RX init - failed(%d)\n", rc);
    229		hfi1_ipoib_txreq_deinit(priv);
    230		return rc;
    231	}
    232
    233	netdev->netdev_ops = &hfi1_ipoib_netdev_ops;
    234
    235	netdev->priv_destructor = hfi1_ipoib_netdev_dtor;
    236	netdev->needs_free_netdev = true;
    237
    238	return 0;
    239}
    240
    241int hfi1_ipoib_rn_get_params(struct ib_device *device,
    242			     u32 port_num,
    243			     enum rdma_netdev_t type,
    244			     struct rdma_netdev_alloc_params *params)
    245{
    246	struct hfi1_devdata *dd = dd_from_ibdev(device);
    247
    248	if (type != RDMA_NETDEV_IPOIB)
    249		return -EOPNOTSUPP;
    250
    251	if (!HFI1_CAP_IS_KSET(AIP) || !dd->num_netdev_contexts)
    252		return -EOPNOTSUPP;
    253
    254	if (!port_num || port_num > dd->num_pports)
    255		return -EINVAL;
    256
    257	params->sizeof_priv = sizeof(struct hfi1_ipoib_rdma_netdev);
    258	params->txqs = dd->num_sdma;
    259	params->rxqs = dd->num_netdev_contexts;
    260	params->param = NULL;
    261	params->initialize_rdma_netdev = hfi1_ipoib_setup_rn;
    262
    263	return 0;
    264}