brintos

brintos / linux-shallow public Read only

0
0
Text · 15.4 KiB · fb52743 Raw
633 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (C) 2019-2021, Intel Corporation. */3 4#include "ice.h"5#include "ice_lib.h"6#include "ice_eswitch.h"7#include "ice_eswitch_br.h"8#include "ice_fltr.h"9#include "ice_repr.h"10#include "devlink/devlink.h"11#include "ice_tc_lib.h"12 13/**14 * ice_eswitch_setup_env - configure eswitch HW filters15 * @pf: pointer to PF struct16 *17 * This function adds HW filters configuration specific for switchdev18 * mode.19 */20static int ice_eswitch_setup_env(struct ice_pf *pf)21{22	struct ice_vsi *uplink_vsi = pf->eswitch.uplink_vsi;23	struct net_device *netdev = uplink_vsi->netdev;24	bool if_running = netif_running(netdev);25	struct ice_vsi_vlan_ops *vlan_ops;26 27	if (if_running && !test_and_set_bit(ICE_VSI_DOWN, uplink_vsi->state))28		if (ice_down(uplink_vsi))29			return -ENODEV;30 31	ice_remove_vsi_fltr(&pf->hw, uplink_vsi->idx);32 33	netif_addr_lock_bh(netdev);34	__dev_uc_unsync(netdev, NULL);35	__dev_mc_unsync(netdev, NULL);36	netif_addr_unlock_bh(netdev);37 38	if (ice_vsi_add_vlan_zero(uplink_vsi))39		goto err_vlan_zero;40 41	if (ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx, true,42			     ICE_FLTR_RX))43		goto err_def_rx;44 45	if (ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx, true,46			     ICE_FLTR_TX))47		goto err_def_tx;48 49	vlan_ops = ice_get_compat_vsi_vlan_ops(uplink_vsi);50	if (vlan_ops->dis_rx_filtering(uplink_vsi))51		goto err_vlan_filtering;52 53	if (ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_set_allow_override))54		goto err_override_uplink;55 56	if (ice_vsi_update_local_lb(uplink_vsi, true))57		goto err_override_local_lb;58 59	if (if_running && ice_up(uplink_vsi))60		goto err_up;61 62	return 0;63 64err_up:65	ice_vsi_update_local_lb(uplink_vsi, false);66err_override_local_lb:67	ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override);68err_override_uplink:69	vlan_ops->ena_rx_filtering(uplink_vsi);70err_vlan_filtering:71	ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx, false,72			 ICE_FLTR_TX);73err_def_tx:74	ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx, false,75			 ICE_FLTR_RX);76err_def_rx:77	ice_vsi_del_vlan_zero(uplink_vsi);78err_vlan_zero:79	ice_fltr_add_mac_and_broadcast(uplink_vsi,80				       uplink_vsi->port_info->mac.perm_addr,81				       ICE_FWD_TO_VSI);82	if (if_running)83		ice_up(uplink_vsi);84 85	return -ENODEV;86}87 88/**89 * ice_eswitch_release_repr - clear PR VSI configuration90 * @pf: poiner to PF struct91 * @repr: pointer to PR92 */93static void94ice_eswitch_release_repr(struct ice_pf *pf, struct ice_repr *repr)95{96	struct ice_vsi *vsi = repr->src_vsi;97 98	/* Skip representors that aren't configured */99	if (!repr->dst)100		return;101 102	ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);103	metadata_dst_free(repr->dst);104	repr->dst = NULL;105	ice_fltr_add_mac_and_broadcast(vsi, repr->parent_mac,106				       ICE_FWD_TO_VSI);107}108 109/**110 * ice_eswitch_setup_repr - configure PR to run in switchdev mode111 * @pf: pointer to PF struct112 * @repr: pointer to PR struct113 */114static int ice_eswitch_setup_repr(struct ice_pf *pf, struct ice_repr *repr)115{116	struct ice_vsi *uplink_vsi = pf->eswitch.uplink_vsi;117	struct ice_vsi *vsi = repr->src_vsi;118	struct metadata_dst *dst;119 120	repr->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX,121				       GFP_KERNEL);122	if (!repr->dst)123		return -ENOMEM;124 125	netif_keep_dst(uplink_vsi->netdev);126 127	dst = repr->dst;128	dst->u.port_info.port_id = vsi->vsi_num;129	dst->u.port_info.lower_dev = uplink_vsi->netdev;130 131	return 0;132}133 134/**135 * ice_eswitch_cfg_vsi - configure VSI to work in slow-path136 * @vsi: VSI structure of representee137 * @mac: representee MAC138 *139 * Return: 0 on success, non-zero on error.140 */141int ice_eswitch_cfg_vsi(struct ice_vsi *vsi, const u8 *mac)142{143	int err;144 145	ice_remove_vsi_fltr(&vsi->back->hw, vsi->idx);146 147	err = ice_vsi_update_security(vsi, ice_vsi_ctx_clear_antispoof);148	if (err)149		goto err_update_security;150 151	err = ice_vsi_add_vlan_zero(vsi);152	if (err)153		goto err_vlan_zero;154 155	return 0;156 157err_vlan_zero:158	ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);159err_update_security:160	ice_fltr_add_mac_and_broadcast(vsi, mac, ICE_FWD_TO_VSI);161 162	return err;163}164 165/**166 * ice_eswitch_decfg_vsi - unroll changes done to VSI for switchdev167 * @vsi: VSI structure of representee168 * @mac: representee MAC169 */170void ice_eswitch_decfg_vsi(struct ice_vsi *vsi, const u8 *mac)171{172	ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);173	ice_fltr_add_mac_and_broadcast(vsi, mac, ICE_FWD_TO_VSI);174}175 176/**177 * ice_eswitch_update_repr - reconfigure port representor178 * @repr_id: representor ID179 * @vsi: VSI for which port representor is configured180 */181void ice_eswitch_update_repr(unsigned long *repr_id, struct ice_vsi *vsi)182{183	struct ice_pf *pf = vsi->back;184	struct ice_repr *repr;185	int err;186 187	if (!ice_is_switchdev_running(pf))188		return;189 190	repr = xa_load(&pf->eswitch.reprs, *repr_id);191	if (!repr)192		return;193 194	repr->src_vsi = vsi;195	repr->dst->u.port_info.port_id = vsi->vsi_num;196 197	if (repr->br_port)198		repr->br_port->vsi = vsi;199 200	err = ice_eswitch_cfg_vsi(vsi, repr->parent_mac);201	if (err)202		dev_err(ice_pf_to_dev(pf), "Failed to update VSI of port representor %d",203			repr->id);204 205	/* The VSI number is different, reload the PR with new id */206	if (repr->id != vsi->vsi_num) {207		xa_erase(&pf->eswitch.reprs, repr->id);208		repr->id = vsi->vsi_num;209		if (xa_insert(&pf->eswitch.reprs, repr->id, repr, GFP_KERNEL))210			dev_err(ice_pf_to_dev(pf), "Failed to reload port representor %d",211				repr->id);212		*repr_id = repr->id;213	}214}215 216/**217 * ice_eswitch_port_start_xmit - callback for packets transmit218 * @skb: send buffer219 * @netdev: network interface device structure220 *221 * Returns NETDEV_TX_OK if sent, else an error code222 */223netdev_tx_t224ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev)225{226	struct ice_repr *repr = ice_netdev_to_repr(netdev);227	unsigned int len = skb->len;228	int ret;229 230	skb_dst_drop(skb);231	dst_hold((struct dst_entry *)repr->dst);232	skb_dst_set(skb, (struct dst_entry *)repr->dst);233	skb->dev = repr->dst->u.port_info.lower_dev;234 235	ret = dev_queue_xmit(skb);236	ice_repr_inc_tx_stats(repr, len, ret);237 238	return ret;239}240 241/**242 * ice_eswitch_set_target_vsi - set eswitch context in Tx context descriptor243 * @skb: pointer to send buffer244 * @off: pointer to offload struct245 */246void247ice_eswitch_set_target_vsi(struct sk_buff *skb,248			   struct ice_tx_offload_params *off)249{250	struct metadata_dst *dst = skb_metadata_dst(skb);251	u64 cd_cmd, dst_vsi;252 253	if (!dst) {254		cd_cmd = ICE_TX_CTX_DESC_SWTCH_UPLINK << ICE_TXD_CTX_QW1_CMD_S;255		off->cd_qw1 |= (cd_cmd | ICE_TX_DESC_DTYPE_CTX);256	} else {257		cd_cmd = ICE_TX_CTX_DESC_SWTCH_VSI << ICE_TXD_CTX_QW1_CMD_S;258		dst_vsi = FIELD_PREP(ICE_TXD_CTX_QW1_VSI_M,259				     dst->u.port_info.port_id);260		off->cd_qw1 = cd_cmd | dst_vsi | ICE_TX_DESC_DTYPE_CTX;261	}262}263 264/**265 * ice_eswitch_release_env - clear eswitch HW filters266 * @pf: pointer to PF struct267 *268 * This function removes HW filters configuration specific for switchdev269 * mode and restores default legacy mode settings.270 */271static void ice_eswitch_release_env(struct ice_pf *pf)272{273	struct ice_vsi *uplink_vsi = pf->eswitch.uplink_vsi;274	struct ice_vsi_vlan_ops *vlan_ops;275 276	vlan_ops = ice_get_compat_vsi_vlan_ops(uplink_vsi);277 278	ice_vsi_update_local_lb(uplink_vsi, false);279	ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override);280	vlan_ops->ena_rx_filtering(uplink_vsi);281	ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx, false,282			 ICE_FLTR_TX);283	ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx, false,284			 ICE_FLTR_RX);285	ice_fltr_add_mac_and_broadcast(uplink_vsi,286				       uplink_vsi->port_info->mac.perm_addr,287				       ICE_FWD_TO_VSI);288}289 290/**291 * ice_eswitch_enable_switchdev - configure eswitch in switchdev mode292 * @pf: pointer to PF structure293 */294static int ice_eswitch_enable_switchdev(struct ice_pf *pf)295{296	struct ice_vsi *uplink_vsi;297 298	uplink_vsi = ice_get_main_vsi(pf);299	if (!uplink_vsi)300		return -ENODEV;301 302	if (netif_is_any_bridge_port(uplink_vsi->netdev)) {303		dev_err(ice_pf_to_dev(pf),304			"Uplink port cannot be a bridge port\n");305		return -EINVAL;306	}307 308	pf->eswitch.uplink_vsi = uplink_vsi;309 310	if (ice_eswitch_setup_env(pf))311		return -ENODEV;312 313	if (ice_eswitch_br_offloads_init(pf))314		goto err_br_offloads;315 316	pf->eswitch.is_running = true;317 318	return 0;319 320err_br_offloads:321	ice_eswitch_release_env(pf);322	return -ENODEV;323}324 325/**326 * ice_eswitch_disable_switchdev - disable eswitch resources327 * @pf: pointer to PF structure328 */329static void ice_eswitch_disable_switchdev(struct ice_pf *pf)330{331	ice_eswitch_br_offloads_deinit(pf);332	ice_eswitch_release_env(pf);333 334	pf->eswitch.is_running = false;335}336 337/**338 * ice_eswitch_mode_set - set new eswitch mode339 * @devlink: pointer to devlink structure340 * @mode: eswitch mode to switch to341 * @extack: pointer to extack structure342 */343int344ice_eswitch_mode_set(struct devlink *devlink, u16 mode,345		     struct netlink_ext_ack *extack)346{347	struct ice_pf *pf = devlink_priv(devlink);348 349	if (pf->eswitch_mode == mode)350		return 0;351 352	if (ice_has_vfs(pf)) {353		dev_info(ice_pf_to_dev(pf), "Changing eswitch mode is allowed only if there is no VFs created");354		NL_SET_ERR_MSG_MOD(extack, "Changing eswitch mode is allowed only if there is no VFs created");355		return -EOPNOTSUPP;356	}357 358	switch (mode) {359	case DEVLINK_ESWITCH_MODE_LEGACY:360		dev_info(ice_pf_to_dev(pf), "PF %d changed eswitch mode to legacy",361			 pf->hw.pf_id);362		xa_destroy(&pf->eswitch.reprs);363		NL_SET_ERR_MSG_MOD(extack, "Changed eswitch mode to legacy");364		break;365	case DEVLINK_ESWITCH_MODE_SWITCHDEV:366	{367		if (ice_is_adq_active(pf)) {368			dev_err(ice_pf_to_dev(pf), "Couldn't change eswitch mode to switchdev - ADQ is active. Delete ADQ configs and try again, e.g. tc qdisc del dev $PF root");369			NL_SET_ERR_MSG_MOD(extack, "Couldn't change eswitch mode to switchdev - ADQ is active. Delete ADQ configs and try again, e.g. tc qdisc del dev $PF root");370			return -EOPNOTSUPP;371		}372 373		dev_info(ice_pf_to_dev(pf), "PF %d changed eswitch mode to switchdev",374			 pf->hw.pf_id);375		xa_init(&pf->eswitch.reprs);376		NL_SET_ERR_MSG_MOD(extack, "Changed eswitch mode to switchdev");377		break;378	}379	default:380		NL_SET_ERR_MSG_MOD(extack, "Unknown eswitch mode");381		return -EINVAL;382	}383 384	pf->eswitch_mode = mode;385	return 0;386}387 388/**389 * ice_eswitch_mode_get - get current eswitch mode390 * @devlink: pointer to devlink structure391 * @mode: output parameter for current eswitch mode392 */393int ice_eswitch_mode_get(struct devlink *devlink, u16 *mode)394{395	struct ice_pf *pf = devlink_priv(devlink);396 397	*mode = pf->eswitch_mode;398	return 0;399}400 401/**402 * ice_is_eswitch_mode_switchdev - check if eswitch mode is set to switchdev403 * @pf: pointer to PF structure404 *405 * Returns true if eswitch mode is set to DEVLINK_ESWITCH_MODE_SWITCHDEV,406 * false otherwise.407 */408bool ice_is_eswitch_mode_switchdev(struct ice_pf *pf)409{410	return pf->eswitch_mode == DEVLINK_ESWITCH_MODE_SWITCHDEV;411}412 413/**414 * ice_eswitch_start_all_tx_queues - start Tx queues of all port representors415 * @pf: pointer to PF structure416 */417static void ice_eswitch_start_all_tx_queues(struct ice_pf *pf)418{419	struct ice_repr *repr;420	unsigned long id;421 422	if (test_bit(ICE_DOWN, pf->state))423		return;424 425	xa_for_each(&pf->eswitch.reprs, id, repr)426		ice_repr_start_tx_queues(repr);427}428 429/**430 * ice_eswitch_stop_all_tx_queues - stop Tx queues of all port representors431 * @pf: pointer to PF structure432 */433void ice_eswitch_stop_all_tx_queues(struct ice_pf *pf)434{435	struct ice_repr *repr;436	unsigned long id;437 438	if (test_bit(ICE_DOWN, pf->state))439		return;440 441	xa_for_each(&pf->eswitch.reprs, id, repr)442		ice_repr_stop_tx_queues(repr);443}444 445static void ice_eswitch_stop_reprs(struct ice_pf *pf)446{447	ice_eswitch_stop_all_tx_queues(pf);448}449 450static void ice_eswitch_start_reprs(struct ice_pf *pf)451{452	ice_eswitch_start_all_tx_queues(pf);453}454 455static int456ice_eswitch_attach(struct ice_pf *pf, struct ice_repr *repr, unsigned long *id)457{458	int err;459 460	if (pf->eswitch_mode == DEVLINK_ESWITCH_MODE_LEGACY)461		return 0;462 463	if (xa_empty(&pf->eswitch.reprs)) {464		err = ice_eswitch_enable_switchdev(pf);465		if (err)466			return err;467	}468 469	ice_eswitch_stop_reprs(pf);470 471	err = repr->ops.add(repr);472	if (err)473		goto err_create_repr;474 475	err = ice_eswitch_setup_repr(pf, repr);476	if (err)477		goto err_setup_repr;478 479	err = xa_insert(&pf->eswitch.reprs, repr->id, repr, GFP_KERNEL);480	if (err)481		goto err_xa_alloc;482 483	*id = repr->id;484 485	ice_eswitch_start_reprs(pf);486 487	return 0;488 489err_xa_alloc:490	ice_eswitch_release_repr(pf, repr);491err_setup_repr:492	repr->ops.rem(repr);493err_create_repr:494	if (xa_empty(&pf->eswitch.reprs))495		ice_eswitch_disable_switchdev(pf);496	ice_eswitch_start_reprs(pf);497 498	return err;499}500 501/**502 * ice_eswitch_attach_vf - attach VF to a eswitch503 * @pf: pointer to PF structure504 * @vf: pointer to VF structure to be attached505 *506 * During attaching port representor for VF is created.507 *508 * Return: zero on success or an error code on failure.509 */510int ice_eswitch_attach_vf(struct ice_pf *pf, struct ice_vf *vf)511{512	struct ice_repr *repr = ice_repr_create_vf(vf);513	struct devlink *devlink = priv_to_devlink(pf);514	int err;515 516	if (IS_ERR(repr))517		return PTR_ERR(repr);518 519	devl_lock(devlink);520	err = ice_eswitch_attach(pf, repr, &vf->repr_id);521	if (err)522		ice_repr_destroy(repr);523	devl_unlock(devlink);524 525	return err;526}527 528/**529 * ice_eswitch_attach_sf - attach SF to a eswitch530 * @pf: pointer to PF structure531 * @sf: pointer to SF structure to be attached532 *533 * During attaching port representor for SF is created.534 *535 * Return: zero on success or an error code on failure.536 */537int ice_eswitch_attach_sf(struct ice_pf *pf, struct ice_dynamic_port *sf)538{539	struct ice_repr *repr = ice_repr_create_sf(sf);540	int err;541 542	if (IS_ERR(repr))543		return PTR_ERR(repr);544 545	err = ice_eswitch_attach(pf, repr, &sf->repr_id);546	if (err)547		ice_repr_destroy(repr);548 549	return err;550}551 552static void ice_eswitch_detach(struct ice_pf *pf, struct ice_repr *repr)553{554	ice_eswitch_stop_reprs(pf);555	repr->ops.rem(repr);556 557	xa_erase(&pf->eswitch.reprs, repr->id);558 559	if (xa_empty(&pf->eswitch.reprs))560		ice_eswitch_disable_switchdev(pf);561 562	ice_eswitch_release_repr(pf, repr);563	ice_repr_destroy(repr);564 565	if (xa_empty(&pf->eswitch.reprs)) {566		struct devlink *devlink = priv_to_devlink(pf);567 568		/* since all port representors are destroyed, there is569		 * no point in keeping the nodes570		 */571		ice_devlink_rate_clear_tx_topology(ice_get_main_vsi(pf));572		devl_rate_nodes_destroy(devlink);573	} else {574		ice_eswitch_start_reprs(pf);575	}576}577 578/**579 * ice_eswitch_detach_vf - detach VF from a eswitch580 * @pf: pointer to PF structure581 * @vf: pointer to VF structure to be detached582 */583void ice_eswitch_detach_vf(struct ice_pf *pf, struct ice_vf *vf)584{585	struct ice_repr *repr = xa_load(&pf->eswitch.reprs, vf->repr_id);586	struct devlink *devlink = priv_to_devlink(pf);587 588	if (!repr)589		return;590 591	devl_lock(devlink);592	ice_eswitch_detach(pf, repr);593	devl_unlock(devlink);594}595 596/**597 * ice_eswitch_detach_sf - detach SF from a eswitch598 * @pf: pointer to PF structure599 * @sf: pointer to SF structure to be detached600 */601void ice_eswitch_detach_sf(struct ice_pf *pf, struct ice_dynamic_port *sf)602{603	struct ice_repr *repr = xa_load(&pf->eswitch.reprs, sf->repr_id);604 605	if (!repr)606		return;607 608	ice_eswitch_detach(pf, repr);609}610 611/**612 * ice_eswitch_get_target - get netdev based on src_vsi from descriptor613 * @rx_ring: ring used to receive the packet614 * @rx_desc: descriptor used to get src_vsi value615 *616 * Get src_vsi value from descriptor and load correct representor. If it isn't617 * found return rx_ring->netdev.618 */619struct net_device *ice_eswitch_get_target(struct ice_rx_ring *rx_ring,620					  union ice_32b_rx_flex_desc *rx_desc)621{622	struct ice_eswitch *eswitch = &rx_ring->vsi->back->eswitch;623	struct ice_32b_rx_flex_desc_nic_2 *desc;624	struct ice_repr *repr;625 626	desc = (struct ice_32b_rx_flex_desc_nic_2 *)rx_desc;627	repr = xa_load(&eswitch->reprs, le16_to_cpu(desc->src_vsi));628	if (!repr)629		return rx_ring->netdev;630 631	return repr->netdev;632}633