xref: /linux/drivers/net/ethernet/intel/ice/devlink/port.c (revision 8be4d31cb8aaeea27bde4b7ddb26e28a89062ebf)
12846fe56SPrzemek Kitszel // SPDX-License-Identifier: GPL-2.0
22846fe56SPrzemek Kitszel /* Copyright (c) 2024, Intel Corporation. */
32846fe56SPrzemek Kitszel 
42846fe56SPrzemek Kitszel #include <linux/vmalloc.h>
52846fe56SPrzemek Kitszel 
62846fe56SPrzemek Kitszel #include "ice.h"
72846fe56SPrzemek Kitszel #include "devlink.h"
82846fe56SPrzemek Kitszel #include "port.h"
92846fe56SPrzemek Kitszel #include "ice_lib.h"
102846fe56SPrzemek Kitszel #include "ice_fltr.h"
112846fe56SPrzemek Kitszel 
122846fe56SPrzemek Kitszel static int ice_active_port_option = -1;
132846fe56SPrzemek Kitszel 
142846fe56SPrzemek Kitszel /**
152846fe56SPrzemek Kitszel  * ice_devlink_port_opt_speed_str - convert speed to a string
162846fe56SPrzemek Kitszel  * @speed: speed value
172846fe56SPrzemek Kitszel  */
ice_devlink_port_opt_speed_str(u8 speed)182846fe56SPrzemek Kitszel static const char *ice_devlink_port_opt_speed_str(u8 speed)
192846fe56SPrzemek Kitszel {
202846fe56SPrzemek Kitszel 	switch (speed & ICE_AQC_PORT_OPT_MAX_LANE_M) {
212846fe56SPrzemek Kitszel 	case ICE_AQC_PORT_OPT_MAX_LANE_100M:
222846fe56SPrzemek Kitszel 		return "0.1";
232846fe56SPrzemek Kitszel 	case ICE_AQC_PORT_OPT_MAX_LANE_1G:
242846fe56SPrzemek Kitszel 		return "1";
252846fe56SPrzemek Kitszel 	case ICE_AQC_PORT_OPT_MAX_LANE_2500M:
262846fe56SPrzemek Kitszel 		return "2.5";
272846fe56SPrzemek Kitszel 	case ICE_AQC_PORT_OPT_MAX_LANE_5G:
282846fe56SPrzemek Kitszel 		return "5";
292846fe56SPrzemek Kitszel 	case ICE_AQC_PORT_OPT_MAX_LANE_10G:
302846fe56SPrzemek Kitszel 		return "10";
312846fe56SPrzemek Kitszel 	case ICE_AQC_PORT_OPT_MAX_LANE_25G:
322846fe56SPrzemek Kitszel 		return "25";
33*9419c438SAleksandr Loktionov 	case ICE_AQC_PORT_OPT_MAX_LANE_40G:
34*9419c438SAleksandr Loktionov 		return "40";
352846fe56SPrzemek Kitszel 	case ICE_AQC_PORT_OPT_MAX_LANE_50G:
362846fe56SPrzemek Kitszel 		return "50";
372846fe56SPrzemek Kitszel 	case ICE_AQC_PORT_OPT_MAX_LANE_100G:
382846fe56SPrzemek Kitszel 		return "100";
392846fe56SPrzemek Kitszel 	}
402846fe56SPrzemek Kitszel 
412846fe56SPrzemek Kitszel 	return "-";
422846fe56SPrzemek Kitszel }
432846fe56SPrzemek Kitszel 
442846fe56SPrzemek Kitszel #define ICE_PORT_OPT_DESC_LEN	50
452846fe56SPrzemek Kitszel /**
462846fe56SPrzemek Kitszel  * ice_devlink_port_options_print - Print available port split options
472846fe56SPrzemek Kitszel  * @pf: the PF to print split port options
482846fe56SPrzemek Kitszel  *
492846fe56SPrzemek Kitszel  * Prints a table with available port split options and max port speeds
502846fe56SPrzemek Kitszel  */
ice_devlink_port_options_print(struct ice_pf * pf)512846fe56SPrzemek Kitszel static void ice_devlink_port_options_print(struct ice_pf *pf)
522846fe56SPrzemek Kitszel {
532846fe56SPrzemek Kitszel 	u8 i, j, options_count, cnt, speed, pending_idx, active_idx;
542846fe56SPrzemek Kitszel 	struct ice_aqc_get_port_options_elem *options, *opt;
552846fe56SPrzemek Kitszel 	struct device *dev = ice_pf_to_dev(pf);
562846fe56SPrzemek Kitszel 	bool active_valid, pending_valid;
572846fe56SPrzemek Kitszel 	char desc[ICE_PORT_OPT_DESC_LEN];
582846fe56SPrzemek Kitszel 	const char *str;
592846fe56SPrzemek Kitszel 	int status;
602846fe56SPrzemek Kitszel 
612846fe56SPrzemek Kitszel 	options = kcalloc(ICE_AQC_PORT_OPT_MAX * ICE_MAX_PORT_PER_PCI_DEV,
622846fe56SPrzemek Kitszel 			  sizeof(*options), GFP_KERNEL);
632846fe56SPrzemek Kitszel 	if (!options)
642846fe56SPrzemek Kitszel 		return;
652846fe56SPrzemek Kitszel 
662846fe56SPrzemek Kitszel 	for (i = 0; i < ICE_MAX_PORT_PER_PCI_DEV; i++) {
672846fe56SPrzemek Kitszel 		opt = options + i * ICE_AQC_PORT_OPT_MAX;
682846fe56SPrzemek Kitszel 		options_count = ICE_AQC_PORT_OPT_MAX;
692846fe56SPrzemek Kitszel 		active_valid = 0;
702846fe56SPrzemek Kitszel 
712846fe56SPrzemek Kitszel 		status = ice_aq_get_port_options(&pf->hw, opt, &options_count,
722846fe56SPrzemek Kitszel 						 i, true, &active_idx,
732846fe56SPrzemek Kitszel 						 &active_valid, &pending_idx,
742846fe56SPrzemek Kitszel 						 &pending_valid);
752846fe56SPrzemek Kitszel 		if (status) {
762846fe56SPrzemek Kitszel 			dev_dbg(dev, "Couldn't read port option for port %d, err %d\n",
772846fe56SPrzemek Kitszel 				i, status);
782846fe56SPrzemek Kitszel 			goto err;
792846fe56SPrzemek Kitszel 		}
802846fe56SPrzemek Kitszel 	}
812846fe56SPrzemek Kitszel 
822846fe56SPrzemek Kitszel 	dev_dbg(dev, "Available port split options and max port speeds (Gbps):\n");
832846fe56SPrzemek Kitszel 	dev_dbg(dev, "Status  Split      Quad 0          Quad 1\n");
842846fe56SPrzemek Kitszel 	dev_dbg(dev, "        count  L0  L1  L2  L3  L4  L5  L6  L7\n");
852846fe56SPrzemek Kitszel 
862846fe56SPrzemek Kitszel 	for (i = 0; i < options_count; i++) {
872846fe56SPrzemek Kitszel 		cnt = 0;
882846fe56SPrzemek Kitszel 
892846fe56SPrzemek Kitszel 		if (i == ice_active_port_option)
902846fe56SPrzemek Kitszel 			str = "Active";
912846fe56SPrzemek Kitszel 		else if ((i == pending_idx) && pending_valid)
922846fe56SPrzemek Kitszel 			str = "Pending";
932846fe56SPrzemek Kitszel 		else
942846fe56SPrzemek Kitszel 			str = "";
952846fe56SPrzemek Kitszel 
962846fe56SPrzemek Kitszel 		cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
972846fe56SPrzemek Kitszel 				"%-8s", str);
982846fe56SPrzemek Kitszel 
992846fe56SPrzemek Kitszel 		cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
1002846fe56SPrzemek Kitszel 				"%-6u", options[i].pmd);
1012846fe56SPrzemek Kitszel 
1022846fe56SPrzemek Kitszel 		for (j = 0; j < ICE_MAX_PORT_PER_PCI_DEV; ++j) {
1032846fe56SPrzemek Kitszel 			speed = options[i + j * ICE_AQC_PORT_OPT_MAX].max_lane_speed;
1042846fe56SPrzemek Kitszel 			str = ice_devlink_port_opt_speed_str(speed);
1052846fe56SPrzemek Kitszel 			cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
1062846fe56SPrzemek Kitszel 					"%3s ", str);
1072846fe56SPrzemek Kitszel 		}
1082846fe56SPrzemek Kitszel 
1092846fe56SPrzemek Kitszel 		dev_dbg(dev, "%s\n", desc);
1102846fe56SPrzemek Kitszel 	}
1112846fe56SPrzemek Kitszel 
1122846fe56SPrzemek Kitszel err:
1132846fe56SPrzemek Kitszel 	kfree(options);
1142846fe56SPrzemek Kitszel }
1152846fe56SPrzemek Kitszel 
1162846fe56SPrzemek Kitszel /**
1172846fe56SPrzemek Kitszel  * ice_devlink_aq_set_port_option - Send set port option admin queue command
1182846fe56SPrzemek Kitszel  * @pf: the PF to print split port options
1192846fe56SPrzemek Kitszel  * @option_idx: selected port option
1202846fe56SPrzemek Kitszel  * @extack: extended netdev ack structure
1212846fe56SPrzemek Kitszel  *
1222846fe56SPrzemek Kitszel  * Sends set port option admin queue command with selected port option and
1232846fe56SPrzemek Kitszel  * calls NVM write activate.
1242846fe56SPrzemek Kitszel  */
1252846fe56SPrzemek Kitszel static int
ice_devlink_aq_set_port_option(struct ice_pf * pf,u8 option_idx,struct netlink_ext_ack * extack)1262846fe56SPrzemek Kitszel ice_devlink_aq_set_port_option(struct ice_pf *pf, u8 option_idx,
1272846fe56SPrzemek Kitszel 			       struct netlink_ext_ack *extack)
1282846fe56SPrzemek Kitszel {
1292846fe56SPrzemek Kitszel 	struct device *dev = ice_pf_to_dev(pf);
1302846fe56SPrzemek Kitszel 	int status;
1312846fe56SPrzemek Kitszel 
1322846fe56SPrzemek Kitszel 	status = ice_aq_set_port_option(&pf->hw, 0, true, option_idx);
1332846fe56SPrzemek Kitszel 	if (status) {
1342846fe56SPrzemek Kitszel 		dev_dbg(dev, "ice_aq_set_port_option, err %d aq_err %d\n",
1352846fe56SPrzemek Kitszel 			status, pf->hw.adminq.sq_last_status);
1362846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack, "Port split request failed");
1372846fe56SPrzemek Kitszel 		return -EIO;
1382846fe56SPrzemek Kitszel 	}
1392846fe56SPrzemek Kitszel 
1402846fe56SPrzemek Kitszel 	status = ice_acquire_nvm(&pf->hw, ICE_RES_WRITE);
1412846fe56SPrzemek Kitszel 	if (status) {
1422846fe56SPrzemek Kitszel 		dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
1432846fe56SPrzemek Kitszel 			status, pf->hw.adminq.sq_last_status);
1442846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
1452846fe56SPrzemek Kitszel 		return -EIO;
1462846fe56SPrzemek Kitszel 	}
1472846fe56SPrzemek Kitszel 
1482846fe56SPrzemek Kitszel 	status = ice_nvm_write_activate(&pf->hw, ICE_AQC_NVM_ACTIV_REQ_EMPR, NULL);
1492846fe56SPrzemek Kitszel 	if (status) {
1502846fe56SPrzemek Kitszel 		dev_dbg(dev, "ice_nvm_write_activate failed, err %d aq_err %d\n",
1512846fe56SPrzemek Kitszel 			status, pf->hw.adminq.sq_last_status);
1522846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack, "Port split request failed to save data");
1532846fe56SPrzemek Kitszel 		ice_release_nvm(&pf->hw);
1542846fe56SPrzemek Kitszel 		return -EIO;
1552846fe56SPrzemek Kitszel 	}
1562846fe56SPrzemek Kitszel 
1572846fe56SPrzemek Kitszel 	ice_release_nvm(&pf->hw);
1582846fe56SPrzemek Kitszel 
1592846fe56SPrzemek Kitszel 	NL_SET_ERR_MSG_MOD(extack, "Reboot required to finish port split");
1602846fe56SPrzemek Kitszel 	return 0;
1612846fe56SPrzemek Kitszel }
1622846fe56SPrzemek Kitszel 
1632846fe56SPrzemek Kitszel /**
1642846fe56SPrzemek Kitszel  * ice_devlink_port_split - .port_split devlink handler
1652846fe56SPrzemek Kitszel  * @devlink: devlink instance structure
1662846fe56SPrzemek Kitszel  * @port: devlink port structure
1672846fe56SPrzemek Kitszel  * @count: number of ports to split to
1682846fe56SPrzemek Kitszel  * @extack: extended netdev ack structure
1692846fe56SPrzemek Kitszel  *
1702846fe56SPrzemek Kitszel  * Callback for the devlink .port_split operation.
1712846fe56SPrzemek Kitszel  *
1722846fe56SPrzemek Kitszel  * Unfortunately, the devlink expression of available options is limited
1732846fe56SPrzemek Kitszel  * to just a number, so search for an FW port option which supports
1742846fe56SPrzemek Kitszel  * the specified number. As there could be multiple FW port options with
1752846fe56SPrzemek Kitszel  * the same port split count, allow switching between them. When the same
1762846fe56SPrzemek Kitszel  * port split count request is issued again, switch to the next FW port
1772846fe56SPrzemek Kitszel  * option with the same port split count.
1782846fe56SPrzemek Kitszel  *
1792846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
1802846fe56SPrzemek Kitszel  */
1812846fe56SPrzemek Kitszel static int
ice_devlink_port_split(struct devlink * devlink,struct devlink_port * port,unsigned int count,struct netlink_ext_ack * extack)1822846fe56SPrzemek Kitszel ice_devlink_port_split(struct devlink *devlink, struct devlink_port *port,
1832846fe56SPrzemek Kitszel 		       unsigned int count, struct netlink_ext_ack *extack)
1842846fe56SPrzemek Kitszel {
1852846fe56SPrzemek Kitszel 	struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX];
1862846fe56SPrzemek Kitszel 	u8 i, j, active_idx, pending_idx, new_option;
1872846fe56SPrzemek Kitszel 	struct ice_pf *pf = devlink_priv(devlink);
1882846fe56SPrzemek Kitszel 	u8 option_count = ICE_AQC_PORT_OPT_MAX;
1892846fe56SPrzemek Kitszel 	struct device *dev = ice_pf_to_dev(pf);
1902846fe56SPrzemek Kitszel 	bool active_valid, pending_valid;
1912846fe56SPrzemek Kitszel 	int status;
1922846fe56SPrzemek Kitszel 
1932846fe56SPrzemek Kitszel 	status = ice_aq_get_port_options(&pf->hw, options, &option_count,
1942846fe56SPrzemek Kitszel 					 0, true, &active_idx, &active_valid,
1952846fe56SPrzemek Kitszel 					 &pending_idx, &pending_valid);
1962846fe56SPrzemek Kitszel 	if (status) {
1972846fe56SPrzemek Kitszel 		dev_dbg(dev, "Couldn't read port split options, err = %d\n",
1982846fe56SPrzemek Kitszel 			status);
1992846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack, "Failed to get available port split options");
2002846fe56SPrzemek Kitszel 		return -EIO;
2012846fe56SPrzemek Kitszel 	}
2022846fe56SPrzemek Kitszel 
2032846fe56SPrzemek Kitszel 	new_option = ICE_AQC_PORT_OPT_MAX;
2042846fe56SPrzemek Kitszel 	active_idx = pending_valid ? pending_idx : active_idx;
2052846fe56SPrzemek Kitszel 	for (i = 1; i <= option_count; i++) {
2062846fe56SPrzemek Kitszel 		/* In order to allow switching between FW port options with
2072846fe56SPrzemek Kitszel 		 * the same port split count, search for a new option starting
2082846fe56SPrzemek Kitszel 		 * from the active/pending option (with array wrap around).
2092846fe56SPrzemek Kitszel 		 */
2102846fe56SPrzemek Kitszel 		j = (active_idx + i) % option_count;
2112846fe56SPrzemek Kitszel 
2122846fe56SPrzemek Kitszel 		if (count == options[j].pmd) {
2132846fe56SPrzemek Kitszel 			new_option = j;
2142846fe56SPrzemek Kitszel 			break;
2152846fe56SPrzemek Kitszel 		}
2162846fe56SPrzemek Kitszel 	}
2172846fe56SPrzemek Kitszel 
2182846fe56SPrzemek Kitszel 	if (new_option == active_idx) {
2192846fe56SPrzemek Kitszel 		dev_dbg(dev, "request to split: count: %u is already set and there are no other options\n",
2202846fe56SPrzemek Kitszel 			count);
2212846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack, "Requested split count is already set");
2222846fe56SPrzemek Kitszel 		ice_devlink_port_options_print(pf);
2232846fe56SPrzemek Kitszel 		return -EINVAL;
2242846fe56SPrzemek Kitszel 	}
2252846fe56SPrzemek Kitszel 
2262846fe56SPrzemek Kitszel 	if (new_option == ICE_AQC_PORT_OPT_MAX) {
2272846fe56SPrzemek Kitszel 		dev_dbg(dev, "request to split: count: %u not found\n", count);
2282846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack, "Port split requested unsupported port config");
2292846fe56SPrzemek Kitszel 		ice_devlink_port_options_print(pf);
2302846fe56SPrzemek Kitszel 		return -EINVAL;
2312846fe56SPrzemek Kitszel 	}
2322846fe56SPrzemek Kitszel 
2332846fe56SPrzemek Kitszel 	status = ice_devlink_aq_set_port_option(pf, new_option, extack);
2342846fe56SPrzemek Kitszel 	if (status)
2352846fe56SPrzemek Kitszel 		return status;
2362846fe56SPrzemek Kitszel 
2372846fe56SPrzemek Kitszel 	ice_devlink_port_options_print(pf);
2382846fe56SPrzemek Kitszel 
2392846fe56SPrzemek Kitszel 	return 0;
2402846fe56SPrzemek Kitszel }
2412846fe56SPrzemek Kitszel 
2422846fe56SPrzemek Kitszel /**
2432846fe56SPrzemek Kitszel  * ice_devlink_port_unsplit - .port_unsplit devlink handler
2442846fe56SPrzemek Kitszel  * @devlink: devlink instance structure
2452846fe56SPrzemek Kitszel  * @port: devlink port structure
2462846fe56SPrzemek Kitszel  * @extack: extended netdev ack structure
2472846fe56SPrzemek Kitszel  *
2482846fe56SPrzemek Kitszel  * Callback for the devlink .port_unsplit operation.
2492846fe56SPrzemek Kitszel  * Calls ice_devlink_port_split with split count set to 1.
2502846fe56SPrzemek Kitszel  * There could be no FW option available with split count 1.
2512846fe56SPrzemek Kitszel  *
2522846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
2532846fe56SPrzemek Kitszel  */
2542846fe56SPrzemek Kitszel static int
ice_devlink_port_unsplit(struct devlink * devlink,struct devlink_port * port,struct netlink_ext_ack * extack)2552846fe56SPrzemek Kitszel ice_devlink_port_unsplit(struct devlink *devlink, struct devlink_port *port,
2562846fe56SPrzemek Kitszel 			 struct netlink_ext_ack *extack)
2572846fe56SPrzemek Kitszel {
2582846fe56SPrzemek Kitszel 	return ice_devlink_port_split(devlink, port, 1, extack);
2592846fe56SPrzemek Kitszel }
2602846fe56SPrzemek Kitszel 
2612846fe56SPrzemek Kitszel /**
2622846fe56SPrzemek Kitszel  * ice_devlink_set_port_split_options - Set port split options
2632846fe56SPrzemek Kitszel  * @pf: the PF to set port split options
2642846fe56SPrzemek Kitszel  * @attrs: devlink attributes
2652846fe56SPrzemek Kitszel  *
2662846fe56SPrzemek Kitszel  * Sets devlink port split options based on available FW port options
2672846fe56SPrzemek Kitszel  */
2682846fe56SPrzemek Kitszel static void
ice_devlink_set_port_split_options(struct ice_pf * pf,struct devlink_port_attrs * attrs)2692846fe56SPrzemek Kitszel ice_devlink_set_port_split_options(struct ice_pf *pf,
2702846fe56SPrzemek Kitszel 				   struct devlink_port_attrs *attrs)
2712846fe56SPrzemek Kitszel {
2722846fe56SPrzemek Kitszel 	struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX];
2732846fe56SPrzemek Kitszel 	u8 i, active_idx, pending_idx, option_count = ICE_AQC_PORT_OPT_MAX;
2742846fe56SPrzemek Kitszel 	bool active_valid, pending_valid;
2752846fe56SPrzemek Kitszel 	int status;
2762846fe56SPrzemek Kitszel 
2772846fe56SPrzemek Kitszel 	status = ice_aq_get_port_options(&pf->hw, options, &option_count,
2782846fe56SPrzemek Kitszel 					 0, true, &active_idx, &active_valid,
2792846fe56SPrzemek Kitszel 					 &pending_idx, &pending_valid);
2802846fe56SPrzemek Kitszel 	if (status) {
2812846fe56SPrzemek Kitszel 		dev_dbg(ice_pf_to_dev(pf), "Couldn't read port split options, err = %d\n",
2822846fe56SPrzemek Kitszel 			status);
2832846fe56SPrzemek Kitszel 		return;
2842846fe56SPrzemek Kitszel 	}
2852846fe56SPrzemek Kitszel 
2862846fe56SPrzemek Kitszel 	/* find the biggest available port split count */
2872846fe56SPrzemek Kitszel 	for (i = 0; i < option_count; i++)
2882846fe56SPrzemek Kitszel 		attrs->lanes = max_t(int, attrs->lanes, options[i].pmd);
2892846fe56SPrzemek Kitszel 
2902846fe56SPrzemek Kitszel 	attrs->splittable = attrs->lanes ? 1 : 0;
2912846fe56SPrzemek Kitszel 	ice_active_port_option = active_idx;
2922846fe56SPrzemek Kitszel }
2932846fe56SPrzemek Kitszel 
2942846fe56SPrzemek Kitszel static const struct devlink_port_ops ice_devlink_port_ops = {
2952846fe56SPrzemek Kitszel 	.port_split = ice_devlink_port_split,
2962846fe56SPrzemek Kitszel 	.port_unsplit = ice_devlink_port_unsplit,
2972846fe56SPrzemek Kitszel };
2982846fe56SPrzemek Kitszel 
2992846fe56SPrzemek Kitszel /**
3002846fe56SPrzemek Kitszel  * ice_devlink_set_switch_id - Set unique switch id based on pci dsn
3012846fe56SPrzemek Kitszel  * @pf: the PF to create a devlink port for
3022846fe56SPrzemek Kitszel  * @ppid: struct with switch id information
3032846fe56SPrzemek Kitszel  */
3042846fe56SPrzemek Kitszel static void
ice_devlink_set_switch_id(struct ice_pf * pf,struct netdev_phys_item_id * ppid)3052846fe56SPrzemek Kitszel ice_devlink_set_switch_id(struct ice_pf *pf, struct netdev_phys_item_id *ppid)
3062846fe56SPrzemek Kitszel {
3072846fe56SPrzemek Kitszel 	struct pci_dev *pdev = pf->pdev;
3082846fe56SPrzemek Kitszel 	u64 id;
3092846fe56SPrzemek Kitszel 
3102846fe56SPrzemek Kitszel 	id = pci_get_dsn(pdev);
3112846fe56SPrzemek Kitszel 
3122846fe56SPrzemek Kitszel 	ppid->id_len = sizeof(id);
3132846fe56SPrzemek Kitszel 	put_unaligned_be64(id, &ppid->id);
3142846fe56SPrzemek Kitszel }
3152846fe56SPrzemek Kitszel 
3162846fe56SPrzemek Kitszel /**
3172846fe56SPrzemek Kitszel  * ice_devlink_create_pf_port - Create a devlink port for this PF
3182846fe56SPrzemek Kitszel  * @pf: the PF to create a devlink port for
3192846fe56SPrzemek Kitszel  *
3202846fe56SPrzemek Kitszel  * Create and register a devlink_port for this PF.
3212846fe56SPrzemek Kitszel  * This function has to be called under devl_lock.
3222846fe56SPrzemek Kitszel  *
3232846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
3242846fe56SPrzemek Kitszel  */
ice_devlink_create_pf_port(struct ice_pf * pf)3252846fe56SPrzemek Kitszel int ice_devlink_create_pf_port(struct ice_pf *pf)
3262846fe56SPrzemek Kitszel {
3272846fe56SPrzemek Kitszel 	struct devlink_port_attrs attrs = {};
3282846fe56SPrzemek Kitszel 	struct devlink_port *devlink_port;
3292846fe56SPrzemek Kitszel 	struct devlink *devlink;
3302846fe56SPrzemek Kitszel 	struct ice_vsi *vsi;
3312846fe56SPrzemek Kitszel 	struct device *dev;
3322846fe56SPrzemek Kitszel 	int err;
3332846fe56SPrzemek Kitszel 
3342846fe56SPrzemek Kitszel 	devlink = priv_to_devlink(pf);
3352846fe56SPrzemek Kitszel 
3362846fe56SPrzemek Kitszel 	dev = ice_pf_to_dev(pf);
3372846fe56SPrzemek Kitszel 
3382846fe56SPrzemek Kitszel 	devlink_port = &pf->devlink_port;
3392846fe56SPrzemek Kitszel 
3402846fe56SPrzemek Kitszel 	vsi = ice_get_main_vsi(pf);
3412846fe56SPrzemek Kitszel 	if (!vsi)
3422846fe56SPrzemek Kitszel 		return -EIO;
3432846fe56SPrzemek Kitszel 
3442846fe56SPrzemek Kitszel 	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
3452846fe56SPrzemek Kitszel 	attrs.phys.port_number = pf->hw.pf_id;
3462846fe56SPrzemek Kitszel 
3472846fe56SPrzemek Kitszel 	/* As FW supports only port split options for whole device,
3482846fe56SPrzemek Kitszel 	 * set port split options only for first PF.
3492846fe56SPrzemek Kitszel 	 */
3502846fe56SPrzemek Kitszel 	if (pf->hw.pf_id == 0)
3512846fe56SPrzemek Kitszel 		ice_devlink_set_port_split_options(pf, &attrs);
3522846fe56SPrzemek Kitszel 
3532846fe56SPrzemek Kitszel 	ice_devlink_set_switch_id(pf, &attrs.switch_id);
3542846fe56SPrzemek Kitszel 
3552846fe56SPrzemek Kitszel 	devlink_port_attrs_set(devlink_port, &attrs);
3562846fe56SPrzemek Kitszel 
3572846fe56SPrzemek Kitszel 	err = devl_port_register_with_ops(devlink, devlink_port, vsi->idx,
3582846fe56SPrzemek Kitszel 					  &ice_devlink_port_ops);
3592846fe56SPrzemek Kitszel 	if (err) {
3602846fe56SPrzemek Kitszel 		dev_err(dev, "Failed to create devlink port for PF %d, error %d\n",
3612846fe56SPrzemek Kitszel 			pf->hw.pf_id, err);
3622846fe56SPrzemek Kitszel 		return err;
3632846fe56SPrzemek Kitszel 	}
3642846fe56SPrzemek Kitszel 
3652846fe56SPrzemek Kitszel 	return 0;
3662846fe56SPrzemek Kitszel }
3672846fe56SPrzemek Kitszel 
3682846fe56SPrzemek Kitszel /**
3692846fe56SPrzemek Kitszel  * ice_devlink_destroy_pf_port - Destroy the devlink_port for this PF
3702846fe56SPrzemek Kitszel  * @pf: the PF to cleanup
3712846fe56SPrzemek Kitszel  *
3722846fe56SPrzemek Kitszel  * Unregisters the devlink_port structure associated with this PF.
3732846fe56SPrzemek Kitszel  * This function has to be called under devl_lock.
3742846fe56SPrzemek Kitszel  */
ice_devlink_destroy_pf_port(struct ice_pf * pf)3752846fe56SPrzemek Kitszel void ice_devlink_destroy_pf_port(struct ice_pf *pf)
3762846fe56SPrzemek Kitszel {
3772846fe56SPrzemek Kitszel 	devl_port_unregister(&pf->devlink_port);
3782846fe56SPrzemek Kitszel }
3792846fe56SPrzemek Kitszel 
3802846fe56SPrzemek Kitszel /**
3812846fe56SPrzemek Kitszel  * ice_devlink_port_get_vf_fn_mac - .port_fn_hw_addr_get devlink handler
3822846fe56SPrzemek Kitszel  * @port: devlink port structure
3832846fe56SPrzemek Kitszel  * @hw_addr: MAC address of the port
3842846fe56SPrzemek Kitszel  * @hw_addr_len: length of MAC address
3852846fe56SPrzemek Kitszel  * @extack: extended netdev ack structure
3862846fe56SPrzemek Kitszel  *
3872846fe56SPrzemek Kitszel  * Callback for the devlink .port_fn_hw_addr_get operation
3882846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
3892846fe56SPrzemek Kitszel  */
ice_devlink_port_get_vf_fn_mac(struct devlink_port * port,u8 * hw_addr,int * hw_addr_len,struct netlink_ext_ack * extack)3902846fe56SPrzemek Kitszel static int ice_devlink_port_get_vf_fn_mac(struct devlink_port *port,
3912846fe56SPrzemek Kitszel 					  u8 *hw_addr, int *hw_addr_len,
3922846fe56SPrzemek Kitszel 					  struct netlink_ext_ack *extack)
3932846fe56SPrzemek Kitszel {
3942846fe56SPrzemek Kitszel 	struct ice_vf *vf = container_of(port, struct ice_vf, devlink_port);
3952846fe56SPrzemek Kitszel 
3962846fe56SPrzemek Kitszel 	ether_addr_copy(hw_addr, vf->dev_lan_addr);
3972846fe56SPrzemek Kitszel 	*hw_addr_len = ETH_ALEN;
3982846fe56SPrzemek Kitszel 
3992846fe56SPrzemek Kitszel 	return 0;
4002846fe56SPrzemek Kitszel }
4012846fe56SPrzemek Kitszel 
4022846fe56SPrzemek Kitszel /**
4032846fe56SPrzemek Kitszel  * ice_devlink_port_set_vf_fn_mac - .port_fn_hw_addr_set devlink handler
4042846fe56SPrzemek Kitszel  * @port: devlink port structure
4052846fe56SPrzemek Kitszel  * @hw_addr: MAC address of the port
4062846fe56SPrzemek Kitszel  * @hw_addr_len: length of MAC address
4072846fe56SPrzemek Kitszel  * @extack: extended netdev ack structure
4082846fe56SPrzemek Kitszel  *
4092846fe56SPrzemek Kitszel  * Callback for the devlink .port_fn_hw_addr_set operation
4102846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
4112846fe56SPrzemek Kitszel  */
ice_devlink_port_set_vf_fn_mac(struct devlink_port * port,const u8 * hw_addr,int hw_addr_len,struct netlink_ext_ack * extack)4122846fe56SPrzemek Kitszel static int ice_devlink_port_set_vf_fn_mac(struct devlink_port *port,
4132846fe56SPrzemek Kitszel 					  const u8 *hw_addr,
4142846fe56SPrzemek Kitszel 					  int hw_addr_len,
4152846fe56SPrzemek Kitszel 					  struct netlink_ext_ack *extack)
4162846fe56SPrzemek Kitszel 
4172846fe56SPrzemek Kitszel {
4182846fe56SPrzemek Kitszel 	struct devlink_port_attrs *attrs = &port->attrs;
4192846fe56SPrzemek Kitszel 	struct devlink_port_pci_vf_attrs *pci_vf;
4202846fe56SPrzemek Kitszel 	struct devlink *devlink = port->devlink;
4212846fe56SPrzemek Kitszel 	struct ice_pf *pf;
4222846fe56SPrzemek Kitszel 	u16 vf_id;
4232846fe56SPrzemek Kitszel 
4242846fe56SPrzemek Kitszel 	pf = devlink_priv(devlink);
4252846fe56SPrzemek Kitszel 	pci_vf = &attrs->pci_vf;
4262846fe56SPrzemek Kitszel 	vf_id = pci_vf->vf;
4272846fe56SPrzemek Kitszel 
4282846fe56SPrzemek Kitszel 	return __ice_set_vf_mac(pf, vf_id, hw_addr);
4292846fe56SPrzemek Kitszel }
4302846fe56SPrzemek Kitszel 
4312846fe56SPrzemek Kitszel static const struct devlink_port_ops ice_devlink_vf_port_ops = {
4322846fe56SPrzemek Kitszel 	.port_fn_hw_addr_get = ice_devlink_port_get_vf_fn_mac,
4332846fe56SPrzemek Kitszel 	.port_fn_hw_addr_set = ice_devlink_port_set_vf_fn_mac,
4342846fe56SPrzemek Kitszel };
4352846fe56SPrzemek Kitszel 
4362846fe56SPrzemek Kitszel /**
4372846fe56SPrzemek Kitszel  * ice_devlink_create_vf_port - Create a devlink port for this VF
4382846fe56SPrzemek Kitszel  * @vf: the VF to create a port for
4392846fe56SPrzemek Kitszel  *
4402846fe56SPrzemek Kitszel  * Create and register a devlink_port for this VF.
4412846fe56SPrzemek Kitszel  *
4422846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
4432846fe56SPrzemek Kitszel  */
ice_devlink_create_vf_port(struct ice_vf * vf)4442846fe56SPrzemek Kitszel int ice_devlink_create_vf_port(struct ice_vf *vf)
4452846fe56SPrzemek Kitszel {
4462846fe56SPrzemek Kitszel 	struct devlink_port_attrs attrs = {};
4472846fe56SPrzemek Kitszel 	struct devlink_port *devlink_port;
4482846fe56SPrzemek Kitszel 	struct devlink *devlink;
4492846fe56SPrzemek Kitszel 	struct ice_vsi *vsi;
4502846fe56SPrzemek Kitszel 	struct device *dev;
4512846fe56SPrzemek Kitszel 	struct ice_pf *pf;
4522846fe56SPrzemek Kitszel 	int err;
4532846fe56SPrzemek Kitszel 
4542846fe56SPrzemek Kitszel 	pf = vf->pf;
4552846fe56SPrzemek Kitszel 	dev = ice_pf_to_dev(pf);
4562846fe56SPrzemek Kitszel 	devlink_port = &vf->devlink_port;
4572846fe56SPrzemek Kitszel 
4582846fe56SPrzemek Kitszel 	vsi = ice_get_vf_vsi(vf);
4592846fe56SPrzemek Kitszel 	if (!vsi)
4602846fe56SPrzemek Kitszel 		return -EINVAL;
4612846fe56SPrzemek Kitszel 
4622846fe56SPrzemek Kitszel 	attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF;
4632846fe56SPrzemek Kitszel 	attrs.pci_vf.pf = pf->hw.pf_id;
4642846fe56SPrzemek Kitszel 	attrs.pci_vf.vf = vf->vf_id;
4652846fe56SPrzemek Kitszel 
4662846fe56SPrzemek Kitszel 	ice_devlink_set_switch_id(pf, &attrs.switch_id);
4672846fe56SPrzemek Kitszel 
4682846fe56SPrzemek Kitszel 	devlink_port_attrs_set(devlink_port, &attrs);
4692846fe56SPrzemek Kitszel 	devlink = priv_to_devlink(pf);
4702846fe56SPrzemek Kitszel 
4712846fe56SPrzemek Kitszel 	err = devl_port_register_with_ops(devlink, devlink_port, vsi->idx,
4722846fe56SPrzemek Kitszel 					  &ice_devlink_vf_port_ops);
4732846fe56SPrzemek Kitszel 	if (err) {
4742846fe56SPrzemek Kitszel 		dev_err(dev, "Failed to create devlink port for VF %d, error %d\n",
4752846fe56SPrzemek Kitszel 			vf->vf_id, err);
4762846fe56SPrzemek Kitszel 		return err;
4772846fe56SPrzemek Kitszel 	}
4782846fe56SPrzemek Kitszel 
4792846fe56SPrzemek Kitszel 	return 0;
4802846fe56SPrzemek Kitszel }
4812846fe56SPrzemek Kitszel 
4822846fe56SPrzemek Kitszel /**
4832846fe56SPrzemek Kitszel  * ice_devlink_destroy_vf_port - Destroy the devlink_port for this VF
4842846fe56SPrzemek Kitszel  * @vf: the VF to cleanup
4852846fe56SPrzemek Kitszel  *
4862846fe56SPrzemek Kitszel  * Unregisters the devlink_port structure associated with this VF.
4872846fe56SPrzemek Kitszel  */
ice_devlink_destroy_vf_port(struct ice_vf * vf)4882846fe56SPrzemek Kitszel void ice_devlink_destroy_vf_port(struct ice_vf *vf)
4892846fe56SPrzemek Kitszel {
4902846fe56SPrzemek Kitszel 	devl_rate_leaf_destroy(&vf->devlink_port);
4912846fe56SPrzemek Kitszel 	devl_port_unregister(&vf->devlink_port);
4922846fe56SPrzemek Kitszel }
4932846fe56SPrzemek Kitszel 
4942846fe56SPrzemek Kitszel /**
4952846fe56SPrzemek Kitszel  * ice_devlink_create_sf_dev_port - Register virtual port for a subfunction
4962846fe56SPrzemek Kitszel  * @sf_dev: the subfunction device to create a devlink port for
4972846fe56SPrzemek Kitszel  *
4982846fe56SPrzemek Kitszel  * Register virtual flavour devlink port for the subfunction auxiliary device
4992846fe56SPrzemek Kitszel  * created after activating a dynamically added devlink port.
5002846fe56SPrzemek Kitszel  *
5012846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
5022846fe56SPrzemek Kitszel  */
ice_devlink_create_sf_dev_port(struct ice_sf_dev * sf_dev)5032846fe56SPrzemek Kitszel int ice_devlink_create_sf_dev_port(struct ice_sf_dev *sf_dev)
5042846fe56SPrzemek Kitszel {
5052846fe56SPrzemek Kitszel 	struct devlink_port_attrs attrs = {};
5062846fe56SPrzemek Kitszel 	struct ice_dynamic_port *dyn_port;
5072846fe56SPrzemek Kitszel 	struct devlink_port *devlink_port;
5082846fe56SPrzemek Kitszel 	struct devlink *devlink;
5092846fe56SPrzemek Kitszel 	struct ice_vsi *vsi;
5102846fe56SPrzemek Kitszel 
5112846fe56SPrzemek Kitszel 	dyn_port = sf_dev->dyn_port;
5122846fe56SPrzemek Kitszel 	vsi = dyn_port->vsi;
5132846fe56SPrzemek Kitszel 
5142846fe56SPrzemek Kitszel 	devlink_port = &sf_dev->priv->devlink_port;
5152846fe56SPrzemek Kitszel 
5162846fe56SPrzemek Kitszel 	attrs.flavour = DEVLINK_PORT_FLAVOUR_VIRTUAL;
5172846fe56SPrzemek Kitszel 
5182846fe56SPrzemek Kitszel 	devlink_port_attrs_set(devlink_port, &attrs);
5192846fe56SPrzemek Kitszel 	devlink = priv_to_devlink(sf_dev->priv);
5202846fe56SPrzemek Kitszel 
5212846fe56SPrzemek Kitszel 	return devl_port_register(devlink, devlink_port, vsi->idx);
5222846fe56SPrzemek Kitszel }
5232846fe56SPrzemek Kitszel 
5242846fe56SPrzemek Kitszel /**
5252846fe56SPrzemek Kitszel  * ice_devlink_destroy_sf_dev_port - Destroy virtual port for a subfunction
5262846fe56SPrzemek Kitszel  * @sf_dev: the subfunction device to create a devlink port for
5272846fe56SPrzemek Kitszel  *
5282846fe56SPrzemek Kitszel  * Unregisters the virtual port associated with this subfunction.
5292846fe56SPrzemek Kitszel  */
ice_devlink_destroy_sf_dev_port(struct ice_sf_dev * sf_dev)5302846fe56SPrzemek Kitszel void ice_devlink_destroy_sf_dev_port(struct ice_sf_dev *sf_dev)
5312846fe56SPrzemek Kitszel {
5322846fe56SPrzemek Kitszel 	devl_port_unregister(&sf_dev->priv->devlink_port);
5332846fe56SPrzemek Kitszel }
5342846fe56SPrzemek Kitszel 
5352846fe56SPrzemek Kitszel /**
5362846fe56SPrzemek Kitszel  * ice_activate_dynamic_port - Activate a dynamic port
5372846fe56SPrzemek Kitszel  * @dyn_port: dynamic port instance to activate
5382846fe56SPrzemek Kitszel  * @extack: extack for reporting error messages
5392846fe56SPrzemek Kitszel  *
5402846fe56SPrzemek Kitszel  * Activate the dynamic port based on its flavour.
5412846fe56SPrzemek Kitszel  *
5422846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
5432846fe56SPrzemek Kitszel  */
5442846fe56SPrzemek Kitszel static int
ice_activate_dynamic_port(struct ice_dynamic_port * dyn_port,struct netlink_ext_ack * extack)5452846fe56SPrzemek Kitszel ice_activate_dynamic_port(struct ice_dynamic_port *dyn_port,
5462846fe56SPrzemek Kitszel 			  struct netlink_ext_ack *extack)
5472846fe56SPrzemek Kitszel {
5482846fe56SPrzemek Kitszel 	int err;
5492846fe56SPrzemek Kitszel 
5502846fe56SPrzemek Kitszel 	if (dyn_port->active)
5512846fe56SPrzemek Kitszel 		return 0;
5522846fe56SPrzemek Kitszel 
5532846fe56SPrzemek Kitszel 	err = ice_sf_eth_activate(dyn_port, extack);
5542846fe56SPrzemek Kitszel 	if (err)
5552846fe56SPrzemek Kitszel 		return err;
5562846fe56SPrzemek Kitszel 
5572846fe56SPrzemek Kitszel 	dyn_port->active = true;
5582846fe56SPrzemek Kitszel 
5592846fe56SPrzemek Kitszel 	return 0;
5602846fe56SPrzemek Kitszel }
5612846fe56SPrzemek Kitszel 
5622846fe56SPrzemek Kitszel /**
5632846fe56SPrzemek Kitszel  * ice_deactivate_dynamic_port - Deactivate a dynamic port
5642846fe56SPrzemek Kitszel  * @dyn_port: dynamic port instance to deactivate
5652846fe56SPrzemek Kitszel  *
5662846fe56SPrzemek Kitszel  * Undo activation of a dynamic port.
5672846fe56SPrzemek Kitszel  */
ice_deactivate_dynamic_port(struct ice_dynamic_port * dyn_port)5682846fe56SPrzemek Kitszel static void ice_deactivate_dynamic_port(struct ice_dynamic_port *dyn_port)
5692846fe56SPrzemek Kitszel {
5702846fe56SPrzemek Kitszel 	if (!dyn_port->active)
5712846fe56SPrzemek Kitszel 		return;
5722846fe56SPrzemek Kitszel 
5732846fe56SPrzemek Kitszel 	ice_sf_eth_deactivate(dyn_port);
5742846fe56SPrzemek Kitszel 	dyn_port->active = false;
5752846fe56SPrzemek Kitszel }
5762846fe56SPrzemek Kitszel 
5772846fe56SPrzemek Kitszel /**
5782846fe56SPrzemek Kitszel  * ice_dealloc_dynamic_port - Deallocate and remove a dynamic port
5792846fe56SPrzemek Kitszel  * @dyn_port: dynamic port instance to deallocate
5802846fe56SPrzemek Kitszel  *
5812846fe56SPrzemek Kitszel  * Free resources associated with a dynamically added devlink port. Will
5822846fe56SPrzemek Kitszel  * deactivate the port if its currently active.
5832846fe56SPrzemek Kitszel  */
ice_dealloc_dynamic_port(struct ice_dynamic_port * dyn_port)5842846fe56SPrzemek Kitszel static void ice_dealloc_dynamic_port(struct ice_dynamic_port *dyn_port)
5852846fe56SPrzemek Kitszel {
5862846fe56SPrzemek Kitszel 	struct devlink_port *devlink_port = &dyn_port->devlink_port;
5872846fe56SPrzemek Kitszel 	struct ice_pf *pf = dyn_port->pf;
5882846fe56SPrzemek Kitszel 
5892846fe56SPrzemek Kitszel 	ice_deactivate_dynamic_port(dyn_port);
5902846fe56SPrzemek Kitszel 
5912846fe56SPrzemek Kitszel 	xa_erase(&pf->sf_nums, devlink_port->attrs.pci_sf.sf);
5922846fe56SPrzemek Kitszel 	ice_eswitch_detach_sf(pf, dyn_port);
5932846fe56SPrzemek Kitszel 	ice_vsi_free(dyn_port->vsi);
5942846fe56SPrzemek Kitszel 	xa_erase(&pf->dyn_ports, dyn_port->vsi->idx);
5952846fe56SPrzemek Kitszel 	kfree(dyn_port);
5962846fe56SPrzemek Kitszel }
5972846fe56SPrzemek Kitszel 
5982846fe56SPrzemek Kitszel /**
5992846fe56SPrzemek Kitszel  * ice_dealloc_all_dynamic_ports - Deallocate all dynamic devlink ports
6002846fe56SPrzemek Kitszel  * @pf: pointer to the pf structure
6012846fe56SPrzemek Kitszel  */
ice_dealloc_all_dynamic_ports(struct ice_pf * pf)6022846fe56SPrzemek Kitszel void ice_dealloc_all_dynamic_ports(struct ice_pf *pf)
6032846fe56SPrzemek Kitszel {
6042846fe56SPrzemek Kitszel 	struct ice_dynamic_port *dyn_port;
6052846fe56SPrzemek Kitszel 	unsigned long index;
6062846fe56SPrzemek Kitszel 
6072846fe56SPrzemek Kitszel 	xa_for_each(&pf->dyn_ports, index, dyn_port)
6082846fe56SPrzemek Kitszel 		ice_dealloc_dynamic_port(dyn_port);
6092846fe56SPrzemek Kitszel }
6102846fe56SPrzemek Kitszel 
6112846fe56SPrzemek Kitszel /**
6122846fe56SPrzemek Kitszel  * ice_devlink_port_new_check_attr - Check that new port attributes are valid
6132846fe56SPrzemek Kitszel  * @pf: pointer to the PF structure
6142846fe56SPrzemek Kitszel  * @new_attr: the attributes for the new port
6152846fe56SPrzemek Kitszel  * @extack: extack for reporting error messages
6162846fe56SPrzemek Kitszel  *
6172846fe56SPrzemek Kitszel  * Check that the attributes for the new port are valid before continuing to
6182846fe56SPrzemek Kitszel  * allocate the devlink port.
6192846fe56SPrzemek Kitszel  *
6202846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
6212846fe56SPrzemek Kitszel  */
6222846fe56SPrzemek Kitszel static int
ice_devlink_port_new_check_attr(struct ice_pf * pf,const struct devlink_port_new_attrs * new_attr,struct netlink_ext_ack * extack)6232846fe56SPrzemek Kitszel ice_devlink_port_new_check_attr(struct ice_pf *pf,
6242846fe56SPrzemek Kitszel 				const struct devlink_port_new_attrs *new_attr,
6252846fe56SPrzemek Kitszel 				struct netlink_ext_ack *extack)
6262846fe56SPrzemek Kitszel {
6272846fe56SPrzemek Kitszel 	if (new_attr->flavour != DEVLINK_PORT_FLAVOUR_PCI_SF) {
6282846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack, "Flavour other than pcisf is not supported");
6292846fe56SPrzemek Kitszel 		return -EOPNOTSUPP;
6302846fe56SPrzemek Kitszel 	}
6312846fe56SPrzemek Kitszel 
6322846fe56SPrzemek Kitszel 	if (new_attr->controller_valid) {
6332846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack, "Setting controller is not supported");
6342846fe56SPrzemek Kitszel 		return -EOPNOTSUPP;
6352846fe56SPrzemek Kitszel 	}
6362846fe56SPrzemek Kitszel 
6372846fe56SPrzemek Kitszel 	if (new_attr->port_index_valid) {
6382846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack, "Driver does not support user defined port index assignment");
6392846fe56SPrzemek Kitszel 		return -EOPNOTSUPP;
6402846fe56SPrzemek Kitszel 	}
6412846fe56SPrzemek Kitszel 
6422846fe56SPrzemek Kitszel 	if (new_attr->pfnum != pf->hw.pf_id) {
6432846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack, "Incorrect pfnum supplied");
6442846fe56SPrzemek Kitszel 		return -EINVAL;
6452846fe56SPrzemek Kitszel 	}
6462846fe56SPrzemek Kitszel 
6472846fe56SPrzemek Kitszel 	if (!pci_msix_can_alloc_dyn(pf->pdev)) {
6482846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack, "Dynamic MSIX-X interrupt allocation is not supported");
6492846fe56SPrzemek Kitszel 		return -EOPNOTSUPP;
6502846fe56SPrzemek Kitszel 	}
6512846fe56SPrzemek Kitszel 
6522846fe56SPrzemek Kitszel 	return 0;
6532846fe56SPrzemek Kitszel }
6542846fe56SPrzemek Kitszel 
6552846fe56SPrzemek Kitszel /**
6562846fe56SPrzemek Kitszel  * ice_devlink_port_del - devlink handler for port delete
6572846fe56SPrzemek Kitszel  * @devlink: pointer to devlink
6582846fe56SPrzemek Kitszel  * @port: devlink port to be deleted
6592846fe56SPrzemek Kitszel  * @extack: pointer to extack
6602846fe56SPrzemek Kitszel  *
6612846fe56SPrzemek Kitszel  * Deletes devlink port and deallocates all resources associated with
6622846fe56SPrzemek Kitszel  * created subfunction.
6632846fe56SPrzemek Kitszel  *
6642846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
6652846fe56SPrzemek Kitszel  */
6662846fe56SPrzemek Kitszel static int
ice_devlink_port_del(struct devlink * devlink,struct devlink_port * port,struct netlink_ext_ack * extack)6672846fe56SPrzemek Kitszel ice_devlink_port_del(struct devlink *devlink, struct devlink_port *port,
6682846fe56SPrzemek Kitszel 		     struct netlink_ext_ack *extack)
6692846fe56SPrzemek Kitszel {
6702846fe56SPrzemek Kitszel 	struct ice_dynamic_port *dyn_port;
6712846fe56SPrzemek Kitszel 
6722846fe56SPrzemek Kitszel 	dyn_port = ice_devlink_port_to_dyn(port);
6732846fe56SPrzemek Kitszel 	ice_dealloc_dynamic_port(dyn_port);
6742846fe56SPrzemek Kitszel 
6752846fe56SPrzemek Kitszel 	return 0;
6762846fe56SPrzemek Kitszel }
6772846fe56SPrzemek Kitszel 
6782846fe56SPrzemek Kitszel /**
6792846fe56SPrzemek Kitszel  * ice_devlink_port_fn_hw_addr_set - devlink handler for mac address set
6802846fe56SPrzemek Kitszel  * @port: pointer to devlink port
6812846fe56SPrzemek Kitszel  * @hw_addr: hw address to set
6822846fe56SPrzemek Kitszel  * @hw_addr_len: hw address length
6832846fe56SPrzemek Kitszel  * @extack: extack for reporting error messages
6842846fe56SPrzemek Kitszel  *
6852846fe56SPrzemek Kitszel  * Sets mac address for the port, verifies arguments and copies address
6862846fe56SPrzemek Kitszel  * to the subfunction structure.
6872846fe56SPrzemek Kitszel  *
6882846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
6892846fe56SPrzemek Kitszel  */
6902846fe56SPrzemek Kitszel static int
ice_devlink_port_fn_hw_addr_set(struct devlink_port * port,const u8 * hw_addr,int hw_addr_len,struct netlink_ext_ack * extack)6912846fe56SPrzemek Kitszel ice_devlink_port_fn_hw_addr_set(struct devlink_port *port, const u8 *hw_addr,
6922846fe56SPrzemek Kitszel 				int hw_addr_len,
6932846fe56SPrzemek Kitszel 				struct netlink_ext_ack *extack)
6942846fe56SPrzemek Kitszel {
6952846fe56SPrzemek Kitszel 	struct ice_dynamic_port *dyn_port;
6962846fe56SPrzemek Kitszel 
6972846fe56SPrzemek Kitszel 	dyn_port = ice_devlink_port_to_dyn(port);
6982846fe56SPrzemek Kitszel 
6992846fe56SPrzemek Kitszel 	if (dyn_port->attached) {
7002846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack,
7012846fe56SPrzemek Kitszel 				   "Ethernet address can be change only in detached state");
7022846fe56SPrzemek Kitszel 		return -EBUSY;
7032846fe56SPrzemek Kitszel 	}
7042846fe56SPrzemek Kitszel 
7052846fe56SPrzemek Kitszel 	if (hw_addr_len != ETH_ALEN || !is_valid_ether_addr(hw_addr)) {
7062846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack, "Invalid ethernet address");
7072846fe56SPrzemek Kitszel 		return -EADDRNOTAVAIL;
7082846fe56SPrzemek Kitszel 	}
7092846fe56SPrzemek Kitszel 
7102846fe56SPrzemek Kitszel 	ether_addr_copy(dyn_port->hw_addr, hw_addr);
7112846fe56SPrzemek Kitszel 
7122846fe56SPrzemek Kitszel 	return 0;
7132846fe56SPrzemek Kitszel }
7142846fe56SPrzemek Kitszel 
7152846fe56SPrzemek Kitszel /**
7162846fe56SPrzemek Kitszel  * ice_devlink_port_fn_hw_addr_get - devlink handler for mac address get
7172846fe56SPrzemek Kitszel  * @port: pointer to devlink port
7182846fe56SPrzemek Kitszel  * @hw_addr: hw address to set
7192846fe56SPrzemek Kitszel  * @hw_addr_len: hw address length
7202846fe56SPrzemek Kitszel  * @extack: extack for reporting error messages
7212846fe56SPrzemek Kitszel  *
7222846fe56SPrzemek Kitszel  * Returns mac address for the port.
7232846fe56SPrzemek Kitszel  *
7242846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
7252846fe56SPrzemek Kitszel  */
7262846fe56SPrzemek Kitszel static int
ice_devlink_port_fn_hw_addr_get(struct devlink_port * port,u8 * hw_addr,int * hw_addr_len,struct netlink_ext_ack * extack)7272846fe56SPrzemek Kitszel ice_devlink_port_fn_hw_addr_get(struct devlink_port *port, u8 *hw_addr,
7282846fe56SPrzemek Kitszel 				int *hw_addr_len,
7292846fe56SPrzemek Kitszel 				struct netlink_ext_ack *extack)
7302846fe56SPrzemek Kitszel {
7312846fe56SPrzemek Kitszel 	struct ice_dynamic_port *dyn_port;
7322846fe56SPrzemek Kitszel 
7332846fe56SPrzemek Kitszel 	dyn_port = ice_devlink_port_to_dyn(port);
7342846fe56SPrzemek Kitszel 
7352846fe56SPrzemek Kitszel 	ether_addr_copy(hw_addr, dyn_port->hw_addr);
7362846fe56SPrzemek Kitszel 	*hw_addr_len = ETH_ALEN;
7372846fe56SPrzemek Kitszel 
7382846fe56SPrzemek Kitszel 	return 0;
7392846fe56SPrzemek Kitszel }
7402846fe56SPrzemek Kitszel 
7412846fe56SPrzemek Kitszel /**
7422846fe56SPrzemek Kitszel  * ice_devlink_port_fn_state_set - devlink handler for port state set
7432846fe56SPrzemek Kitszel  * @port: pointer to devlink port
7442846fe56SPrzemek Kitszel  * @state: state to set
7452846fe56SPrzemek Kitszel  * @extack: extack for reporting error messages
7462846fe56SPrzemek Kitszel  *
7472846fe56SPrzemek Kitszel  * Activates or deactivates the port.
7482846fe56SPrzemek Kitszel  *
7492846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
7502846fe56SPrzemek Kitszel  */
7512846fe56SPrzemek Kitszel static int
ice_devlink_port_fn_state_set(struct devlink_port * port,enum devlink_port_fn_state state,struct netlink_ext_ack * extack)7522846fe56SPrzemek Kitszel ice_devlink_port_fn_state_set(struct devlink_port *port,
7532846fe56SPrzemek Kitszel 			      enum devlink_port_fn_state state,
7542846fe56SPrzemek Kitszel 			      struct netlink_ext_ack *extack)
7552846fe56SPrzemek Kitszel {
7562846fe56SPrzemek Kitszel 	struct ice_dynamic_port *dyn_port;
7572846fe56SPrzemek Kitszel 
7582846fe56SPrzemek Kitszel 	dyn_port = ice_devlink_port_to_dyn(port);
7592846fe56SPrzemek Kitszel 
7602846fe56SPrzemek Kitszel 	switch (state) {
7612846fe56SPrzemek Kitszel 	case DEVLINK_PORT_FN_STATE_ACTIVE:
7622846fe56SPrzemek Kitszel 		return ice_activate_dynamic_port(dyn_port, extack);
7632846fe56SPrzemek Kitszel 
7642846fe56SPrzemek Kitszel 	case DEVLINK_PORT_FN_STATE_INACTIVE:
7652846fe56SPrzemek Kitszel 		ice_deactivate_dynamic_port(dyn_port);
7662846fe56SPrzemek Kitszel 		break;
7672846fe56SPrzemek Kitszel 	}
7682846fe56SPrzemek Kitszel 
7692846fe56SPrzemek Kitszel 	return 0;
7702846fe56SPrzemek Kitszel }
7712846fe56SPrzemek Kitszel 
7722846fe56SPrzemek Kitszel /**
7732846fe56SPrzemek Kitszel  * ice_devlink_port_fn_state_get - devlink handler for port state get
7742846fe56SPrzemek Kitszel  * @port: pointer to devlink port
7752846fe56SPrzemek Kitszel  * @state: admin configured state of the port
7762846fe56SPrzemek Kitszel  * @opstate: current port operational state
7772846fe56SPrzemek Kitszel  * @extack: extack for reporting error messages
7782846fe56SPrzemek Kitszel  *
7792846fe56SPrzemek Kitszel  * Gets port state.
7802846fe56SPrzemek Kitszel  *
7812846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
7822846fe56SPrzemek Kitszel  */
7832846fe56SPrzemek Kitszel static int
ice_devlink_port_fn_state_get(struct devlink_port * port,enum devlink_port_fn_state * state,enum devlink_port_fn_opstate * opstate,struct netlink_ext_ack * extack)7842846fe56SPrzemek Kitszel ice_devlink_port_fn_state_get(struct devlink_port *port,
7852846fe56SPrzemek Kitszel 			      enum devlink_port_fn_state *state,
7862846fe56SPrzemek Kitszel 			      enum devlink_port_fn_opstate *opstate,
7872846fe56SPrzemek Kitszel 			      struct netlink_ext_ack *extack)
7882846fe56SPrzemek Kitszel {
7892846fe56SPrzemek Kitszel 	struct ice_dynamic_port *dyn_port;
7902846fe56SPrzemek Kitszel 
7912846fe56SPrzemek Kitszel 	dyn_port = ice_devlink_port_to_dyn(port);
7922846fe56SPrzemek Kitszel 
7932846fe56SPrzemek Kitszel 	if (dyn_port->active)
7942846fe56SPrzemek Kitszel 		*state = DEVLINK_PORT_FN_STATE_ACTIVE;
7952846fe56SPrzemek Kitszel 	else
7962846fe56SPrzemek Kitszel 		*state = DEVLINK_PORT_FN_STATE_INACTIVE;
7972846fe56SPrzemek Kitszel 
7982846fe56SPrzemek Kitszel 	if (dyn_port->attached)
7992846fe56SPrzemek Kitszel 		*opstate = DEVLINK_PORT_FN_OPSTATE_ATTACHED;
8002846fe56SPrzemek Kitszel 	else
8012846fe56SPrzemek Kitszel 		*opstate = DEVLINK_PORT_FN_OPSTATE_DETACHED;
8022846fe56SPrzemek Kitszel 
8032846fe56SPrzemek Kitszel 	return 0;
8042846fe56SPrzemek Kitszel }
8052846fe56SPrzemek Kitszel 
8062846fe56SPrzemek Kitszel static const struct devlink_port_ops ice_devlink_port_sf_ops = {
8072846fe56SPrzemek Kitszel 	.port_del = ice_devlink_port_del,
8082846fe56SPrzemek Kitszel 	.port_fn_hw_addr_get = ice_devlink_port_fn_hw_addr_get,
8092846fe56SPrzemek Kitszel 	.port_fn_hw_addr_set = ice_devlink_port_fn_hw_addr_set,
8102846fe56SPrzemek Kitszel 	.port_fn_state_get = ice_devlink_port_fn_state_get,
8112846fe56SPrzemek Kitszel 	.port_fn_state_set = ice_devlink_port_fn_state_set,
8122846fe56SPrzemek Kitszel };
8132846fe56SPrzemek Kitszel 
8142846fe56SPrzemek Kitszel /**
8152846fe56SPrzemek Kitszel  * ice_reserve_sf_num - Reserve a subfunction number for this port
8162846fe56SPrzemek Kitszel  * @pf: pointer to the pf structure
8172846fe56SPrzemek Kitszel  * @new_attr: devlink port attributes requested
8182846fe56SPrzemek Kitszel  * @extack: extack for reporting error messages
8192846fe56SPrzemek Kitszel  * @sfnum: on success, the sf number reserved
8202846fe56SPrzemek Kitszel  *
8212846fe56SPrzemek Kitszel  * Reserve a subfunction number for this port. Only called for
8222846fe56SPrzemek Kitszel  * DEVLINK_PORT_FLAVOUR_PCI_SF ports.
8232846fe56SPrzemek Kitszel  *
8242846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
8252846fe56SPrzemek Kitszel  */
8262846fe56SPrzemek Kitszel static int
ice_reserve_sf_num(struct ice_pf * pf,const struct devlink_port_new_attrs * new_attr,struct netlink_ext_ack * extack,u32 * sfnum)8272846fe56SPrzemek Kitszel ice_reserve_sf_num(struct ice_pf *pf,
8282846fe56SPrzemek Kitszel 		   const struct devlink_port_new_attrs *new_attr,
8292846fe56SPrzemek Kitszel 		   struct netlink_ext_ack *extack, u32 *sfnum)
8302846fe56SPrzemek Kitszel {
8312846fe56SPrzemek Kitszel 	int err;
8322846fe56SPrzemek Kitszel 
8332846fe56SPrzemek Kitszel 	/* If user didn't request an explicit number, pick one */
8342846fe56SPrzemek Kitszel 	if (!new_attr->sfnum_valid)
8352846fe56SPrzemek Kitszel 		return xa_alloc(&pf->sf_nums, sfnum, NULL, xa_limit_32b,
8362846fe56SPrzemek Kitszel 				GFP_KERNEL);
8372846fe56SPrzemek Kitszel 
8382846fe56SPrzemek Kitszel 	/* Otherwise, check and use the number provided */
8392846fe56SPrzemek Kitszel 	err = xa_insert(&pf->sf_nums, new_attr->sfnum, NULL, GFP_KERNEL);
8402846fe56SPrzemek Kitszel 	if (err) {
8412846fe56SPrzemek Kitszel 		if (err == -EBUSY)
8422846fe56SPrzemek Kitszel 			NL_SET_ERR_MSG_MOD(extack, "Subfunction with given sfnum already exists");
8432846fe56SPrzemek Kitszel 		return err;
8442846fe56SPrzemek Kitszel 	}
8452846fe56SPrzemek Kitszel 
8462846fe56SPrzemek Kitszel 	*sfnum = new_attr->sfnum;
8472846fe56SPrzemek Kitszel 
8482846fe56SPrzemek Kitszel 	return 0;
8492846fe56SPrzemek Kitszel }
8502846fe56SPrzemek Kitszel 
8512846fe56SPrzemek Kitszel /**
8522846fe56SPrzemek Kitszel  * ice_devlink_create_sf_port - Register PCI subfunction devlink port
8532846fe56SPrzemek Kitszel  * @dyn_port: the dynamic port instance structure for this subfunction
8542846fe56SPrzemek Kitszel  *
8552846fe56SPrzemek Kitszel  * Register PCI subfunction flavour devlink port for a dynamically added
8562846fe56SPrzemek Kitszel  * subfunction port.
8572846fe56SPrzemek Kitszel  *
8582846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
8592846fe56SPrzemek Kitszel  */
ice_devlink_create_sf_port(struct ice_dynamic_port * dyn_port)8602846fe56SPrzemek Kitszel int ice_devlink_create_sf_port(struct ice_dynamic_port *dyn_port)
8612846fe56SPrzemek Kitszel {
8622846fe56SPrzemek Kitszel 	struct devlink_port_attrs attrs = {};
8632846fe56SPrzemek Kitszel 	struct devlink_port *devlink_port;
8642846fe56SPrzemek Kitszel 	struct devlink *devlink;
8652846fe56SPrzemek Kitszel 	struct ice_vsi *vsi;
8662846fe56SPrzemek Kitszel 	struct ice_pf *pf;
8672846fe56SPrzemek Kitszel 
8682846fe56SPrzemek Kitszel 	vsi = dyn_port->vsi;
8692846fe56SPrzemek Kitszel 	pf = dyn_port->pf;
8702846fe56SPrzemek Kitszel 
8712846fe56SPrzemek Kitszel 	devlink_port = &dyn_port->devlink_port;
8722846fe56SPrzemek Kitszel 
8732846fe56SPrzemek Kitszel 	attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_SF;
8742846fe56SPrzemek Kitszel 	attrs.pci_sf.pf = pf->hw.pf_id;
8752846fe56SPrzemek Kitszel 	attrs.pci_sf.sf = dyn_port->sfnum;
8762846fe56SPrzemek Kitszel 
8772846fe56SPrzemek Kitszel 	devlink_port_attrs_set(devlink_port, &attrs);
8782846fe56SPrzemek Kitszel 	devlink = priv_to_devlink(pf);
8792846fe56SPrzemek Kitszel 
8802846fe56SPrzemek Kitszel 	return devl_port_register_with_ops(devlink, devlink_port, vsi->idx,
8812846fe56SPrzemek Kitszel 					   &ice_devlink_port_sf_ops);
8822846fe56SPrzemek Kitszel }
8832846fe56SPrzemek Kitszel 
8842846fe56SPrzemek Kitszel /**
8852846fe56SPrzemek Kitszel  * ice_devlink_destroy_sf_port - Destroy the devlink_port for this SF
8862846fe56SPrzemek Kitszel  * @dyn_port: the dynamic port instance structure for this subfunction
8872846fe56SPrzemek Kitszel  *
8882846fe56SPrzemek Kitszel  * Unregisters the devlink_port structure associated with this SF.
8892846fe56SPrzemek Kitszel  */
ice_devlink_destroy_sf_port(struct ice_dynamic_port * dyn_port)8902846fe56SPrzemek Kitszel void ice_devlink_destroy_sf_port(struct ice_dynamic_port *dyn_port)
8912846fe56SPrzemek Kitszel {
8922846fe56SPrzemek Kitszel 	devl_rate_leaf_destroy(&dyn_port->devlink_port);
8932846fe56SPrzemek Kitszel 	devl_port_unregister(&dyn_port->devlink_port);
8942846fe56SPrzemek Kitszel }
8952846fe56SPrzemek Kitszel 
8962846fe56SPrzemek Kitszel /**
8972846fe56SPrzemek Kitszel  * ice_alloc_dynamic_port - Allocate new dynamic port
8982846fe56SPrzemek Kitszel  * @pf: pointer to the pf structure
8992846fe56SPrzemek Kitszel  * @new_attr: devlink port attributes requested
9002846fe56SPrzemek Kitszel  * @extack: extack for reporting error messages
9012846fe56SPrzemek Kitszel  * @devlink_port: index of newly created devlink port
9022846fe56SPrzemek Kitszel  *
9032846fe56SPrzemek Kitszel  * Allocate a new dynamic port instance and prepare it for configuration
9042846fe56SPrzemek Kitszel  * with devlink.
9052846fe56SPrzemek Kitszel  *
9062846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
9072846fe56SPrzemek Kitszel  */
9082846fe56SPrzemek Kitszel static int
ice_alloc_dynamic_port(struct ice_pf * pf,const struct devlink_port_new_attrs * new_attr,struct netlink_ext_ack * extack,struct devlink_port ** devlink_port)9092846fe56SPrzemek Kitszel ice_alloc_dynamic_port(struct ice_pf *pf,
9102846fe56SPrzemek Kitszel 		       const struct devlink_port_new_attrs *new_attr,
9112846fe56SPrzemek Kitszel 		       struct netlink_ext_ack *extack,
9122846fe56SPrzemek Kitszel 		       struct devlink_port **devlink_port)
9132846fe56SPrzemek Kitszel {
9142846fe56SPrzemek Kitszel 	struct ice_dynamic_port *dyn_port;
9152846fe56SPrzemek Kitszel 	struct ice_vsi *vsi;
9162846fe56SPrzemek Kitszel 	u32 sfnum;
9172846fe56SPrzemek Kitszel 	int err;
9182846fe56SPrzemek Kitszel 
9192846fe56SPrzemek Kitszel 	err = ice_reserve_sf_num(pf, new_attr, extack, &sfnum);
9202846fe56SPrzemek Kitszel 	if (err)
9212846fe56SPrzemek Kitszel 		return err;
9222846fe56SPrzemek Kitszel 
9232846fe56SPrzemek Kitszel 	dyn_port = kzalloc(sizeof(*dyn_port), GFP_KERNEL);
9242846fe56SPrzemek Kitszel 	if (!dyn_port) {
9252846fe56SPrzemek Kitszel 		err = -ENOMEM;
9262846fe56SPrzemek Kitszel 		goto unroll_reserve_sf_num;
9272846fe56SPrzemek Kitszel 	}
9282846fe56SPrzemek Kitszel 
9292846fe56SPrzemek Kitszel 	vsi = ice_vsi_alloc(pf);
9302846fe56SPrzemek Kitszel 	if (!vsi) {
9312846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack, "Unable to allocate VSI");
9322846fe56SPrzemek Kitszel 		err = -ENOMEM;
9332846fe56SPrzemek Kitszel 		goto unroll_dyn_port_alloc;
9342846fe56SPrzemek Kitszel 	}
9352846fe56SPrzemek Kitszel 
9362846fe56SPrzemek Kitszel 	dyn_port->vsi = vsi;
9372846fe56SPrzemek Kitszel 	dyn_port->pf = pf;
9382846fe56SPrzemek Kitszel 	dyn_port->sfnum = sfnum;
9392846fe56SPrzemek Kitszel 	eth_random_addr(dyn_port->hw_addr);
9402846fe56SPrzemek Kitszel 
9412846fe56SPrzemek Kitszel 	err = xa_insert(&pf->dyn_ports, vsi->idx, dyn_port, GFP_KERNEL);
9422846fe56SPrzemek Kitszel 	if (err) {
9432846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack, "Port index reservation failed");
9442846fe56SPrzemek Kitszel 		goto unroll_vsi_alloc;
9452846fe56SPrzemek Kitszel 	}
9462846fe56SPrzemek Kitszel 
9472846fe56SPrzemek Kitszel 	err = ice_eswitch_attach_sf(pf, dyn_port);
9482846fe56SPrzemek Kitszel 	if (err) {
9492846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack, "Failed to attach SF to eswitch");
9502846fe56SPrzemek Kitszel 		goto unroll_xa_insert;
9512846fe56SPrzemek Kitszel 	}
9522846fe56SPrzemek Kitszel 
9532846fe56SPrzemek Kitszel 	*devlink_port = &dyn_port->devlink_port;
9542846fe56SPrzemek Kitszel 
9552846fe56SPrzemek Kitszel 	return 0;
9562846fe56SPrzemek Kitszel 
9572846fe56SPrzemek Kitszel unroll_xa_insert:
9582846fe56SPrzemek Kitszel 	xa_erase(&pf->dyn_ports, vsi->idx);
9592846fe56SPrzemek Kitszel unroll_vsi_alloc:
9602846fe56SPrzemek Kitszel 	ice_vsi_free(vsi);
9612846fe56SPrzemek Kitszel unroll_dyn_port_alloc:
9622846fe56SPrzemek Kitszel 	kfree(dyn_port);
9632846fe56SPrzemek Kitszel unroll_reserve_sf_num:
9642846fe56SPrzemek Kitszel 	xa_erase(&pf->sf_nums, sfnum);
9652846fe56SPrzemek Kitszel 
9662846fe56SPrzemek Kitszel 	return err;
9672846fe56SPrzemek Kitszel }
9682846fe56SPrzemek Kitszel 
9692846fe56SPrzemek Kitszel /**
9702846fe56SPrzemek Kitszel  * ice_devlink_port_new - devlink handler for the new port
9712846fe56SPrzemek Kitszel  * @devlink: pointer to devlink
9722846fe56SPrzemek Kitszel  * @new_attr: pointer to the port new attributes
9732846fe56SPrzemek Kitszel  * @extack: extack for reporting error messages
9742846fe56SPrzemek Kitszel  * @devlink_port: pointer to a new port
9752846fe56SPrzemek Kitszel  *
9762846fe56SPrzemek Kitszel  * Creates new devlink port, checks new port attributes and reject
9772846fe56SPrzemek Kitszel  * any unsupported parameters, allocates new subfunction for that port.
9782846fe56SPrzemek Kitszel  *
9792846fe56SPrzemek Kitszel  * Return: zero on success or an error code on failure.
9802846fe56SPrzemek Kitszel  */
9812846fe56SPrzemek Kitszel int
ice_devlink_port_new(struct devlink * devlink,const struct devlink_port_new_attrs * new_attr,struct netlink_ext_ack * extack,struct devlink_port ** devlink_port)9822846fe56SPrzemek Kitszel ice_devlink_port_new(struct devlink *devlink,
9832846fe56SPrzemek Kitszel 		     const struct devlink_port_new_attrs *new_attr,
9842846fe56SPrzemek Kitszel 		     struct netlink_ext_ack *extack,
9852846fe56SPrzemek Kitszel 		     struct devlink_port **devlink_port)
9862846fe56SPrzemek Kitszel {
9872846fe56SPrzemek Kitszel 	struct ice_pf *pf = devlink_priv(devlink);
9882846fe56SPrzemek Kitszel 	int err;
9892846fe56SPrzemek Kitszel 
9902846fe56SPrzemek Kitszel 	err = ice_devlink_port_new_check_attr(pf, new_attr, extack);
9912846fe56SPrzemek Kitszel 	if (err)
9922846fe56SPrzemek Kitszel 		return err;
9932846fe56SPrzemek Kitszel 
9942846fe56SPrzemek Kitszel 	if (!ice_is_eswitch_mode_switchdev(pf)) {
9952846fe56SPrzemek Kitszel 		NL_SET_ERR_MSG_MOD(extack,
9962846fe56SPrzemek Kitszel 				   "SF ports are only supported in eswitch switchdev mode");
9972846fe56SPrzemek Kitszel 		return -EOPNOTSUPP;
9982846fe56SPrzemek Kitszel 	}
9992846fe56SPrzemek Kitszel 
10002846fe56SPrzemek Kitszel 	return ice_alloc_dynamic_port(pf, new_attr, extack, devlink_port);
10012846fe56SPrzemek Kitszel }
1002