Unverified Commit 4c305bd4 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!7062 [openEuler-22.03-SP4]drivers: support Yunsilicon's metaScale/metaVisor series NICs

Merge Pull Request from: @OGman 
 
1. Support for metaScale/metaVisor series network cards
2. ethtool feature completion
3. Code optimization 
 
Link:https://gitee.com/openeuler/kernel/pulls/7062

 

Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents 77ea0bd5 8474501e
Loading
Loading
Loading
Loading
+0 −21
Original line number Diff line number Diff line
@@ -7,7 +7,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/random.h>
#include <rdma/ib_cache.h>

#include "xsc_ib.h"
#include "user.h"
@@ -119,26 +118,6 @@ xsc_ib_create_ah_def()

int xsc_ib_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr)
{
//	struct xsc_ib_ah *ah = to_mah(ibah);
//	u32 tmp;

//	pr_err("[%s:%d]", __func__, __LINE__);

//	memset(ah_attr, 0, sizeof(*ah_attr));

//	tmp = be32_to_cpu(ah->av.grh_gid_fl);
//	if (tmp & (1 << 30)) {
//		ah_attr->ah_flags = IB_AH_GRH;
//		ah_attr->grh.sgid_index = (tmp >> 20) & 0xff;
//		ah_attr->grh.flow_label = tmp & 0xfffff;
//		memcpy(&ah_attr->grh.dgid, ah->av.rgid, 16);
//		ah_attr->grh.hop_limit = ah->av.hop_limit;
//		ah_attr->grh.traffic_class = ah->av.tclass;
//	}
//	ah_attr->dlid = be16_to_cpu(ah->av.rlid);
//	ah_attr->static_rate = ah->av.stat_rate_sl >> 4;
//	ah_attr->sl = ah->av.stat_rate_sl & 0xf;

	return 0;
}

+34 −17
Original line number Diff line number Diff line
@@ -120,12 +120,12 @@ static void *get_cqe(struct xsc_ib_cq *cq, int n)

static void *get_sw_cqe(struct xsc_ib_cq *cq, int n)
{
	struct xsc_cqe64 *cqe64;
	struct xsc_cqe *cqe;

	cqe64 = (struct xsc_cqe64 *)get_cqe(cq, n & cq->ibcq.cqe);
	cqe = (struct xsc_cqe *)get_cqe(cq, n & (cq->ibcq.cqe - 1));

	return ((cqe64->owner & XSC_CQE_OWNER_MASK) ^
		!!(n & (cq->ibcq.cqe + 1))) ? NULL : cqe64;
	return ((cqe->owner & XSC_CQE_OWNER_MASK) ^
		!!(n & cq->ibcq.cqe)) ? NULL : cqe;
}

