brintos

brintos / linux-shallow public Read only

0
0
Text · 11.5 KiB · 445b626 Raw
432 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Marvell Octeon EP (EndPoint) VF Ethernet Driver3 *4 * Copyright (C) 2020 Marvell.5 *6 */7#include <linux/types.h>8#include <linux/pci.h>9#include <linux/netdevice.h>10#include <linux/vmalloc.h>11#include "octep_vf_config.h"12#include "octep_vf_main.h"13 14/* When a new command is implemented, the below table should be updated15 * with new command and it's version info.16 */17static u32 pfvf_cmd_versions[OCTEP_PFVF_MBOX_CMD_MAX] = {18	[0 ... OCTEP_PFVF_MBOX_CMD_DEV_REMOVE] = OCTEP_PFVF_MBOX_VERSION_V1,19	[OCTEP_PFVF_MBOX_CMD_GET_FW_INFO ... OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS] =20		OCTEP_PFVF_MBOX_VERSION_V221};22 23int octep_vf_setup_mbox(struct octep_vf_device *oct)24{25	int ring = 0;26 27	oct->mbox = vzalloc(sizeof(*oct->mbox));28	if (!oct->mbox)29		return -1;30 31	mutex_init(&oct->mbox->lock);32 33	oct->hw_ops.setup_mbox_regs(oct, ring);34	INIT_WORK(&oct->mbox->wk.work, octep_vf_mbox_work);35	oct->mbox->wk.ctxptr = oct;36	oct->mbox_neg_ver = OCTEP_PFVF_MBOX_VERSION_CURRENT;37	dev_info(&oct->pdev->dev, "setup vf mbox successfully\n");38	return 0;39}40 41void octep_vf_delete_mbox(struct octep_vf_device *oct)42{43	if (oct->mbox) {44		if (work_pending(&oct->mbox->wk.work))45			cancel_work_sync(&oct->mbox->wk.work);46 47		mutex_destroy(&oct->mbox->lock);48		vfree(oct->mbox);49		oct->mbox = NULL;50		dev_info(&oct->pdev->dev, "Deleted vf mbox successfully\n");51	}52}53 54int octep_vf_mbox_version_check(struct octep_vf_device *oct)55{56	union octep_pfvf_mbox_word cmd;57	union octep_pfvf_mbox_word rsp;58	int ret;59 60	cmd.u64 = 0;61	cmd.s_version.opcode = OCTEP_PFVF_MBOX_CMD_VERSION;62	cmd.s_version.version = OCTEP_PFVF_MBOX_VERSION_CURRENT;63	ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);64	if (ret == OCTEP_PFVF_MBOX_CMD_STATUS_NACK) {65		dev_err(&oct->pdev->dev,66			"VF Mbox version is incompatible with PF\n");67		return -EINVAL;68	}69	oct->mbox_neg_ver = (u32)rsp.s_version.version;70	dev_dbg(&oct->pdev->dev,71		"VF Mbox version:%u Negotiated VF version with PF:%u\n",72		 (u32)cmd.s_version.version,73		 (u32)rsp.s_version.version);74	return 0;75}76 77void octep_vf_mbox_work(struct work_struct *work)78{79	struct octep_vf_mbox_wk *wk = container_of(work, struct octep_vf_mbox_wk, work);80	struct octep_vf_iface_link_info *link_info;81	struct octep_vf_device *oct = NULL;82	struct octep_vf_mbox *mbox = NULL;83	union octep_pfvf_mbox_word *notif;84	u64 pf_vf_data;85 86	oct = (struct octep_vf_device *)wk->ctxptr;87	link_info = &oct->link_info;88	mbox = oct->mbox;89	pf_vf_data = readq(mbox->mbox_read_reg);90 91	notif = (union octep_pfvf_mbox_word *)&pf_vf_data;92 93	switch (notif->s.opcode) {94	case OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS:95		if (notif->s_link_status.status) {96			link_info->oper_up = OCTEP_PFVF_LINK_STATUS_UP;97			netif_carrier_on(oct->netdev);98			dev_info(&oct->pdev->dev, "netif_carrier_on\n");99		} else {100			link_info->oper_up = OCTEP_PFVF_LINK_STATUS_DOWN;101			netif_carrier_off(oct->netdev);102			dev_info(&oct->pdev->dev, "netif_carrier_off\n");103		}104		break;105	default:106		dev_err(&oct->pdev->dev,107			"Received unsupported notif %d\n", notif->s.opcode);108		break;109	}110}111 112static int __octep_vf_mbox_send_cmd(struct octep_vf_device *oct,113				    union octep_pfvf_mbox_word cmd,114				    union octep_pfvf_mbox_word *rsp)115{116	struct octep_vf_mbox *mbox = oct->mbox;117	u64 reg_val = 0ull;118	int count;119 120	if (!mbox)121		return OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP;122 123	cmd.s.type = OCTEP_PFVF_MBOX_TYPE_CMD;124	writeq(cmd.u64, mbox->mbox_write_reg);125 126	/* No response for notification messages */127	if (!rsp)128		return 0;129 130	for (count = 0; count < OCTEP_PFVF_MBOX_TIMEOUT_WAIT_COUNT; count++) {131		usleep_range(1000, 1500);132		reg_val = readq(mbox->mbox_write_reg);133		if (reg_val != cmd.u64) {134			rsp->u64 = reg_val;135			break;136		}137	}138	if (count == OCTEP_PFVF_MBOX_TIMEOUT_WAIT_COUNT) {139		dev_err(&oct->pdev->dev, "mbox send command timed out\n");140		return OCTEP_PFVF_MBOX_CMD_STATUS_TIMEDOUT;141	}142	if (rsp->s.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {143		dev_err(&oct->pdev->dev, "mbox_send: Received NACK\n");144		return OCTEP_PFVF_MBOX_CMD_STATUS_NACK;145	}146	rsp->u64 = reg_val;147	return 0;148}149 150int octep_vf_mbox_send_cmd(struct octep_vf_device *oct, union octep_pfvf_mbox_word cmd,151			   union octep_pfvf_mbox_word *rsp)152{153	struct octep_vf_mbox *mbox = oct->mbox;154	int ret;155 156	if (!mbox)157		return OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP;158	mutex_lock(&mbox->lock);159	if (pfvf_cmd_versions[cmd.s.opcode] > oct->mbox_neg_ver) {160		dev_dbg(&oct->pdev->dev, "CMD:%d not supported in Version:%d\n",161			cmd.s.opcode, oct->mbox_neg_ver);162		mutex_unlock(&mbox->lock);163		return -EOPNOTSUPP;164	}165	ret = __octep_vf_mbox_send_cmd(oct, cmd, rsp);166	mutex_unlock(&mbox->lock);167	return ret;168}169 170int octep_vf_mbox_bulk_read(struct octep_vf_device *oct, enum octep_pfvf_mbox_opcode opcode,171			    u8 *data, int *size)172{173	struct octep_vf_mbox *mbox = oct->mbox;174	union octep_pfvf_mbox_word cmd;175	union octep_pfvf_mbox_word rsp;176	int data_len = 0, tmp_len = 0;177	int read_cnt, i = 0, ret;178 179	if (!mbox)180		return OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP;181 182	mutex_lock(&mbox->lock);183	cmd.u64 = 0;184	cmd.s_data.opcode = opcode;185	cmd.s_data.frag = 0;186	/* Send cmd to read data from PF */187	ret = __octep_vf_mbox_send_cmd(oct, cmd, &rsp);188	if (ret) {189		dev_err(&oct->pdev->dev, "send mbox cmd fail for data request\n");190		mutex_unlock(&mbox->lock);191		return ret;192	}193	/*  PF sends the data length of requested CMD194	 *  in  ACK195	 */196	data_len = *((int32_t *)rsp.s_data.data);197	tmp_len = data_len;198	cmd.u64 = 0;199	rsp.u64 = 0;200	cmd.s_data.opcode = opcode;201	cmd.s_data.frag = 1;202	while (data_len) {203		ret = __octep_vf_mbox_send_cmd(oct, cmd, &rsp);204		if (ret) {205			dev_err(&oct->pdev->dev, "send mbox cmd fail for data request\n");206			mutex_unlock(&mbox->lock);207			mbox->mbox_data.data_index = 0;208			memset(mbox->mbox_data.recv_data, 0, OCTEP_PFVF_MBOX_MAX_DATA_BUF_SIZE);209			return ret;210		}211		if (data_len > OCTEP_PFVF_MBOX_MAX_DATA_SIZE) {212			data_len -= OCTEP_PFVF_MBOX_MAX_DATA_SIZE;213			read_cnt = OCTEP_PFVF_MBOX_MAX_DATA_SIZE;214		} else {215			read_cnt = data_len;216			data_len = 0;217		}218		for (i = 0; i < read_cnt; i++) {219			mbox->mbox_data.recv_data[mbox->mbox_data.data_index] =220				rsp.s_data.data[i];221			mbox->mbox_data.data_index++;222		}223		cmd.u64 = 0;224		rsp.u64 = 0;225		cmd.s_data.opcode = opcode;226		cmd.s_data.frag = 1;227	}228	memcpy(data, mbox->mbox_data.recv_data, tmp_len);229	*size = tmp_len;230	mbox->mbox_data.data_index = 0;231	memset(mbox->mbox_data.recv_data, 0, OCTEP_PFVF_MBOX_MAX_DATA_BUF_SIZE);232	mutex_unlock(&mbox->lock);233	return 0;234}235 236int octep_vf_mbox_set_mtu(struct octep_vf_device *oct, int mtu)237{238	int frame_size = mtu + ETH_HLEN + ETH_FCS_LEN;239	union octep_pfvf_mbox_word cmd;240	union octep_pfvf_mbox_word rsp;241	int ret = 0;242 243	if (mtu < ETH_MIN_MTU || frame_size > ETH_MAX_MTU) {244		dev_err(&oct->pdev->dev,245			"Failed to set MTU to %d MIN MTU:%d MAX MTU:%d\n",246			mtu, ETH_MIN_MTU, ETH_MAX_MTU);247		return -EINVAL;248	}249 250	cmd.u64 = 0;251	cmd.s_set_mtu.opcode = OCTEP_PFVF_MBOX_CMD_SET_MTU;252	cmd.s_set_mtu.mtu = mtu;253 254	ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);255	if (ret) {256		dev_err(&oct->pdev->dev, "Mbox send failed; err=%d\n", ret);257		return ret;258	}259	if (rsp.s_set_mtu.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {260		dev_err(&oct->pdev->dev, "Received Mbox NACK from PF for MTU:%d\n", mtu);261		return -EINVAL;262	}263 264	return 0;265}266 267int octep_vf_mbox_set_mac_addr(struct octep_vf_device *oct, char *mac_addr)268{269	union octep_pfvf_mbox_word cmd;270	union octep_pfvf_mbox_word rsp;271	int i, ret;272 273	cmd.u64 = 0;274	cmd.s_set_mac.opcode = OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR;275	for (i = 0; i < ETH_ALEN; i++)276		cmd.s_set_mac.mac_addr[i] = mac_addr[i];277	ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);278	if (ret) {279		dev_err(&oct->pdev->dev, "Mbox send failed; err = %d\n", ret);280		return ret;281	}282	if (rsp.s_set_mac.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {283		dev_err(&oct->pdev->dev, "received NACK\n");284		return -EINVAL;285	}286	return 0;287}288 289int octep_vf_mbox_get_mac_addr(struct octep_vf_device *oct, char *mac_addr)290{291	union octep_pfvf_mbox_word cmd;292	union octep_pfvf_mbox_word rsp;293	int i, ret;294 295	cmd.u64 = 0;296	cmd.s_set_mac.opcode = OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR;297	ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);298	if (ret) {299		dev_err(&oct->pdev->dev, "get_mac: mbox send failed; err = %d\n", ret);300		return ret;301	}302	if (rsp.s_set_mac.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {303		dev_err(&oct->pdev->dev, "get_mac: received NACK\n");304		return -EINVAL;305	}306	for (i = 0; i < ETH_ALEN; i++)307		mac_addr[i] = rsp.s_set_mac.mac_addr[i];308	return 0;309}310 311int octep_vf_mbox_set_rx_state(struct octep_vf_device *oct, bool state)312{313	union octep_pfvf_mbox_word cmd;314	union octep_pfvf_mbox_word rsp;315	int ret;316 317	cmd.u64 = 0;318	cmd.s_link_state.opcode = OCTEP_PFVF_MBOX_CMD_SET_RX_STATE;319	cmd.s_link_state.state = state;320	ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);321	if (ret) {322		dev_err(&oct->pdev->dev, "Set Rx state via VF Mbox send failed\n");323		return ret;324	}325	if (rsp.s_link_state.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {326		dev_err(&oct->pdev->dev, "Set Rx state received NACK\n");327		return -EINVAL;328	}329	return 0;330}331 332int octep_vf_mbox_set_link_status(struct octep_vf_device *oct, bool status)333{334	union octep_pfvf_mbox_word cmd;335	union octep_pfvf_mbox_word rsp;336	int ret;337 338	cmd.u64 = 0;339	cmd.s_link_status.opcode = OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS;340	cmd.s_link_status.status = status;341	ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);342	if (ret) {343		dev_err(&oct->pdev->dev, "Set link status via VF Mbox send failed\n");344		return ret;345	}346	if (rsp.s_link_status.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {347		dev_err(&oct->pdev->dev, "Set link status received NACK\n");348		return -EINVAL;349	}350	return 0;351}352 353int octep_vf_mbox_get_link_status(struct octep_vf_device *oct, u8 *oper_up)354{355	union octep_pfvf_mbox_word cmd;356	union octep_pfvf_mbox_word rsp;357	int ret;358 359	cmd.u64 = 0;360	cmd.s_link_status.opcode = OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS;361	ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);362	if (ret) {363		dev_err(&oct->pdev->dev, "Get link status via VF Mbox send failed\n");364		return ret;365	}366	if (rsp.s_link_status.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {367		dev_err(&oct->pdev->dev, "Get link status received NACK\n");368		return -EINVAL;369	}370	*oper_up = rsp.s_link_status.status;371	return 0;372}373 374int octep_vf_mbox_dev_remove(struct octep_vf_device *oct)375{376	union octep_pfvf_mbox_word cmd;377	int ret;378 379	cmd.u64 = 0;380	cmd.s.opcode = OCTEP_PFVF_MBOX_CMD_DEV_REMOVE;381	ret = octep_vf_mbox_send_cmd(oct, cmd, NULL);382	return ret;383}384 385int octep_vf_mbox_get_fw_info(struct octep_vf_device *oct)386{387	union octep_pfvf_mbox_word cmd;388	union octep_pfvf_mbox_word rsp;389	int ret;390 391	cmd.u64 = 0;392	cmd.s_fw_info.opcode = OCTEP_PFVF_MBOX_CMD_GET_FW_INFO;393	ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);394	if (ret) {395		dev_err(&oct->pdev->dev, "Get link status via VF Mbox send failed\n");396		return ret;397	}398	if (rsp.s_fw_info.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {399		dev_err(&oct->pdev->dev, "Get link status received NACK\n");400		return -EINVAL;401	}402	oct->fw_info.pkind = rsp.s_fw_info.pkind;403	oct->fw_info.fsz = rsp.s_fw_info.fsz;404	oct->fw_info.rx_ol_flags = rsp.s_fw_info.rx_ol_flags;405	oct->fw_info.tx_ol_flags = rsp.s_fw_info.tx_ol_flags;406 407	return 0;408}409 410int octep_vf_mbox_set_offloads(struct octep_vf_device *oct, u16 tx_offloads,411			       u16 rx_offloads)412{413	union octep_pfvf_mbox_word cmd;414	union octep_pfvf_mbox_word rsp;415	int ret;416 417	cmd.u64 = 0;418	cmd.s_offloads.opcode = OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS;419	cmd.s_offloads.rx_ol_flags = rx_offloads;420	cmd.s_offloads.tx_ol_flags = tx_offloads;421	ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp);422	if (ret) {423		dev_err(&oct->pdev->dev, "Set offloads via VF Mbox send failed\n");424		return ret;425	}426	if (rsp.s_link_state.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) {427		dev_err(&oct->pdev->dev, "Set offloads received NACK\n");428		return -EINVAL;429	}430	return 0;431}432