Beispiel #1
0
static int rvu_map_cgx_lmac_pf(struct rvu *rvu)
{
	struct npc_pkind *pkind = &rvu->hw->pkind;
	int cgx_cnt_max = rvu->cgx_cnt_max;
	int cgx, lmac_cnt, lmac;
	int pf = PF_CGXMAP_BASE;
	int size, free_pkind;

	if (!cgx_cnt_max)
		return 0;

	if (cgx_cnt_max > 0xF || MAX_LMAC_PER_CGX > 0xF)
		return -EINVAL;

	/* Alloc map table
	 * An additional entry is required since PF id starts from 1 and
	 * hence entry at offset 0 is invalid.
	 */
	size = (cgx_cnt_max * MAX_LMAC_PER_CGX + 1) * sizeof(u8);
	rvu->pf2cgxlmac_map = devm_kmalloc(rvu->dev, size, GFP_KERNEL);
	if (!rvu->pf2cgxlmac_map)
		return -ENOMEM;

	/* Initialize all entries with an invalid cgx and lmac id */
	memset(rvu->pf2cgxlmac_map, 0xFF, size);

	/* Reverse map table */
	rvu->cgxlmac2pf_map = devm_kzalloc(rvu->dev,
				  cgx_cnt_max * MAX_LMAC_PER_CGX * sizeof(u16),
				  GFP_KERNEL);
	if (!rvu->cgxlmac2pf_map)
		return -ENOMEM;

	rvu->cgx_mapped_pfs = 0;
	for (cgx = 0; cgx < cgx_cnt_max; cgx++) {
		if (!rvu_cgx_pdata(cgx, rvu))
			continue;
		lmac_cnt = cgx_get_lmac_cnt(rvu_cgx_pdata(cgx, rvu));
		for (lmac = 0; lmac < lmac_cnt; lmac++, pf++) {
			rvu->pf2cgxlmac_map[pf] = cgxlmac_id_to_bmap(cgx, lmac);
			rvu->cgxlmac2pf_map[CGX_OFFSET(cgx) + lmac] = 1 << pf;
			free_pkind = rvu_alloc_rsrc(&pkind->rsrc);
			pkind->pfchan_map[free_pkind] = ((pf) & 0x3F) << 16;
			rvu->cgx_mapped_pfs++;
		}
	}
	return 0;
}
Beispiel #2
0
static void cgx_lmac_event_handler_init(struct rvu *rvu)
{
	struct cgx_event_cb cb;
	int cgx, lmac, err;
	void *cgxd;

	spin_lock_init(&rvu->cgx_evq_lock);
	INIT_LIST_HEAD(&rvu->cgx_evq_head);
	INIT_WORK(&rvu->cgx_evh_work, cgx_evhandler_task);
	rvu->cgx_evh_wq = alloc_workqueue("rvu_evh_wq", 0, 0);
	if (!rvu->cgx_evh_wq) {
		dev_err(rvu->dev, "alloc workqueue failed");
		return;
	}

	cb.notify_link_chg = cgx_lmac_postevent; /* link change call back */
	cb.data = rvu;

	for (cgx = 0; cgx < rvu->cgx_cnt; cgx++) {
		cgxd = rvu_cgx_pdata(cgx, rvu);
		for (lmac = 0; lmac < cgx_get_lmac_cnt(cgxd); lmac++) {
			err = cgx_lmac_evh_register(&cb, cgxd, lmac);
			if (err)
				dev_err(rvu->dev,
					"%d:%d handler register failed\n",
					cgx, lmac);
		}
	}
}
Beispiel #3
0
static int rvu_cgx_send_link_info(int cgx_id, int lmac_id, struct rvu *rvu)
{
	struct cgx_evq_entry *qentry;
	unsigned long flags;
	int err;

	qentry = kmalloc(sizeof(*qentry), GFP_KERNEL);
	if (!qentry)
		return -ENOMEM;

	/* Lock the event queue before we read the local link status */
	spin_lock_irqsave(&rvu->cgx_evq_lock, flags);
	err = cgx_get_link_info(rvu_cgx_pdata(cgx_id, rvu), lmac_id,
				&qentry->link_event.link_uinfo);
	qentry->link_event.cgx_id = cgx_id;
	qentry->link_event.lmac_id = lmac_id;
	if (err)
		goto skip_add;
	list_add_tail(&qentry->evq_node, &rvu->cgx_evq_head);
skip_add:
	spin_unlock_irqrestore(&rvu->cgx_evq_lock, flags);

	/* start worker to process the events */
	queue_work(rvu->cgx_evh_wq, &rvu->cgx_evh_work);

	return 0;
}
Beispiel #4
0
int rvu_cgx_init(struct rvu *rvu)
{
	int cgx, err;
	void *cgxd;

	/* CGX port id starts from 0 and are not necessarily contiguous
	 * Hence we allocate resources based on the maximum port id value.
	 */
	rvu->cgx_cnt_max = cgx_get_cgxcnt_max();
	if (!rvu->cgx_cnt_max) {
		dev_info(rvu->dev, "No CGX devices found!\n");
		return -ENODEV;
	}

	rvu->cgx_idmap = devm_kzalloc(rvu->dev, rvu->cgx_cnt_max *
				      sizeof(void *), GFP_KERNEL);
	if (!rvu->cgx_idmap)
		return -ENOMEM;

	/* Initialize the cgxdata table */
	for (cgx = 0; cgx < rvu->cgx_cnt_max; cgx++)
		rvu->cgx_idmap[cgx] = cgx_get_pdata(cgx);

	/* Map CGX LMAC interfaces to RVU PFs */
	err = rvu_map_cgx_lmac_pf(rvu);
	if (err)
		return err;

	/* Register for CGX events */
	err = cgx_lmac_event_handler_init(rvu);
	if (err)
		return err;

	/* Ensure event handler registration is completed, before
	 * we turn on the links
	 */
	mb();

	/* Do link up for all CGX ports */
	for (cgx = 0; cgx <= rvu->cgx_cnt_max; cgx++) {
		cgxd = rvu_cgx_pdata(cgx, rvu);
		if (!cgxd)
			continue;
		err = cgx_lmac_linkup_start(cgxd);
		if (err)
			dev_err(rvu->dev,
				"Link up process failed to start on cgx %d\n",
				cgx);
	}

	return 0;
}
Beispiel #5
0
static int rvu_cgx_config_intlbk(struct rvu *rvu, u16 pcifunc, bool en)
{
	int pf = rvu_get_pf(pcifunc);
	u8 cgx_id, lmac_id;

	/* This msg is expected only from PFs that are mapped to CGX LMACs,
	 * if received from other PF/VF simply ACK, nothing to do.
	 */
	if ((pcifunc & RVU_PFVF_FUNC_MASK) || !is_pf_cgxmapped(rvu, pf))
		return -ENODEV;

	rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);

	return cgx_lmac_internal_loopback(rvu_cgx_pdata(cgx_id, rvu),
					  lmac_id, en);
}
Beispiel #6
0
int rvu_mbox_handler_CGX_GET_LINKINFO(struct rvu *rvu, struct msg_req *req,
				      struct cgx_link_info_msg *rsp)
{
	u8 cgx_id, lmac_id;
	int pf, err;

