brintos

brintos / linux-shallow public Read only

0
0
Text · 12.7 KiB · 01b7be1 Raw
449 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Marvell Octeon EP (EndPoint) Ethernet Driver3 *4 * Copyright (C) 2020 Marvell.5 *6 */7#include <linux/string.h>8#include <linux/types.h>9#include <linux/etherdevice.h>10#include <linux/pci.h>11#include <linux/wait.h>12 13#include "octep_config.h"14#include "octep_main.h"15#include "octep_ctrl_net.h"16#include "octep_pfvf_mbox.h"17 18/* Control plane version */19#define OCTEP_CP_VERSION_CURRENT	OCTEP_CP_VERSION(1, 0, 0)20 21static const u32 req_hdr_sz = sizeof(union octep_ctrl_net_req_hdr);22static const u32 mtu_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_mtu);23static const u32 mac_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_mac);24static const u32 state_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_state);25static const u32 link_info_sz = sizeof(struct octep_ctrl_net_link_info);26static const u32 offloads_sz = sizeof(struct octep_ctrl_net_offloads);27static atomic_t ctrl_net_msg_id;28 29/* Control plane version in which OCTEP_CTRL_NET_H2F_CMD was added */30static const u32 octep_ctrl_net_h2f_cmd_versions[OCTEP_CTRL_NET_H2F_CMD_MAX] = {31	[OCTEP_CTRL_NET_H2F_CMD_INVALID ... OCTEP_CTRL_NET_H2F_CMD_DEV_REMOVE] =32	 OCTEP_CP_VERSION(1, 0, 0),33	[OCTEP_CTRL_NET_H2F_CMD_OFFLOADS] = OCTEP_CP_VERSION(1, 0, 1)34 35};36 37/* Control plane version in which OCTEP_CTRL_NET_F2H_CMD was added */38static const u32 octep_ctrl_net_f2h_cmd_versions[OCTEP_CTRL_NET_F2H_CMD_MAX] = {39	[OCTEP_CTRL_NET_F2H_CMD_INVALID ... OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS] =40	 OCTEP_CP_VERSION(1, 0, 0)41};42 43static void init_send_req(struct octep_ctrl_mbox_msg *msg, void *buf,44			  u16 sz, int vfid)45{46	msg->hdr.s.flags = OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ;47	msg->hdr.s.msg_id = atomic_inc_return(&ctrl_net_msg_id) &48			    GENMASK(sizeof(msg->hdr.s.msg_id) * BITS_PER_BYTE, 0);49	msg->hdr.s.sz = req_hdr_sz + sz;50	msg->sg_num = 1;51	msg->sg_list[0].msg = buf;52	msg->sg_list[0].sz = msg->hdr.s.sz;53	if (vfid != OCTEP_CTRL_NET_INVALID_VFID) {54		msg->hdr.s.is_vf = 1;55		msg->hdr.s.vf_idx = vfid;56	}57}58 59static int octep_send_mbox_req(struct octep_device *oct,60			       struct octep_ctrl_net_wait_data *d,61			       bool wait_for_response)62{63	int err, ret, cmd;64 65	/* check if firmware is compatible for this request */66	cmd = d->data.req.hdr.s.cmd;67	if (octep_ctrl_net_h2f_cmd_versions[cmd] > oct->ctrl_mbox.max_fw_version ||68	    octep_ctrl_net_h2f_cmd_versions[cmd] < oct->ctrl_mbox.min_fw_version)69		return -EOPNOTSUPP;70 71	err = octep_ctrl_mbox_send(&oct->ctrl_mbox, &d->msg);72	if (err < 0)73		return err;74 75	if (!wait_for_response)76		return 0;77 78	d->done = 0;79	INIT_LIST_HEAD(&d->list);80	list_add_tail(&d->list, &oct->ctrl_req_wait_list);81	ret = wait_event_interruptible_timeout(oct->ctrl_req_wait_q,82					       (d->done != 0),83					       msecs_to_jiffies(500));84	list_del(&d->list);85	if (ret == 0 || ret == 1)86		return -EAGAIN;87 88	/**89	 * (ret == 0)  cond = false && timeout, return 090	 * (ret < 0) interrupted by signal, return 091	 * (ret == 1) cond = true && timeout, return 192	 * (ret >= 1) cond = true && !timeout, return 193	 */94 95	if (d->data.resp.hdr.s.reply != OCTEP_CTRL_NET_REPLY_OK)96		return -EAGAIN;97 98	return 0;99}100 101int octep_ctrl_net_init(struct octep_device *oct)102{103	struct octep_ctrl_mbox *ctrl_mbox;104	struct pci_dev *pdev = oct->pdev;105	int ret;106 107	init_waitqueue_head(&oct->ctrl_req_wait_q);108	INIT_LIST_HEAD(&oct->ctrl_req_wait_list);109 110	/* Initialize control mbox */111	ctrl_mbox = &oct->ctrl_mbox;112	ctrl_mbox->version = OCTEP_CP_VERSION_CURRENT;113	ctrl_mbox->barmem = CFG_GET_CTRL_MBOX_MEM_ADDR(oct->conf);114	ret = octep_ctrl_mbox_init(ctrl_mbox);115	if (ret) {116		dev_err(&pdev->dev, "Failed to initialize control mbox\n");117		return ret;118	}119	dev_info(&pdev->dev, "Control plane versions host: %llx, firmware: %x:%x\n",120		 ctrl_mbox->version, ctrl_mbox->min_fw_version,121		 ctrl_mbox->max_fw_version);122	oct->ctrl_mbox_ifstats_offset = ctrl_mbox->barmem_sz;123 124	return 0;125}126 127int octep_ctrl_net_get_link_status(struct octep_device *oct, int vfid)128{129	struct octep_ctrl_net_wait_data d = {};130	struct octep_ctrl_net_h2f_req *req = &d.data.req;131	int err;132 133	init_send_req(&d.msg, (void *)req, state_sz, vfid);134	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_STATUS;135	req->link.cmd = OCTEP_CTRL_NET_CMD_GET;136	err = octep_send_mbox_req(oct, &d, true);137	if (err < 0)138		return err;139 140	return d.data.resp.link.state;141}142 143int octep_ctrl_net_set_link_status(struct octep_device *oct, int vfid, bool up,144				   bool wait_for_response)145{146	struct octep_ctrl_net_wait_data d = {};147	struct octep_ctrl_net_h2f_req *req = &d.data.req;148 149	init_send_req(&d.msg, req, state_sz, vfid);150	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_STATUS;151	req->link.cmd = OCTEP_CTRL_NET_CMD_SET;152	req->link.state = (up) ? OCTEP_CTRL_NET_STATE_UP :153				OCTEP_CTRL_NET_STATE_DOWN;154 155	return octep_send_mbox_req(oct, &d, wait_for_response);156}157 158int octep_ctrl_net_set_rx_state(struct octep_device *oct, int vfid, bool up,159				bool wait_for_response)160{161	struct octep_ctrl_net_wait_data d = {};162	struct octep_ctrl_net_h2f_req *req = &d.data.req;163 164	init_send_req(&d.msg, req, state_sz, vfid);165	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_RX_STATE;166	req->link.cmd = OCTEP_CTRL_NET_CMD_SET;167	req->link.state = (up) ? OCTEP_CTRL_NET_STATE_UP :168				OCTEP_CTRL_NET_STATE_DOWN;169 170	return octep_send_mbox_req(oct, &d, wait_for_response);171}172 173int octep_ctrl_net_get_mac_addr(struct octep_device *oct, int vfid, u8 *addr)174{175	struct octep_ctrl_net_wait_data d = {};176	struct octep_ctrl_net_h2f_req *req = &d.data.req;177	int err;178 179	init_send_req(&d.msg, req, mac_sz, vfid);180	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_MAC;181	req->link.cmd = OCTEP_CTRL_NET_CMD_GET;182	err = octep_send_mbox_req(oct, &d, true);183	if (err < 0)184		return err;185 186	memcpy(addr, d.data.resp.mac.addr, ETH_ALEN);187 188	return 0;189}190 191int octep_ctrl_net_set_mac_addr(struct octep_device *oct, int vfid, u8 *addr,192				bool wait_for_response)193{194	struct octep_ctrl_net_wait_data d = {};195	struct octep_ctrl_net_h2f_req *req = &d.data.req;196 197	init_send_req(&d.msg, req, mac_sz, vfid);198	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_MAC;199	req->mac.cmd = OCTEP_CTRL_NET_CMD_SET;200	memcpy(&req->mac.addr, addr, ETH_ALEN);201 202	return octep_send_mbox_req(oct, &d, wait_for_response);203}204 205int octep_ctrl_net_get_mtu(struct octep_device *oct, int vfid)206{207	struct octep_ctrl_net_wait_data d = {};208	struct octep_ctrl_net_h2f_req *req;209	int err;210 211	req = &d.data.req;212	init_send_req(&d.msg, req, mtu_sz, vfid);213	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_MTU;214	req->mtu.cmd = OCTEP_CTRL_NET_CMD_GET;215 216	err = octep_send_mbox_req(oct, &d, true);217	if (err < 0)218		return err;219 220	return d.data.resp.mtu.val;221}222 223int octep_ctrl_net_set_mtu(struct octep_device *oct, int vfid, int mtu,224			   bool wait_for_response)225{226	struct octep_ctrl_net_wait_data d = {};227	struct octep_ctrl_net_h2f_req *req = &d.data.req;228 229	init_send_req(&d.msg, req, mtu_sz, vfid);230	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_MTU;231	req->mtu.cmd = OCTEP_CTRL_NET_CMD_SET;232	req->mtu.val = mtu;233 234	return octep_send_mbox_req(oct, &d, wait_for_response);235}236 237int octep_ctrl_net_get_if_stats(struct octep_device *oct, int vfid,238				struct octep_iface_rx_stats *rx_stats,239				struct octep_iface_tx_stats *tx_stats)240{241	struct octep_ctrl_net_wait_data d = {};242	struct octep_ctrl_net_h2f_req *req = &d.data.req;243	struct octep_ctrl_net_h2f_resp *resp;244	int err;245 246	init_send_req(&d.msg, req, 0, vfid);247	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_GET_IF_STATS;248	err = octep_send_mbox_req(oct, &d, true);249	if (err < 0)250		return err;251 252	resp = &d.data.resp;253	memcpy(rx_stats, &resp->if_stats.rx_stats, sizeof(struct octep_iface_rx_stats));254	memcpy(tx_stats, &resp->if_stats.tx_stats, sizeof(struct octep_iface_tx_stats));255	return 0;256}257 258int octep_ctrl_net_get_link_info(struct octep_device *oct, int vfid,259				 struct octep_iface_link_info *link_info)260{261	struct octep_ctrl_net_wait_data d = {};262	struct octep_ctrl_net_h2f_req *req = &d.data.req;263	struct octep_ctrl_net_h2f_resp *resp;264	int err;265 266	init_send_req(&d.msg, req, link_info_sz, vfid);267	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_INFO;268	req->link_info.cmd = OCTEP_CTRL_NET_CMD_GET;269	err = octep_send_mbox_req(oct, &d, true);270	if (err < 0)271		return err;272 273	resp = &d.data.resp;274	link_info->supported_modes = resp->link_info.supported_modes;275	link_info->advertised_modes = resp->link_info.advertised_modes;276	link_info->autoneg = resp->link_info.autoneg;277	link_info->pause = resp->link_info.pause;278	link_info->speed = resp->link_info.speed;279 280	return 0;281}282 283int octep_ctrl_net_set_link_info(struct octep_device *oct, int vfid,284				 struct octep_iface_link_info *link_info,285				 bool wait_for_response)286{287	struct octep_ctrl_net_wait_data d = {};288	struct octep_ctrl_net_h2f_req *req = &d.data.req;289 290	init_send_req(&d.msg, req, link_info_sz, vfid);291	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_LINK_INFO;292	req->link_info.cmd = OCTEP_CTRL_NET_CMD_SET;293	req->link_info.info.advertised_modes = link_info->advertised_modes;294	req->link_info.info.autoneg = link_info->autoneg;295	req->link_info.info.pause = link_info->pause;296	req->link_info.info.speed = link_info->speed;297 298	return octep_send_mbox_req(oct, &d, wait_for_response);299}300 301static void process_mbox_resp(struct octep_device *oct,302			      struct octep_ctrl_mbox_msg *msg)303{304	struct octep_ctrl_net_wait_data *pos, *n;305 306	list_for_each_entry_safe(pos, n, &oct->ctrl_req_wait_list, list) {307		if (pos->msg.hdr.s.msg_id == msg->hdr.s.msg_id) {308			memcpy(&pos->data.resp,309			       msg->sg_list[0].msg,310			       msg->hdr.s.sz);311			pos->done = 1;312			wake_up_interruptible_all(&oct->ctrl_req_wait_q);313			break;314		}315	}316}317 318static int process_mbox_notify(struct octep_device *oct,319			       struct octep_ctrl_mbox_msg *msg)320{321	struct net_device *netdev = oct->netdev;322	struct octep_ctrl_net_f2h_req *req;323	int cmd;324 325	req = (struct octep_ctrl_net_f2h_req *)msg->sg_list[0].msg;326	cmd = req->hdr.s.cmd;327 328	/* check if we support this command */329	if (octep_ctrl_net_f2h_cmd_versions[cmd] > OCTEP_CP_VERSION_CURRENT ||330	    octep_ctrl_net_f2h_cmd_versions[cmd] < OCTEP_CP_VERSION_CURRENT)331		return -EOPNOTSUPP;332 333	if (msg->hdr.s.is_vf) {334		octep_pfvf_notify(oct, msg);335		return 0;336	}337 338	switch (cmd) {339	case OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS:340		if (netif_running(netdev)) {341			if (req->link.state) {342				dev_info(&oct->pdev->dev, "netif_carrier_on\n");343				netif_carrier_on(netdev);344			} else {345				dev_info(&oct->pdev->dev, "netif_carrier_off\n");346				netif_carrier_off(netdev);347			}348		}349		break;350	default:351		pr_info("Unknown mbox req : %u\n", req->hdr.s.cmd);352		break;353	}354 355	return 0;356}357 358void octep_ctrl_net_recv_fw_messages(struct octep_device *oct)359{360	static u16 msg_sz = sizeof(union octep_ctrl_net_max_data);361	union octep_ctrl_net_max_data data = {};362	struct octep_ctrl_mbox_msg msg = {};363	int ret;364 365	msg.hdr.s.sz = msg_sz;366	msg.sg_num = 1;367	msg.sg_list[0].sz = msg_sz;368	msg.sg_list[0].msg = &data;369	while (true) {370		/* mbox will overwrite msg.hdr.s.sz so initialize it */371		msg.hdr.s.sz = msg_sz;372		ret = octep_ctrl_mbox_recv(&oct->ctrl_mbox, (struct octep_ctrl_mbox_msg *)&msg);373		if (ret < 0)374			break;375 376		if (msg.hdr.s.flags & OCTEP_CTRL_MBOX_MSG_HDR_FLAG_RESP)377			process_mbox_resp(oct, &msg);378		else if (msg.hdr.s.flags & OCTEP_CTRL_MBOX_MSG_HDR_FLAG_NOTIFY)379			process_mbox_notify(oct, &msg);380	}381}382 383int octep_ctrl_net_get_info(struct octep_device *oct, int vfid,384			    struct octep_fw_info *info)385{386	struct octep_ctrl_net_wait_data d = {};387	struct octep_ctrl_net_h2f_resp *resp;388	struct octep_ctrl_net_h2f_req *req;389	int err;390 391	req = &d.data.req;392	init_send_req(&d.msg, req, 0, vfid);393	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_GET_INFO;394	req->link_info.cmd = OCTEP_CTRL_NET_CMD_GET;395	err = octep_send_mbox_req(oct, &d, true);396	if (err < 0)397		return err;398 399	resp = &d.data.resp;400	memcpy(info, &resp->info.fw_info, sizeof(struct octep_fw_info));401 402	return 0;403}404 405int octep_ctrl_net_dev_remove(struct octep_device *oct, int vfid)406{407	struct octep_ctrl_net_wait_data d = {};408	struct octep_ctrl_net_h2f_req *req;409 410	req = &d.data.req;411	dev_dbg(&oct->pdev->dev, "Sending dev_unload msg to fw\n");412	init_send_req(&d.msg, req, sizeof(int), vfid);413	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_DEV_REMOVE;414 415	return octep_send_mbox_req(oct, &d, false);416}417 418int octep_ctrl_net_set_offloads(struct octep_device *oct, int vfid,419				struct octep_ctrl_net_offloads *offloads,420				bool wait_for_response)421{422	struct octep_ctrl_net_wait_data d = {};423	struct octep_ctrl_net_h2f_req *req;424 425	req = &d.data.req;426	init_send_req(&d.msg, req, offloads_sz, vfid);427	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_OFFLOADS;428	req->offloads.cmd = OCTEP_CTRL_NET_CMD_SET;429	req->offloads.offloads = *offloads;430 431	return octep_send_mbox_req(oct, &d, wait_for_response);432}433 434int octep_ctrl_net_uninit(struct octep_device *oct)435{436	struct octep_ctrl_net_wait_data *pos, *n;437 438	octep_ctrl_net_dev_remove(oct, OCTEP_CTRL_NET_INVALID_VFID);439 440	list_for_each_entry_safe(pos, n, &oct->ctrl_req_wait_list, list)441		pos->done = 1;442 443	wake_up_interruptible_all(&oct->ctrl_req_wait_q);444 445	octep_ctrl_mbox_uninit(&oct->ctrl_mbox);446 447	return 0;448}449