static inline void handle_good_req(struct ib_wc *wc,
@@ -198,6 +198,7 @@ static void xsc_handle_rdma_mad_resp_recv(struct xsc_ib_cq *cq,
	void *recv;
	struct xsc_wqe_data_seg *data_seg;
	struct iphdr *ip4h = NULL;
	struct ipv6hdr *ip6h;
	struct udphdr *udph;
	struct ib_unpacked_eth *eth;
	struct ib_unpacked_vlan *vlan;
@@ -208,6 +209,8 @@ static void xsc_handle_rdma_mad_resp_recv(struct xsc_ib_cq *cq,
	unsigned int pading_sz = 0;
	struct xsc_ib_wq *wq;
	int idx;
	u16 eth_type;
	void *l3_start;

	wq = &(*cur_qp)->rq;
	idx = wq->tail & (wq->wqe_cnt - 1);
@@ -221,23 +224,36 @@ static void xsc_handle_rdma_mad_resp_recv(struct xsc_ib_cq *cq,
	grh = (struct ib_grh *)recv;
	if (eth->type == htons(ETH_P_8021Q)) {
		vlan = (struct ib_unpacked_vlan *)(eth + 1);
		ip4h = (struct iphdr *)(vlan + 1);
		eth_type = ntohs(vlan->type);
		l3_start = vlan + 1;

		wc->vlan_id = ntohs(vlan->tag) & 0x0fff;
		wc->sl = (ntohs(vlan->tag) >> 13) & 0x7;
		wc->wc_flags |= IB_WC_WITH_VLAN;
	} else {
		ip4h = (struct iphdr *)(eth + 1);
		eth_type = ntohs(eth->type);
		l3_start = eth + 1;
	}

	if (eth_type == ETH_P_IP) {
		ip4h = (struct iphdr *)l3_start;
		udph = (struct udphdr *)(ip4h + 1);
	} else {
		ip6h = (struct ipv6hdr *)l3_start;
		udph = (struct udphdr *)(ip6h + 1);
	}
	bth = (struct rxe_bth *)(udph + 1);
	deth = (struct rxe_deth *)(bth + 1);
	mad = (struct ib_mad *)(deth + 1);

	memcpy(grh + 1, mad, sizeof(*mad));
	if (eth_type == ETH_P_IP) {
		pading_sz = sizeof(*grh) - sizeof(*ip4h);
		memmove((u8 *)(grh + 1) - sizeof(*ip4h), ip4h, sizeof(*ip4h));
		memset(grh, 0, pading_sz);
	} else {
		memmove(grh, ip6h, sizeof(*ip6h));
	}
	memmove(grh + 1, mad, sizeof(*mad));

	wc->wc_flags |= IB_WC_GRH;

@@ -543,7 +559,7 @@ xsc_ib_create_cq_def()
	int err;
	unsigned int eqn;

	entries = roundup_pow_of_two(entries + 1);
	entries = roundup_pow_of_two(entries);

	xsc_ib_dbg(dev, "entries:%d, vector:%d, max_cqes:%d\n", entries, vector,
		   dev->xdev->caps.max_cqes);
@@ -551,7 +567,7 @@ xsc_ib_create_cq_def()
	if (entries > dev->xdev->caps.max_cqes)
		entries = dev->xdev->caps.max_cqes;
	cq = to_xcq(ibcq);
	cq->ibcq.cqe = entries - 1;
	cq->ibcq.cqe = entries;
	mutex_init(&cq->resize_mutex);
	spin_lock_init(&cq->lock);
	cq->resize_buf = NULL;
@@ -628,7 +644,7 @@ xsc_ib_destroy_cq_def()
	return 0;
}

static int is_equal_rsn(struct xsc_cqe64 *cqe, u32 rsn)
static int is_equal_rsn(struct xsc_cqe *cqe, u32 rsn)
{
	u32 qpn = le32_to_cpu(cqe->qp_id);
	return rsn == qpn;
@@ -636,7 +652,7 @@ static int is_equal_rsn(struct xsc_cqe64 *cqe, u32 rsn)

void __xsc_ib_cq_clean(struct xsc_ib_cq *cq, u32 rsn)
{
	struct xsc_cqe64 *cqe, *dest;
	struct xsc_cqe *cqe, *dest;
	u32 prod_index;
	int nfreed = 0;
	u8 owner_bit;
@@ -658,11 +674,12 @@ void __xsc_ib_cq_clean(struct xsc_ib_cq *cq, u32 rsn)
	 * that match our QP by copying older entries on top of them.
	 */
	while ((int)(--prod_index) - (int)cq->xcq.cons_index >= 0) {
		cqe = get_cqe(cq, prod_index & cq->ibcq.cqe);
		cqe = (struct xsc_cqe *)get_cqe(cq, prod_index & (cq->ibcq.cqe - 1));
		if (is_equal_rsn(cqe, rsn)) {
			++nfreed;
		} else if (nfreed) {
			dest = get_cqe(cq, (prod_index + nfreed) & cq->ibcq.cqe);
			dest = (struct xsc_cqe *)get_cqe(cq, (prod_index + nfreed) &
							 (cq->ibcq.cqe - 1));
			owner_bit = dest->owner & XSC_CQE_OWNER_MASK;
			memcpy(dest, cqe, cq->xcq.cqe_sz);
			dest->owner = owner_bit |
+75 −25
Original line number Diff line number Diff line
@@ -12,10 +12,13 @@
#include <linux/slab.h>
#include <linux/io-mapping.h>
#include <linux/sched.h>
#include <linux/netdevice.h>
#include <net/bonding.h>
#include "common/xsc_core.h"
#include "common/xsc_hsi.h"
#include "common/xsc_cmd.h"
#include "common/driver.h"
#include "common/xsc_lag.h"

#include <rdma/ib_user_verbs.h>
#include <rdma/ib_smi.h>
@@ -113,7 +116,7 @@ static int xsc_ib_query_device(struct ib_device *ibdev,
	props->page_size_cap	   = dev->xdev->caps.min_page_sz;
	props->max_mr_size	   = (1 << dev->xdev->caps.log_max_mtt) * PAGE_SIZE;
	props->max_qp		   = 1 << dev->xdev->caps.log_max_qp;
	props->max_qp_wr	   = dev->xdev->caps.max_wqes;
	props->max_qp_wr	   = (32 * 1024); /* hack for GPFS */
	max_rq_sg = dev->xdev->caps.max_rq_desc_sz / sizeof(struct xsc_wqe_data_seg);
	max_sq_sg = (dev->xdev->caps.max_sq_desc_sz - sizeof(struct xsc_wqe_ctrl_seg_2)) /
		sizeof(struct xsc_wqe_data_seg_2);
@@ -207,6 +210,57 @@ static int xsc_ib_query_device(struct ib_device *ibdev,
	return 0;
}

void xsc_calc_link_info(struct xsc_core_device *xdev,
			struct ib_port_attr *props)
{
	switch (xsc_get_link_speed(xdev)) {
	case MODULE_SPEED_10G:
		props->active_speed = XSC_RDMA_LINK_SPEED_10GB;
		props->active_width = 1;
		break;
	case MODULE_SPEED_25G:
		props->active_speed = XSC_RDMA_LINK_SPEED_25GB;
		props->active_width = 1;
		break;
	case MODULE_SPEED_40G_R4:
		props->active_speed = XSC_RDMA_LINK_SPEED_10GB;
		props->active_width = 2;
		break;
	case MODULE_SPEED_50G_R:
		props->active_speed = XSC_RDMA_LINK_SPEED_50GB;
		props->active_width = 1;
		break;
	case MODULE_SPEED_50G_R2:
		props->active_speed = XSC_RDMA_LINK_SPEED_50GB;
		props->active_width = 1;
		break;
	case MODULE_SPEED_100G_R2:
		props->active_speed = XSC_RDMA_LINK_SPEED_25GB;
		props->active_width = 2;
		break;
	case MODULE_SPEED_100G_R4:
		props->active_speed = XSC_RDMA_LINK_SPEED_25GB;
		props->active_width = 2;
		break;
	case MODULE_SPEED_200G_R4:
		props->active_speed = XSC_RDMA_LINK_SPEED_50GB;
		props->active_width = 2;
		break;
	case MODULE_SPEED_200G_R8:
		props->active_speed = XSC_RDMA_LINK_SPEED_25GB;
		props->active_width = 4;
		break;
	case MODULE_SPEED_400G_R8:
		props->active_speed = XSC_RDMA_LINK_SPEED_50GB;
		props->active_width = 4;
		break;
	default:
		props->active_speed = XSC_RDMA_LINK_SPEED_25GB;
		props->active_width = 1;
		break;
	}
}

static enum rdma_link_layer xsc_ib_port_link_layer(struct ib_device *ibdev, u8 port)
{
	return IB_LINK_LAYER_ETHERNET;
@@ -246,11 +300,7 @@ int xsc_ib_query_port(struct ib_device *ibdev, u8 port,
		props->active_width = 1;
		props->active_speed = XSC_RDMA_LINK_SPEED_25GB;
	} else {
		if (xsc_get_link_speed(xdev) == XSC_CMD_RESP_LINKSPEED_MODE_100G)
			props->active_width = 2;
		else
			props->active_width = 1;
		props->active_speed = XSC_RDMA_LINK_SPEED_25GB;
		xsc_calc_link_info(xdev, props);
	}

	props->phys_state = netif_carrier_ok(ndev) ? XSC_RDMA_PHY_STATE_LINK_UP :
@@ -560,14 +610,27 @@ static void _xsc_get_netdev(struct xsc_ib_dev *dev)

static struct net_device *xsc_get_netdev(struct ib_device *ibdev, u8 port_num)
{
	struct xsc_ib_dev *dev = to_mdev(ibdev);
	struct net_device *netdev = dev->netdev;
	struct xsc_ib_dev *xsc_ib_dev = to_mdev(ibdev);
	struct net_device *dev = xsc_ib_dev->netdev;

	rcu_read_lock();
	if (netdev)
		dev_hold(netdev);
	if (dev) {
		if (xsc_ib_dev->xdev->priv.lag && __xsc_lag_is_active(xsc_ib_dev->xdev->priv.lag)) {
			struct net_device *upper = NULL;

			upper = netdev_master_upper_dev_get_rcu(dev);
			if (upper) {
				struct net_device *active;

				active = bond_option_active_slave_get_rcu(netdev_priv(upper));
				if (active)
					dev = active;
			}
		}
		dev_hold(dev);
	}
	rcu_read_unlock();
	return netdev;
	return dev;
}

void xsc_get_guid(u8 *dev_addr, u8 *guid)
@@ -837,23 +900,11 @@ static int init_one(struct xsc_core_device *xdev,
	err = get_port_caps(dev);
	if (err)
		goto err_free;
//
//	get_ext_port_caps(dev);
//
//	err = alloc_comp_eqs(dev);
//	if (err)
//		goto err_cleanup;
//
//	XSC_INIT_DOORBELL_LOCK(&dev->uar_lock);
	if (!xdev->caps.msix_enable)
		dev->num_comp_vectors = 1;
	else
		dev->num_comp_vectors = xdev->dev_res->eq_table.num_comp_vectors;

//	dev->ib_dev.dev.dma_ops = &dma_virt_ops;
//	dma_coerce_mask_and_coherent(&dev->ib_dev.dev,
//				     dma_get_required_mask(&dev->ib_dev.dev));

	strlcpy(dev->ib_dev.name, "xscale_%d", IB_DEVICE_NAME_MAX);
	dev->ib_dev.node_type		= RDMA_NODE_IB_CA;
	dev->ib_dev.local_dma_lkey	= 0xFF;
@@ -916,6 +967,7 @@ static int init_one(struct xsc_core_device *xdev,
	if (ib_register_device(&dev->ib_dev, dev->ib_dev.name, dev->xdev->device))
		goto err_rsrc;

	rdma_roce_rescan_device(&dev->ib_dev);
	dev->ib_active = true;
	*m_ibdev = dev;

@@ -966,7 +1018,6 @@ static void *xsc_add(struct xsc_core_device *xpdev)
		return NULL;
	}

	xpdev->rdma_ready = 1;
	return m_ibdev;
}

@@ -974,7 +1025,6 @@ static void xsc_remove(struct xsc_core_device *xpdev, void *context)
{
	pr_err("remove rdma driver\n");
	remove_one(xpdev, context);
	xpdev->rdma_ready = 0;
}

static struct xsc_interface xsc_interface = {
+3 −4
Original line number Diff line number Diff line
@@ -102,7 +102,7 @@ int xsc_find_best_pgsz(struct ib_umem *umem,

		if (pa == chunk->pa + chunk->length) {
			chunk->length += sg_dma_len(sg);
			va += chunk->length;
			va += sg_dma_len(sg);
		} else {
			chunk = kzalloc(sizeof(*chunk), GFP_KERNEL);
			if (!chunk) {
@@ -135,7 +135,7 @@ int xsc_find_best_pgsz(struct ib_umem *umem,

	if (chunk_cnt == 1) {
		list_for_each_entry(chunk, &chunk_list, list) {
			mask = GENMASK(*shift - 1, min_t(int, page_shift, *shift - 1));
			mask = GENMASK(*shift - 1, min_t(int, page_shift, *shift));
			*npages += DIV_ROUND_UP(chunk->length + (virt & mask), pgsz);
			*pas = vmalloc(*npages * sizeof(u64));
			if (!*pas) {
@@ -165,7 +165,7 @@ int xsc_find_best_pgsz(struct ib_umem *umem,
			for (i = 0; i < chunk_npages; i++) {
				if (pa_index == 0) {
					mask = GENMASK(*shift - 1,
						       min_t(int, page_shift, *shift - 1));
						       min_t(int, page_shift, *shift));
					chunk_pa -= (virt & mask);
				}
				(*pas)[pa_index] = chunk_pa + i * pgsz;
@@ -202,7 +202,6 @@ void __xsc_ib_cont_pages(struct ib_umem *umem, u64 addr,
	int i = 0;
	struct scatterlist *sg;
	int entry;
	// TODO: need peer mem support
	unsigned long page_shift = PAGE_SHIFT;

	addr = addr >> page_shift;
+1 −3
Original line number Diff line number Diff line
@@ -188,6 +188,7 @@ struct ib_mr *xsc_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
		if (err)
			goto error;
		using_peer_mem = 1;

	} else {
		umem_ex = ib_umem_ex(umem);
		if (IS_ERR(umem_ex)) {
@@ -266,7 +267,6 @@ xsc_ib_dereg_mr_def()
		kfree(mr);
		return 0;
	}
	//printk("%s %d\n", __func__, __LINE__);
	if (mr->npages) {
		err = xsc_core_dereg_mr(dev->xdev, &mr->mmr);
		if (err) {
@@ -275,7 +275,6 @@ xsc_ib_dereg_mr_def()
			return err;
		}
	}
	//printk("%s %d\n", __func__, __LINE__);
	err = xsc_core_destroy_mkey(dev->xdev, &mr->mmr);
	if (err) {
		xsc_ib_warn(dev, "failed to destroy mkey 0x%x (%d)\n",
@@ -410,7 +409,6 @@ int xsc_wr_invalidate_mr(struct xsc_ib_dev *dev, const struct ib_send_wr *wr)
	if (!wr)
		return -1;
	mr.key = wr->ex.invalidate_rkey;
	//printk("%s %d key:0x%x\n", __func__, __LINE__, mr.key);
	err = xsc_core_dereg_mr(dev->xdev, &mr);
	return err;
}
Loading