	pf = rvu_get_pf(req->hdr.pcifunc);

	if (!is_pf_cgxmapped(rvu, pf))
		return -ENODEV;

	rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);

	err = cgx_get_link_info(rvu_cgx_pdata(cgx_id, rvu), lmac_id,
				&rsp->link_info);
	return err;
}
Beispiel #7
0
int rvu_cgx_config_rxtx(struct rvu *rvu, u16 pcifunc, bool start)
{
	int pf = rvu_get_pf(pcifunc);
	u8 cgx_id, lmac_id;

	/* This msg is expected only from PFs that are mapped to CGX LMACs,
	 * if received from other PF/VF simply ACK, nothing to do.
	 */
	if ((pcifunc & RVU_PFVF_FUNC_MASK) || !is_pf_cgxmapped(rvu, pf))
		return -ENODEV;

	rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);

	cgx_lmac_rx_tx_enable(rvu_cgx_pdata(cgx_id, rvu), lmac_id, start);

	return 0;
}
Beispiel #8
0
int rvu_cgx_exit(struct rvu *rvu)
{
	int cgx, lmac;
	void *cgxd;

	for (cgx = 0; cgx <= rvu->cgx_cnt_max; cgx++) {
		cgxd = rvu_cgx_pdata(cgx, rvu);
		if (!cgxd)
			continue;
		for (lmac = 0; lmac < cgx_get_lmac_cnt(cgxd); lmac++)
			cgx_lmac_evh_unregister(cgxd, lmac);
	}

	/* Ensure event handler unregister is completed */
	mb();

	rvu_cgx_wq_destroy(rvu);
	return 0;
}
Beispiel #9
0
int rvu_mbox_handler_CGX_STATS(struct rvu *rvu, struct msg_req *req,
			       struct cgx_stats_rsp *rsp)
{
	int pf = rvu_get_pf(req->hdr.pcifunc);
	int stat = 0, err = 0;
	u64 tx_stat, rx_stat;
	u8 cgx_idx, lmac;
	void *cgxd;

	if ((req->hdr.pcifunc & RVU_PFVF_FUNC_MASK) ||
	    !is_pf_cgxmapped(rvu, pf))
		return -ENODEV;

	rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_idx, &lmac);
	cgxd = rvu_cgx_pdata(cgx_idx, rvu);

	/* Rx stats */
	while (stat < CGX_RX_STATS_COUNT) {
		err = cgx_get_rx_stats(cgxd, lmac, stat, &rx_stat);
		if (err)
			return err;
		rsp->rx_stats[stat] = rx_stat;
		stat++;
	}

	/* Tx stats */
	stat = 0;
	while (stat < CGX_TX_STATS_COUNT) {
		err = cgx_get_tx_stats(cgxd, lmac, stat, &tx_stat);
		if (err)
			return err;
		rsp->tx_stats[stat] = tx_stat;
		stat++;
	}
	return 0;
}