brintos

brintos / linux-shallow public Read only

0
0
Text · 26.5 KiB · c6779d9 Raw
1000 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2024, Intel Corporation. */3 4#include <linux/vmalloc.h>5 6#include "ice.h"7#include "devlink.h"8#include "devlink_port.h"9#include "ice_lib.h"10#include "ice_fltr.h"11 12static int ice_active_port_option = -1;13 14/**15 * ice_devlink_port_opt_speed_str - convert speed to a string16 * @speed: speed value17 */18static const char *ice_devlink_port_opt_speed_str(u8 speed)19{20	switch (speed & ICE_AQC_PORT_OPT_MAX_LANE_M) {21	case ICE_AQC_PORT_OPT_MAX_LANE_100M:22		return "0.1";23	case ICE_AQC_PORT_OPT_MAX_LANE_1G:24		return "1";25	case ICE_AQC_PORT_OPT_MAX_LANE_2500M:26		return "2.5";27	case ICE_AQC_PORT_OPT_MAX_LANE_5G:28		return "5";29	case ICE_AQC_PORT_OPT_MAX_LANE_10G:30		return "10";31	case ICE_AQC_PORT_OPT_MAX_LANE_25G:32		return "25";33	case ICE_AQC_PORT_OPT_MAX_LANE_50G:34		return "50";35	case ICE_AQC_PORT_OPT_MAX_LANE_100G:36		return "100";37	}38 39	return "-";40}41 42#define ICE_PORT_OPT_DESC_LEN	5043/**44 * ice_devlink_port_options_print - Print available port split options45 * @pf: the PF to print split port options46 *47 * Prints a table with available port split options and max port speeds48 */49static void ice_devlink_port_options_print(struct ice_pf *pf)50{51	u8 i, j, options_count, cnt, speed, pending_idx, active_idx;52	struct ice_aqc_get_port_options_elem *options, *opt;53	struct device *dev = ice_pf_to_dev(pf);54	bool active_valid, pending_valid;55	char desc[ICE_PORT_OPT_DESC_LEN];56	const char *str;57	int status;58 59	options = kcalloc(ICE_AQC_PORT_OPT_MAX * ICE_MAX_PORT_PER_PCI_DEV,60			  sizeof(*options), GFP_KERNEL);61	if (!options)62		return;63 64	for (i = 0; i < ICE_MAX_PORT_PER_PCI_DEV; i++) {65		opt = options + i * ICE_AQC_PORT_OPT_MAX;66		options_count = ICE_AQC_PORT_OPT_MAX;67		active_valid = 0;68 69		status = ice_aq_get_port_options(&pf->hw, opt, &options_count,70						 i, true, &active_idx,71						 &active_valid, &pending_idx,72						 &pending_valid);73		if (status) {74			dev_dbg(dev, "Couldn't read port option for port %d, err %d\n",75				i, status);76			goto err;77		}78	}79 80	dev_dbg(dev, "Available port split options and max port speeds (Gbps):\n");81	dev_dbg(dev, "Status  Split      Quad 0          Quad 1\n");82	dev_dbg(dev, "        count  L0  L1  L2  L3  L4  L5  L6  L7\n");83 84	for (i = 0; i < options_count; i++) {85		cnt = 0;86 87		if (i == ice_active_port_option)88			str = "Active";89		else if ((i == pending_idx) && pending_valid)90			str = "Pending";91		else92			str = "";93 94		cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,95				"%-8s", str);96 97		cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,98				"%-6u", options[i].pmd);99 100		for (j = 0; j < ICE_MAX_PORT_PER_PCI_DEV; ++j) {101			speed = options[i + j * ICE_AQC_PORT_OPT_MAX].max_lane_speed;102			str = ice_devlink_port_opt_speed_str(speed);103			cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,104					"%3s ", str);105		}106 107		dev_dbg(dev, "%s\n", desc);108	}109 110err:111	kfree(options);112}113 114/**115 * ice_devlink_aq_set_port_option - Send set port option admin queue command116 * @pf: the PF to print split port options117 * @option_idx: selected port option118 * @extack: extended netdev ack structure119 *120 * Sends set port option admin queue command with selected port option and121 * calls NVM write activate.122 */123static int124ice_devlink_aq_set_port_option(struct ice_pf *pf, u8 option_idx,125			       struct netlink_ext_ack *extack)126{127	struct device *dev = ice_pf_to_dev(pf);128	int status;129 130	status = ice_aq_set_port_option(&pf->hw, 0, true, option_idx);131	if (status) {132		dev_dbg(dev, "ice_aq_set_port_option, err %d aq_err %d\n",133			status, pf->hw.adminq.sq_last_status);134		NL_SET_ERR_MSG_MOD(extack, "Port split request failed");135		return -EIO;136	}137 138	status = ice_acquire_nvm(&pf->hw, ICE_RES_WRITE);139	if (status) {140		dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",141			status, pf->hw.adminq.sq_last_status);142		NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");143		return -EIO;144	}145 146	status = ice_nvm_write_activate(&pf->hw, ICE_AQC_NVM_ACTIV_REQ_EMPR, NULL);147	if (status) {148		dev_dbg(dev, "ice_nvm_write_activate failed, err %d aq_err %d\n",149			status, pf->hw.adminq.sq_last_status);150		NL_SET_ERR_MSG_MOD(extack, "Port split request failed to save data");151		ice_release_nvm(&pf->hw);152		return -EIO;153	}154 155	ice_release_nvm(&pf->hw);156 157	NL_SET_ERR_MSG_MOD(extack, "Reboot required to finish port split");158	return 0;159}160 161/**162 * ice_devlink_port_split - .port_split devlink handler163 * @devlink: devlink instance structure164 * @port: devlink port structure165 * @count: number of ports to split to166 * @extack: extended netdev ack structure167 *168 * Callback for the devlink .port_split operation.169 *170 * Unfortunately, the devlink expression of available options is limited171 * to just a number, so search for an FW port option which supports172 * the specified number. As there could be multiple FW port options with173 * the same port split count, allow switching between them. When the same174 * port split count request is issued again, switch to the next FW port175 * option with the same port split count.176 *177 * Return: zero on success or an error code on failure.178 */179static int180ice_devlink_port_split(struct devlink *devlink, struct devlink_port *port,181		       unsigned int count, struct netlink_ext_ack *extack)182{183	struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX];184	u8 i, j, active_idx, pending_idx, new_option;185	struct ice_pf *pf = devlink_priv(devlink);186	u8 option_count = ICE_AQC_PORT_OPT_MAX;187	struct device *dev = ice_pf_to_dev(pf);188	bool active_valid, pending_valid;189	int status;190 191	status = ice_aq_get_port_options(&pf->hw, options, &option_count,192					 0, true, &active_idx, &active_valid,193					 &pending_idx, &pending_valid);194	if (status) {195		dev_dbg(dev, "Couldn't read port split options, err = %d\n",196			status);197		NL_SET_ERR_MSG_MOD(extack, "Failed to get available port split options");198		return -EIO;199	}200 201	new_option = ICE_AQC_PORT_OPT_MAX;202	active_idx = pending_valid ? pending_idx : active_idx;203	for (i = 1; i <= option_count; i++) {204		/* In order to allow switching between FW port options with205		 * the same port split count, search for a new option starting206		 * from the active/pending option (with array wrap around).207		 */208		j = (active_idx + i) % option_count;209 210		if (count == options[j].pmd) {211			new_option = j;212			break;213		}214	}215 216	if (new_option == active_idx) {217		dev_dbg(dev, "request to split: count: %u is already set and there are no other options\n",218			count);219		NL_SET_ERR_MSG_MOD(extack, "Requested split count is already set");220		ice_devlink_port_options_print(pf);221		return -EINVAL;222	}223 224	if (new_option == ICE_AQC_PORT_OPT_MAX) {225		dev_dbg(dev, "request to split: count: %u not found\n", count);226		NL_SET_ERR_MSG_MOD(extack, "Port split requested unsupported port config");227		ice_devlink_port_options_print(pf);228		return -EINVAL;229	}230 231	status = ice_devlink_aq_set_port_option(pf, new_option, extack);232	if (status)233		return status;234 235	ice_devlink_port_options_print(pf);236 237	return 0;238}239 240/**241 * ice_devlink_port_unsplit - .port_unsplit devlink handler242 * @devlink: devlink instance structure243 * @port: devlink port structure244 * @extack: extended netdev ack structure245 *246 * Callback for the devlink .port_unsplit operation.247 * Calls ice_devlink_port_split with split count set to 1.248 * There could be no FW option available with split count 1.249 *250 * Return: zero on success or an error code on failure.251 */252static int253ice_devlink_port_unsplit(struct devlink *devlink, struct devlink_port *port,254			 struct netlink_ext_ack *extack)255{256	return ice_devlink_port_split(devlink, port, 1, extack);257}258 259/**260 * ice_devlink_set_port_split_options - Set port split options261 * @pf: the PF to set port split options262 * @attrs: devlink attributes263 *264 * Sets devlink port split options based on available FW port options265 */266static void267ice_devlink_set_port_split_options(struct ice_pf *pf,268				   struct devlink_port_attrs *attrs)269{270	struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX];271	u8 i, active_idx, pending_idx, option_count = ICE_AQC_PORT_OPT_MAX;272	bool active_valid, pending_valid;273	int status;274 275	status = ice_aq_get_port_options(&pf->hw, options, &option_count,276					 0, true, &active_idx, &active_valid,277					 &pending_idx, &pending_valid);278	if (status) {279		dev_dbg(ice_pf_to_dev(pf), "Couldn't read port split options, err = %d\n",280			status);281		return;282	}283 284	/* find the biggest available port split count */285	for (i = 0; i < option_count; i++)286		attrs->lanes = max_t(int, attrs->lanes, options[i].pmd);287 288	attrs->splittable = attrs->lanes ? 1 : 0;289	ice_active_port_option = active_idx;290}291 292static const struct devlink_port_ops ice_devlink_port_ops = {293	.port_split = ice_devlink_port_split,294	.port_unsplit = ice_devlink_port_unsplit,295};296 297/**298 * ice_devlink_set_switch_id - Set unique switch id based on pci dsn299 * @pf: the PF to create a devlink port for300 * @ppid: struct with switch id information301 */302static void303ice_devlink_set_switch_id(struct ice_pf *pf, struct netdev_phys_item_id *ppid)304{305	struct pci_dev *pdev = pf->pdev;306	u64 id;307 308	id = pci_get_dsn(pdev);309 310	ppid->id_len = sizeof(id);311	put_unaligned_be64(id, &ppid->id);312}313 314/**315 * ice_devlink_create_pf_port - Create a devlink port for this PF316 * @pf: the PF to create a devlink port for317 *318 * Create and register a devlink_port for this PF.319 * This function has to be called under devl_lock.320 *321 * Return: zero on success or an error code on failure.322 */323int ice_devlink_create_pf_port(struct ice_pf *pf)324{325	struct devlink_port_attrs attrs = {};326	struct devlink_port *devlink_port;327	struct devlink *devlink;328	struct ice_vsi *vsi;329	struct device *dev;330	int err;331 332	devlink = priv_to_devlink(pf);333 334	dev = ice_pf_to_dev(pf);335 336	devlink_port = &pf->devlink_port;337 338	vsi = ice_get_main_vsi(pf);339	if (!vsi)340		return -EIO;341 342	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;343	attrs.phys.port_number = pf->hw.pf_id;344 345	/* As FW supports only port split options for whole device,346	 * set port split options only for first PF.347	 */348	if (pf->hw.pf_id == 0)349		ice_devlink_set_port_split_options(pf, &attrs);350 351	ice_devlink_set_switch_id(pf, &attrs.switch_id);352 353	devlink_port_attrs_set(devlink_port, &attrs);354 355	err = devl_port_register_with_ops(devlink, devlink_port, vsi->idx,356					  &ice_devlink_port_ops);357	if (err) {358		dev_err(dev, "Failed to create devlink port for PF %d, error %d\n",359			pf->hw.pf_id, err);360		return err;361	}362 363	return 0;364}365 366/**367 * ice_devlink_destroy_pf_port - Destroy the devlink_port for this PF368 * @pf: the PF to cleanup369 *370 * Unregisters the devlink_port structure associated with this PF.371 * This function has to be called under devl_lock.372 */373void ice_devlink_destroy_pf_port(struct ice_pf *pf)374{375	devl_port_unregister(&pf->devlink_port);376}377 378/**379 * ice_devlink_port_get_vf_fn_mac - .port_fn_hw_addr_get devlink handler380 * @port: devlink port structure381 * @hw_addr: MAC address of the port382 * @hw_addr_len: length of MAC address383 * @extack: extended netdev ack structure384 *385 * Callback for the devlink .port_fn_hw_addr_get operation386 * Return: zero on success or an error code on failure.387 */388static int ice_devlink_port_get_vf_fn_mac(struct devlink_port *port,389					  u8 *hw_addr, int *hw_addr_len,390					  struct netlink_ext_ack *extack)391{392	struct ice_vf *vf = container_of(port, struct ice_vf, devlink_port);393 394	ether_addr_copy(hw_addr, vf->dev_lan_addr);395	*hw_addr_len = ETH_ALEN;396 397	return 0;398}399 400/**401 * ice_devlink_port_set_vf_fn_mac - .port_fn_hw_addr_set devlink handler402 * @port: devlink port structure403 * @hw_addr: MAC address of the port404 * @hw_addr_len: length of MAC address405 * @extack: extended netdev ack structure406 *407 * Callback for the devlink .port_fn_hw_addr_set operation408 * Return: zero on success or an error code on failure.409 */410static int ice_devlink_port_set_vf_fn_mac(struct devlink_port *port,411					  const u8 *hw_addr,412					  int hw_addr_len,413					  struct netlink_ext_ack *extack)414 415{416	struct devlink_port_attrs *attrs = &port->attrs;417	struct devlink_port_pci_vf_attrs *pci_vf;418	struct devlink *devlink = port->devlink;419	struct ice_pf *pf;420	u16 vf_id;421 422	pf = devlink_priv(devlink);423	pci_vf = &attrs->pci_vf;424	vf_id = pci_vf->vf;425 426	return __ice_set_vf_mac(pf, vf_id, hw_addr);427}428 429static const struct devlink_port_ops ice_devlink_vf_port_ops = {430	.port_fn_hw_addr_get = ice_devlink_port_get_vf_fn_mac,431	.port_fn_hw_addr_set = ice_devlink_port_set_vf_fn_mac,432};433 434/**435 * ice_devlink_create_vf_port - Create a devlink port for this VF436 * @vf: the VF to create a port for437 *438 * Create and register a devlink_port for this VF.439 *440 * Return: zero on success or an error code on failure.441 */442int ice_devlink_create_vf_port(struct ice_vf *vf)443{444	struct devlink_port_attrs attrs = {};445	struct devlink_port *devlink_port;446	struct devlink *devlink;447	struct ice_vsi *vsi;448	struct device *dev;449	struct ice_pf *pf;450	int err;451 452	pf = vf->pf;453	dev = ice_pf_to_dev(pf);454	devlink_port = &vf->devlink_port;455 456	vsi = ice_get_vf_vsi(vf);457	if (!vsi)458		return -EINVAL;459 460	attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF;461	attrs.pci_vf.pf = pf->hw.pf_id;462	attrs.pci_vf.vf = vf->vf_id;463 464	ice_devlink_set_switch_id(pf, &attrs.switch_id);465 466	devlink_port_attrs_set(devlink_port, &attrs);467	devlink = priv_to_devlink(pf);468 469	err = devl_port_register_with_ops(devlink, devlink_port, vsi->idx,470					  &ice_devlink_vf_port_ops);471	if (err) {472		dev_err(dev, "Failed to create devlink port for VF %d, error %d\n",473			vf->vf_id, err);474		return err;475	}476 477	return 0;478}479 480/**481 * ice_devlink_destroy_vf_port - Destroy the devlink_port for this VF482 * @vf: the VF to cleanup483 *484 * Unregisters the devlink_port structure associated with this VF.485 */486void ice_devlink_destroy_vf_port(struct ice_vf *vf)487{488	devl_rate_leaf_destroy(&vf->devlink_port);489	devl_port_unregister(&vf->devlink_port);490}491 492/**493 * ice_devlink_create_sf_dev_port - Register virtual port for a subfunction494 * @sf_dev: the subfunction device to create a devlink port for495 *496 * Register virtual flavour devlink port for the subfunction auxiliary device497 * created after activating a dynamically added devlink port.498 *499 * Return: zero on success or an error code on failure.500 */501int ice_devlink_create_sf_dev_port(struct ice_sf_dev *sf_dev)502{503	struct devlink_port_attrs attrs = {};504	struct ice_dynamic_port *dyn_port;505	struct devlink_port *devlink_port;506	struct devlink *devlink;507	struct ice_vsi *vsi;508 509	dyn_port = sf_dev->dyn_port;510	vsi = dyn_port->vsi;511 512	devlink_port = &sf_dev->priv->devlink_port;513 514	attrs.flavour = DEVLINK_PORT_FLAVOUR_VIRTUAL;515 516	devlink_port_attrs_set(devlink_port, &attrs);517	devlink = priv_to_devlink(sf_dev->priv);518 519	return devl_port_register(devlink, devlink_port, vsi->idx);520}521 522/**523 * ice_devlink_destroy_sf_dev_port - Destroy virtual port for a subfunction524 * @sf_dev: the subfunction device to create a devlink port for525 *526 * Unregisters the virtual port associated with this subfunction.527 */528void ice_devlink_destroy_sf_dev_port(struct ice_sf_dev *sf_dev)529{530	devl_port_unregister(&sf_dev->priv->devlink_port);531}532 533/**534 * ice_activate_dynamic_port - Activate a dynamic port535 * @dyn_port: dynamic port instance to activate536 * @extack: extack for reporting error messages537 *538 * Activate the dynamic port based on its flavour.539 *540 * Return: zero on success or an error code on failure.541 */542static int543ice_activate_dynamic_port(struct ice_dynamic_port *dyn_port,544			  struct netlink_ext_ack *extack)545{546	int err;547 548	if (dyn_port->active)549		return 0;550 551	err = ice_sf_eth_activate(dyn_port, extack);552	if (err)553		return err;554 555	dyn_port->active = true;556 557	return 0;558}559 560/**561 * ice_deactivate_dynamic_port - Deactivate a dynamic port562 * @dyn_port: dynamic port instance to deactivate563 *564 * Undo activation of a dynamic port.565 */566static void ice_deactivate_dynamic_port(struct ice_dynamic_port *dyn_port)567{568	if (!dyn_port->active)569		return;570 571	ice_sf_eth_deactivate(dyn_port);572	dyn_port->active = false;573}574 575/**576 * ice_dealloc_dynamic_port - Deallocate and remove a dynamic port577 * @dyn_port: dynamic port instance to deallocate578 *579 * Free resources associated with a dynamically added devlink port. Will580 * deactivate the port if its currently active.581 */582static void ice_dealloc_dynamic_port(struct ice_dynamic_port *dyn_port)583{584	struct devlink_port *devlink_port = &dyn_port->devlink_port;585	struct ice_pf *pf = dyn_port->pf;586 587	ice_deactivate_dynamic_port(dyn_port);588 589	xa_erase(&pf->sf_nums, devlink_port->attrs.pci_sf.sf);590	ice_eswitch_detach_sf(pf, dyn_port);591	ice_vsi_free(dyn_port->vsi);592	xa_erase(&pf->dyn_ports, dyn_port->vsi->idx);593	kfree(dyn_port);594}595 596/**597 * ice_dealloc_all_dynamic_ports - Deallocate all dynamic devlink ports598 * @pf: pointer to the pf structure599 */600void ice_dealloc_all_dynamic_ports(struct ice_pf *pf)601{602	struct ice_dynamic_port *dyn_port;603	unsigned long index;604 605	xa_for_each(&pf->dyn_ports, index, dyn_port)606		ice_dealloc_dynamic_port(dyn_port);607}608 609/**610 * ice_devlink_port_new_check_attr - Check that new port attributes are valid611 * @pf: pointer to the PF structure612 * @new_attr: the attributes for the new port613 * @extack: extack for reporting error messages614 *615 * Check that the attributes for the new port are valid before continuing to616 * allocate the devlink port.617 *618 * Return: zero on success or an error code on failure.619 */620static int621ice_devlink_port_new_check_attr(struct ice_pf *pf,622				const struct devlink_port_new_attrs *new_attr,623				struct netlink_ext_ack *extack)624{625	if (new_attr->flavour != DEVLINK_PORT_FLAVOUR_PCI_SF) {626		NL_SET_ERR_MSG_MOD(extack, "Flavour other than pcisf is not supported");627		return -EOPNOTSUPP;628	}629 630	if (new_attr->controller_valid) {631		NL_SET_ERR_MSG_MOD(extack, "Setting controller is not supported");632		return -EOPNOTSUPP;633	}634 635	if (new_attr->port_index_valid) {636		NL_SET_ERR_MSG_MOD(extack, "Driver does not support user defined port index assignment");637		return -EOPNOTSUPP;638	}639 640	if (new_attr->pfnum != pf->hw.pf_id) {641		NL_SET_ERR_MSG_MOD(extack, "Incorrect pfnum supplied");642		return -EINVAL;643	}644 645	if (!pci_msix_can_alloc_dyn(pf->pdev)) {646		NL_SET_ERR_MSG_MOD(extack, "Dynamic MSIX-X interrupt allocation is not supported");647		return -EOPNOTSUPP;648	}649 650	return 0;651}652 653/**654 * ice_devlink_port_del - devlink handler for port delete655 * @devlink: pointer to devlink656 * @port: devlink port to be deleted657 * @extack: pointer to extack658 *659 * Deletes devlink port and deallocates all resources associated with660 * created subfunction.661 *662 * Return: zero on success or an error code on failure.663 */664static int665ice_devlink_port_del(struct devlink *devlink, struct devlink_port *port,666		     struct netlink_ext_ack *extack)667{668	struct ice_dynamic_port *dyn_port;669 670	dyn_port = ice_devlink_port_to_dyn(port);671	ice_dealloc_dynamic_port(dyn_port);672 673	return 0;674}675 676/**677 * ice_devlink_port_fn_hw_addr_set - devlink handler for mac address set678 * @port: pointer to devlink port679 * @hw_addr: hw address to set680 * @hw_addr_len: hw address length681 * @extack: extack for reporting error messages682 *683 * Sets mac address for the port, verifies arguments and copies address684 * to the subfunction structure.685 *686 * Return: zero on success or an error code on failure.687 */688static int689ice_devlink_port_fn_hw_addr_set(struct devlink_port *port, const u8 *hw_addr,690				int hw_addr_len,691				struct netlink_ext_ack *extack)692{693	struct ice_dynamic_port *dyn_port;694 695	dyn_port = ice_devlink_port_to_dyn(port);696 697	if (dyn_port->attached) {698		NL_SET_ERR_MSG_MOD(extack,699				   "Ethernet address can be change only in detached state");700		return -EBUSY;701	}702 703	if (hw_addr_len != ETH_ALEN || !is_valid_ether_addr(hw_addr)) {704		NL_SET_ERR_MSG_MOD(extack, "Invalid ethernet address");705		return -EADDRNOTAVAIL;706	}707 708	ether_addr_copy(dyn_port->hw_addr, hw_addr);709 710	return 0;711}712 713/**714 * ice_devlink_port_fn_hw_addr_get - devlink handler for mac address get715 * @port: pointer to devlink port716 * @hw_addr: hw address to set717 * @hw_addr_len: hw address length718 * @extack: extack for reporting error messages719 *720 * Returns mac address for the port.721 *722 * Return: zero on success or an error code on failure.723 */724static int725ice_devlink_port_fn_hw_addr_get(struct devlink_port *port, u8 *hw_addr,726				int *hw_addr_len,727				struct netlink_ext_ack *extack)728{729	struct ice_dynamic_port *dyn_port;730 731	dyn_port = ice_devlink_port_to_dyn(port);732 733	ether_addr_copy(hw_addr, dyn_port->hw_addr);734	*hw_addr_len = ETH_ALEN;735 736	return 0;737}738 739/**740 * ice_devlink_port_fn_state_set - devlink handler for port state set741 * @port: pointer to devlink port742 * @state: state to set743 * @extack: extack for reporting error messages744 *745 * Activates or deactivates the port.746 *747 * Return: zero on success or an error code on failure.748 */749static int750ice_devlink_port_fn_state_set(struct devlink_port *port,751			      enum devlink_port_fn_state state,752			      struct netlink_ext_ack *extack)753{754	struct ice_dynamic_port *dyn_port;755 756	dyn_port = ice_devlink_port_to_dyn(port);757 758	switch (state) {759	case DEVLINK_PORT_FN_STATE_ACTIVE:760		return ice_activate_dynamic_port(dyn_port, extack);761 762	case DEVLINK_PORT_FN_STATE_INACTIVE:763		ice_deactivate_dynamic_port(dyn_port);764		break;765	}766 767	return 0;768}769 770/**771 * ice_devlink_port_fn_state_get - devlink handler for port state get772 * @port: pointer to devlink port773 * @state: admin configured state of the port774 * @opstate: current port operational state775 * @extack: extack for reporting error messages776 *777 * Gets port state.778 *779 * Return: zero on success or an error code on failure.780 */781static int782ice_devlink_port_fn_state_get(struct devlink_port *port,783			      enum devlink_port_fn_state *state,784			      enum devlink_port_fn_opstate *opstate,785			      struct netlink_ext_ack *extack)786{787	struct ice_dynamic_port *dyn_port;788 789	dyn_port = ice_devlink_port_to_dyn(port);790 791	if (dyn_port->active)792		*state = DEVLINK_PORT_FN_STATE_ACTIVE;793	else794		*state = DEVLINK_PORT_FN_STATE_INACTIVE;795 796	if (dyn_port->attached)797		*opstate = DEVLINK_PORT_FN_OPSTATE_ATTACHED;798	else799		*opstate = DEVLINK_PORT_FN_OPSTATE_DETACHED;800 801	return 0;802}803 804static const struct devlink_port_ops ice_devlink_port_sf_ops = {805	.port_del = ice_devlink_port_del,806	.port_fn_hw_addr_get = ice_devlink_port_fn_hw_addr_get,807	.port_fn_hw_addr_set = ice_devlink_port_fn_hw_addr_set,808	.port_fn_state_get = ice_devlink_port_fn_state_get,809	.port_fn_state_set = ice_devlink_port_fn_state_set,810};811 812/**813 * ice_reserve_sf_num - Reserve a subfunction number for this port814 * @pf: pointer to the pf structure815 * @new_attr: devlink port attributes requested816 * @extack: extack for reporting error messages817 * @sfnum: on success, the sf number reserved818 *819 * Reserve a subfunction number for this port. Only called for820 * DEVLINK_PORT_FLAVOUR_PCI_SF ports.821 *822 * Return: zero on success or an error code on failure.823 */824static int825ice_reserve_sf_num(struct ice_pf *pf,826		   const struct devlink_port_new_attrs *new_attr,827		   struct netlink_ext_ack *extack, u32 *sfnum)828{829	int err;830 831	/* If user didn't request an explicit number, pick one */832	if (!new_attr->sfnum_valid)833		return xa_alloc(&pf->sf_nums, sfnum, NULL, xa_limit_32b,834				GFP_KERNEL);835 836	/* Otherwise, check and use the number provided */837	err = xa_insert(&pf->sf_nums, new_attr->sfnum, NULL, GFP_KERNEL);838	if (err) {839		if (err == -EBUSY)840			NL_SET_ERR_MSG_MOD(extack, "Subfunction with given sfnum already exists");841		return err;842	}843 844	*sfnum = new_attr->sfnum;845 846	return 0;847}848 849/**850 * ice_devlink_create_sf_port - Register PCI subfunction devlink port851 * @dyn_port: the dynamic port instance structure for this subfunction852 *853 * Register PCI subfunction flavour devlink port for a dynamically added854 * subfunction port.855 *856 * Return: zero on success or an error code on failure.857 */858int ice_devlink_create_sf_port(struct ice_dynamic_port *dyn_port)859{860	struct devlink_port_attrs attrs = {};861	struct devlink_port *devlink_port;862	struct devlink *devlink;863	struct ice_vsi *vsi;864	struct ice_pf *pf;865 866	vsi = dyn_port->vsi;867	pf = dyn_port->pf;868 869	devlink_port = &dyn_port->devlink_port;870 871	attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_SF;872	attrs.pci_sf.pf = pf->hw.pf_id;873	attrs.pci_sf.sf = dyn_port->sfnum;874 875	devlink_port_attrs_set(devlink_port, &attrs);876	devlink = priv_to_devlink(pf);877 878	return devl_port_register_with_ops(devlink, devlink_port, vsi->idx,879					   &ice_devlink_port_sf_ops);880}881 882/**883 * ice_devlink_destroy_sf_port - Destroy the devlink_port for this SF884 * @dyn_port: the dynamic port instance structure for this subfunction885 *886 * Unregisters the devlink_port structure associated with this SF.887 */888void ice_devlink_destroy_sf_port(struct ice_dynamic_port *dyn_port)889{890	devl_rate_leaf_destroy(&dyn_port->devlink_port);891	devl_port_unregister(&dyn_port->devlink_port);892}893 894/**895 * ice_alloc_dynamic_port - Allocate new dynamic port896 * @pf: pointer to the pf structure897 * @new_attr: devlink port attributes requested898 * @extack: extack for reporting error messages899 * @devlink_port: index of newly created devlink port900 *901 * Allocate a new dynamic port instance and prepare it for configuration902 * with devlink.903 *904 * Return: zero on success or an error code on failure.905 */906static int907ice_alloc_dynamic_port(struct ice_pf *pf,908		       const struct devlink_port_new_attrs *new_attr,909		       struct netlink_ext_ack *extack,910		       struct devlink_port **devlink_port)911{912	struct ice_dynamic_port *dyn_port;913	struct ice_vsi *vsi;914	u32 sfnum;915	int err;916 917	err = ice_reserve_sf_num(pf, new_attr, extack, &sfnum);918	if (err)919		return err;920 921	dyn_port = kzalloc(sizeof(*dyn_port), GFP_KERNEL);922	if (!dyn_port) {923		err = -ENOMEM;924		goto unroll_reserve_sf_num;925	}926 927	vsi = ice_vsi_alloc(pf);928	if (!vsi) {929		NL_SET_ERR_MSG_MOD(extack, "Unable to allocate VSI");930		err = -ENOMEM;931		goto unroll_dyn_port_alloc;932	}933 934	dyn_port->vsi = vsi;935	dyn_port->pf = pf;936	dyn_port->sfnum = sfnum;937	eth_random_addr(dyn_port->hw_addr);938 939	err = xa_insert(&pf->dyn_ports, vsi->idx, dyn_port, GFP_KERNEL);940	if (err) {941		NL_SET_ERR_MSG_MOD(extack, "Port index reservation failed");942		goto unroll_vsi_alloc;943	}944 945	err = ice_eswitch_attach_sf(pf, dyn_port);946	if (err) {947		NL_SET_ERR_MSG_MOD(extack, "Failed to attach SF to eswitch");948		goto unroll_xa_insert;949	}950 951	*devlink_port = &dyn_port->devlink_port;952 953	return 0;954 955unroll_xa_insert:956	xa_erase(&pf->dyn_ports, vsi->idx);957unroll_vsi_alloc:958	ice_vsi_free(vsi);959unroll_dyn_port_alloc:960	kfree(dyn_port);961unroll_reserve_sf_num:962	xa_erase(&pf->sf_nums, sfnum);963 964	return err;965}966 967/**968 * ice_devlink_port_new - devlink handler for the new port969 * @devlink: pointer to devlink970 * @new_attr: pointer to the port new attributes971 * @extack: extack for reporting error messages972 * @devlink_port: pointer to a new port973 *974 * Creates new devlink port, checks new port attributes and reject975 * any unsupported parameters, allocates new subfunction for that port.976 *977 * Return: zero on success or an error code on failure.978 */979int980ice_devlink_port_new(struct devlink *devlink,981		     const struct devlink_port_new_attrs *new_attr,982		     struct netlink_ext_ack *extack,983		     struct devlink_port **devlink_port)984{985	struct ice_pf *pf = devlink_priv(devlink);986	int err;987 988	err = ice_devlink_port_new_check_attr(pf, new_attr, extack);989	if (err)990		return err;991 992	if (!ice_is_eswitch_mode_switchdev(pf)) {993		NL_SET_ERR_MSG_MOD(extack,994				   "SF ports are only supported in eswitch switchdev mode");995		return -EOPNOTSUPP;996	}997 998	return ice_alloc_dynamic_port(pf, new_attr, extack, devlink_port);999}1000