brintos

brintos / linux-shallow public Read only

0
0
Text · 15.5 KiB · eabbacb Raw
683 lines · c
1// SPDX-License-Identifier: GPL-2.0+2// Copyright (c) 2016-2017 Hisilicon Limited.3 4#include "hclge_main.h"5#include "hclge_dcb.h"6#include "hclge_tm.h"7#include "hnae3.h"8 9#define BW_PERCENT	10010 11static int hclge_ieee_ets_to_tm_info(struct hclge_dev *hdev,12				     struct ieee_ets *ets)13{14	u8 i;15 16	for (i = 0; i < HNAE3_MAX_TC; i++) {17		switch (ets->tc_tsa[i]) {18		case IEEE_8021QAZ_TSA_STRICT:19			hdev->tm_info.tc_info[i].tc_sch_mode =20				HCLGE_SCH_MODE_SP;21			hdev->tm_info.pg_info[0].tc_dwrr[i] = 0;22			break;23		case IEEE_8021QAZ_TSA_ETS:24			hdev->tm_info.tc_info[i].tc_sch_mode =25				HCLGE_SCH_MODE_DWRR;26			hdev->tm_info.pg_info[0].tc_dwrr[i] =27				ets->tc_tx_bw[i];28			break;29		default:30			/* Hardware only supports SP (strict priority)31			 * or ETS (enhanced transmission selection)32			 * algorithms, if we receive some other value33			 * from dcbnl, then throw an error.34			 */35			return -EINVAL;36		}37	}38 39	hclge_tm_prio_tc_info_update(hdev, ets->prio_tc);40 41	return 0;42}43 44static void hclge_tm_info_to_ieee_ets(struct hclge_dev *hdev,45				      struct ieee_ets *ets)46{47	u32 i;48 49	memset(ets, 0, sizeof(*ets));50	ets->willing = 1;51	ets->ets_cap = hdev->tc_max;52 53	for (i = 0; i < HNAE3_MAX_TC; i++) {54		ets->prio_tc[i] = hdev->tm_info.prio_tc[i];55		if (i < hdev->tm_info.num_tc)56			ets->tc_tx_bw[i] = hdev->tm_info.pg_info[0].tc_dwrr[i];57		else58			ets->tc_tx_bw[i] = 0;59 60		if (hdev->tm_info.tc_info[i].tc_sch_mode ==61		    HCLGE_SCH_MODE_SP)62			ets->tc_tsa[i] = IEEE_8021QAZ_TSA_STRICT;63		else64			ets->tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;65	}66}67 68/* IEEE std */69static int hclge_ieee_getets(struct hnae3_handle *h, struct ieee_ets *ets)70{71	struct hclge_vport *vport = hclge_get_vport(h);72	struct hclge_dev *hdev = vport->back;73 74	hclge_tm_info_to_ieee_ets(hdev, ets);75 76	return 0;77}78 79static int hclge_dcb_common_validate(struct hclge_dev *hdev, u8 num_tc,80				     u8 *prio_tc)81{82	int i;83 84	if (num_tc > hdev->tc_max) {85		dev_err(&hdev->pdev->dev,86			"tc num checking failed, %u > tc_max(%u)\n",87			num_tc, hdev->tc_max);88		return -EINVAL;89	}90 91	for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) {92		if (prio_tc[i] >= num_tc) {93			dev_err(&hdev->pdev->dev,94				"prio_tc[%d] checking failed, %u >= num_tc(%u)\n",95				i, prio_tc[i], num_tc);96			return -EINVAL;97		}98	}99 100	if (num_tc > hdev->vport[0].alloc_tqps) {101		dev_err(&hdev->pdev->dev,102			"allocated tqp checking failed, %u > tqp(%u)\n",103			num_tc, hdev->vport[0].alloc_tqps);104		return -EINVAL;105	}106 107	return 0;108}109 110static u8 hclge_ets_tc_changed(struct hclge_dev *hdev, struct ieee_ets *ets,111			       bool *changed)112{113	u8 max_tc_id = 0;114	u8 i;115 116	for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) {117		if (ets->prio_tc[i] != hdev->tm_info.prio_tc[i])118			*changed = true;119 120		if (ets->prio_tc[i] > max_tc_id)121			max_tc_id = ets->prio_tc[i];122	}123 124	/* return max tc number, max tc id need to plus 1 */125	return max_tc_id + 1;126}127 128static int hclge_ets_sch_mode_validate(struct hclge_dev *hdev,129				       struct ieee_ets *ets, bool *changed,130				       u8 tc_num)131{132	bool has_ets_tc = false;133	u32 total_ets_bw = 0;134	u8 i;135 136	for (i = 0; i < HNAE3_MAX_TC; i++) {137		switch (ets->tc_tsa[i]) {138		case IEEE_8021QAZ_TSA_STRICT:139			if (hdev->tm_info.tc_info[i].tc_sch_mode !=140				HCLGE_SCH_MODE_SP)141				*changed = true;142			break;143		case IEEE_8021QAZ_TSA_ETS:144			if (i >= tc_num) {145				dev_err(&hdev->pdev->dev,146					"tc%u is disabled, cannot set ets bw\n",147					i);148				return -EINVAL;149			}150 151			/* The hardware will switch to sp mode if bandwidth is152			 * 0, so limit ets bandwidth must be greater than 0.153			 */154			if (!ets->tc_tx_bw[i]) {155				dev_err(&hdev->pdev->dev,156					"tc%u ets bw cannot be 0\n", i);157				return -EINVAL;158			}159 160			if (hdev->tm_info.tc_info[i].tc_sch_mode !=161				HCLGE_SCH_MODE_DWRR)162				*changed = true;163 164			total_ets_bw += ets->tc_tx_bw[i];165			has_ets_tc = true;166			break;167		default:168			return -EINVAL;169		}170	}171 172	if (has_ets_tc && total_ets_bw != BW_PERCENT)173		return -EINVAL;174 175	return 0;176}177 178static int hclge_ets_validate(struct hclge_dev *hdev, struct ieee_ets *ets,179			      u8 *tc, bool *changed)180{181	u8 tc_num;182	int ret;183 184	tc_num = hclge_ets_tc_changed(hdev, ets, changed);185 186	ret = hclge_dcb_common_validate(hdev, tc_num, ets->prio_tc);187	if (ret)188		return ret;189 190	ret = hclge_ets_sch_mode_validate(hdev, ets, changed, tc_num);191	if (ret)192		return ret;193 194	*tc = tc_num;195	if (*tc != hdev->tm_info.num_tc)196		*changed = true;197 198	return 0;199}200 201static int hclge_map_update(struct hclge_dev *hdev)202{203	int ret;204 205	ret = hclge_tm_schd_setup_hw(hdev);206	if (ret)207		return ret;208 209	ret = hclge_pause_setup_hw(hdev, false);210	if (ret)211		return ret;212 213	ret = hclge_buffer_alloc(hdev);214	if (ret)215		return ret;216 217	hclge_comm_rss_indir_init_cfg(hdev->ae_dev, &hdev->rss_cfg);218 219	return hclge_rss_init_hw(hdev);220}221 222static int hclge_notify_down_uinit(struct hclge_dev *hdev)223{224	int ret;225 226	ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT);227	if (ret)228		return ret;229 230	ret = hclge_tm_flush_cfg(hdev, true);231	if (ret)232		return ret;233 234	return hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT);235}236 237static int hclge_notify_init_up(struct hclge_dev *hdev)238{239	int ret;240 241	ret = hclge_notify_client(hdev, HNAE3_INIT_CLIENT);242	if (ret)243		return ret;244 245	ret = hclge_tm_flush_cfg(hdev, false);246	if (ret)247		return ret;248 249	return hclge_notify_client(hdev, HNAE3_UP_CLIENT);250}251 252static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets)253{254	struct hclge_vport *vport = hclge_get_vport(h);255	struct net_device *netdev = h->kinfo.netdev;256	struct hclge_dev *hdev = vport->back;257	bool map_changed = false;258	u8 num_tc = 0;259	int ret;260 261	if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||262	    h->kinfo.tc_info.mqprio_active)263		return -EINVAL;264 265	ret = hclge_ets_validate(hdev, ets, &num_tc, &map_changed);266	if (ret)267		return ret;268 269	if (map_changed) {270		netif_dbg(h, drv, netdev, "set ets\n");271 272		ret = hclge_notify_down_uinit(hdev);273		if (ret)274			return ret;275	}276 277	hclge_tm_schd_info_update(hdev, num_tc);278	h->kinfo.tc_info.dcb_ets_active = num_tc > 1;279 280	ret = hclge_ieee_ets_to_tm_info(hdev, ets);281	if (ret)282		goto err_out;283 284	if (map_changed) {285		ret = hclge_map_update(hdev);286		if (ret)287			goto err_out;288 289		return hclge_notify_init_up(hdev);290	}291 292	return hclge_tm_dwrr_cfg(hdev);293 294err_out:295	if (!map_changed)296		return ret;297 298	hclge_notify_init_up(hdev);299 300	return ret;301}302 303static int hclge_ieee_getpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)304{305	struct hclge_vport *vport = hclge_get_vport(h);306	struct hclge_dev *hdev = vport->back;307	int ret;308 309	memset(pfc, 0, sizeof(*pfc));310	pfc->pfc_cap = hdev->pfc_max;311	pfc->pfc_en = hdev->tm_info.pfc_en;312 313	ret = hclge_mac_update_stats(hdev);314	if (ret) {315		dev_err(&hdev->pdev->dev,316			"failed to update MAC stats, ret = %d.\n", ret);317		return ret;318	}319 320	hclge_pfc_tx_stats_get(hdev, pfc->requests);321	hclge_pfc_rx_stats_get(hdev, pfc->indications);322 323	return 0;324}325 326static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)327{328	struct hclge_vport *vport = hclge_get_vport(h);329	struct net_device *netdev = h->kinfo.netdev;330	struct hclge_dev *hdev = vport->back;331	u8 i, j, pfc_map, *prio_tc;332	int last_bad_ret = 0;333	int ret;334 335	if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))336		return -EINVAL;337 338	if (pfc->pfc_en == hdev->tm_info.pfc_en)339		return 0;340 341	prio_tc = hdev->tm_info.prio_tc;342	pfc_map = 0;343 344	for (i = 0; i < hdev->tm_info.num_tc; i++) {345		for (j = 0; j < HNAE3_MAX_USER_PRIO; j++) {346			if ((prio_tc[j] == i) && (pfc->pfc_en & BIT(j))) {347				pfc_map |= BIT(i);348				break;349			}350		}351	}352 353	hdev->tm_info.hw_pfc_map = pfc_map;354	hdev->tm_info.pfc_en = pfc->pfc_en;355 356	netif_dbg(h, drv, netdev,357		  "set pfc: pfc_en=%x, pfc_map=%x, num_tc=%u\n",358		  pfc->pfc_en, pfc_map, hdev->tm_info.num_tc);359 360	hclge_tm_pfc_info_update(hdev);361 362	ret = hclge_pause_setup_hw(hdev, false);363	if (ret)364		return ret;365 366	ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT);367	if (ret)368		return ret;369 370	ret = hclge_tm_flush_cfg(hdev, true);371	if (ret)372		return ret;373 374	/* No matter whether the following operations are performed375	 * successfully or not, disabling the tm flush and notify376	 * the network status to up are necessary.377	 * Do not return immediately.378	 */379	ret = hclge_buffer_alloc(hdev);380	if (ret)381		last_bad_ret = ret;382 383	ret = hclge_tm_flush_cfg(hdev, false);384	if (ret)385		last_bad_ret = ret;386 387	ret = hclge_notify_client(hdev, HNAE3_UP_CLIENT);388	if (ret)389		last_bad_ret = ret;390 391	return last_bad_ret;392}393 394static int hclge_ieee_setapp(struct hnae3_handle *h, struct dcb_app *app)395{396	struct hclge_vport *vport = hclge_get_vport(h);397	struct net_device *netdev = h->kinfo.netdev;398	struct hclge_dev *hdev = vport->back;399	struct dcb_app old_app;400	int ret;401 402	if (app->selector != IEEE_8021QAZ_APP_SEL_DSCP ||403	    app->protocol >= HNAE3_MAX_DSCP ||404	    app->priority >= HNAE3_MAX_USER_PRIO)405		return -EINVAL;406 407	dev_info(&hdev->pdev->dev, "setapp dscp=%u priority=%u\n",408		 app->protocol, app->priority);409 410	if (app->priority == h->kinfo.dscp_prio[app->protocol])411		return 0;412 413	ret = dcb_ieee_setapp(netdev, app);414	if (ret)415		return ret;416 417	old_app.selector = IEEE_8021QAZ_APP_SEL_DSCP;418	old_app.protocol = app->protocol;419	old_app.priority = h->kinfo.dscp_prio[app->protocol];420 421	h->kinfo.dscp_prio[app->protocol] = app->priority;422	ret = hclge_dscp_to_tc_map(hdev);423	if (ret) {424		dev_err(&hdev->pdev->dev,425			"failed to set dscp to tc map, ret = %d\n", ret);426		h->kinfo.dscp_prio[app->protocol] = old_app.priority;427		(void)dcb_ieee_delapp(netdev, app);428		return ret;429	}430 431	vport->nic.kinfo.tc_map_mode = HNAE3_TC_MAP_MODE_DSCP;432	if (old_app.priority == HNAE3_PRIO_ID_INVALID)433		h->kinfo.dscp_app_cnt++;434	else435		ret = dcb_ieee_delapp(netdev, &old_app);436 437	return ret;438}439 440static int hclge_ieee_delapp(struct hnae3_handle *h, struct dcb_app *app)441{442	struct hclge_vport *vport = hclge_get_vport(h);443	struct net_device *netdev = h->kinfo.netdev;444	struct hclge_dev *hdev = vport->back;445	int ret;446 447	if (app->selector != IEEE_8021QAZ_APP_SEL_DSCP ||448	    app->protocol >= HNAE3_MAX_DSCP ||449	    app->priority >= HNAE3_MAX_USER_PRIO ||450	    app->priority != h->kinfo.dscp_prio[app->protocol])451		return -EINVAL;452 453	dev_info(&hdev->pdev->dev, "delapp dscp=%u priority=%u\n",454		 app->protocol, app->priority);455 456	ret = dcb_ieee_delapp(netdev, app);457	if (ret)458		return ret;459 460	h->kinfo.dscp_prio[app->protocol] = HNAE3_PRIO_ID_INVALID;461	ret = hclge_dscp_to_tc_map(hdev);462	if (ret) {463		dev_err(&hdev->pdev->dev,464			"failed to del dscp to tc map, ret = %d\n", ret);465		h->kinfo.dscp_prio[app->protocol] = app->priority;466		(void)dcb_ieee_setapp(netdev, app);467		return ret;468	}469 470	if (h->kinfo.dscp_app_cnt)471		h->kinfo.dscp_app_cnt--;472 473	if (!h->kinfo.dscp_app_cnt) {474		vport->nic.kinfo.tc_map_mode = HNAE3_TC_MAP_MODE_PRIO;475		ret = hclge_up_to_tc_map(hdev);476	}477 478	return ret;479}480 481/* DCBX configuration */482static u8 hclge_getdcbx(struct hnae3_handle *h)483{484	struct hclge_vport *vport = hclge_get_vport(h);485	struct hclge_dev *hdev = vport->back;486 487	if (h->kinfo.tc_info.mqprio_active)488		return 0;489 490	return hdev->dcbx_cap;491}492 493static u8 hclge_setdcbx(struct hnae3_handle *h, u8 mode)494{495	struct hclge_vport *vport = hclge_get_vport(h);496	struct net_device *netdev = h->kinfo.netdev;497	struct hclge_dev *hdev = vport->back;498 499	netif_dbg(h, drv, netdev, "set dcbx: mode=%u\n", mode);500 501	/* No support for LLD_MANAGED modes or CEE */502	if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||503	    (mode & DCB_CAP_DCBX_VER_CEE) ||504	    !(mode & DCB_CAP_DCBX_HOST))505		return 1;506 507	hdev->dcbx_cap = mode;508 509	return 0;510}511 512static int hclge_mqprio_qopt_check(struct hclge_dev *hdev,513				   struct tc_mqprio_qopt_offload *mqprio_qopt)514{515	u16 queue_sum = 0;516	int ret;517	int i;518 519	if (!mqprio_qopt->qopt.num_tc) {520		mqprio_qopt->qopt.num_tc = 1;521		return 0;522	}523 524	ret = hclge_dcb_common_validate(hdev, mqprio_qopt->qopt.num_tc,525					mqprio_qopt->qopt.prio_tc_map);526	if (ret)527		return ret;528 529	for (i = 0; i < mqprio_qopt->qopt.num_tc; i++) {530		if (!is_power_of_2(mqprio_qopt->qopt.count[i])) {531			dev_err(&hdev->pdev->dev,532				"qopt queue count must be power of 2\n");533			return -EINVAL;534		}535 536		if (mqprio_qopt->qopt.count[i] > hdev->pf_rss_size_max) {537			dev_err(&hdev->pdev->dev,538				"qopt queue count should be no more than %u\n",539				hdev->pf_rss_size_max);540			return -EINVAL;541		}542 543		if (mqprio_qopt->qopt.offset[i] != queue_sum) {544			dev_err(&hdev->pdev->dev,545				"qopt queue offset must start from 0, and being continuous\n");546			return -EINVAL;547		}548 549		if (mqprio_qopt->min_rate[i] || mqprio_qopt->max_rate[i]) {550			dev_err(&hdev->pdev->dev,551				"qopt tx_rate is not supported\n");552			return -EOPNOTSUPP;553		}554 555		queue_sum = mqprio_qopt->qopt.offset[i];556		queue_sum += mqprio_qopt->qopt.count[i];557	}558	if (hdev->vport[0].alloc_tqps < queue_sum) {559		dev_err(&hdev->pdev->dev,560			"qopt queue count sum should be less than %u\n",561			hdev->vport[0].alloc_tqps);562		return -EINVAL;563	}564 565	return 0;566}567 568static void hclge_sync_mqprio_qopt(struct hnae3_tc_info *tc_info,569				   struct tc_mqprio_qopt_offload *mqprio_qopt)570{571	memset(tc_info, 0, sizeof(*tc_info));572	tc_info->num_tc = mqprio_qopt->qopt.num_tc;573	memcpy(tc_info->prio_tc, mqprio_qopt->qopt.prio_tc_map,574	       sizeof_field(struct hnae3_tc_info, prio_tc));575	memcpy(tc_info->tqp_count, mqprio_qopt->qopt.count,576	       sizeof_field(struct hnae3_tc_info, tqp_count));577	memcpy(tc_info->tqp_offset, mqprio_qopt->qopt.offset,578	       sizeof_field(struct hnae3_tc_info, tqp_offset));579}580 581static int hclge_config_tc(struct hclge_dev *hdev,582			   struct hnae3_tc_info *tc_info)583{584	int i;585 586	hclge_tm_schd_info_update(hdev, tc_info->num_tc);587	for (i = 0; i < HNAE3_MAX_USER_PRIO; i++)588		hdev->tm_info.prio_tc[i] = tc_info->prio_tc[i];589 590	return hclge_map_update(hdev);591}592 593/* Set up TC for hardware offloaded mqprio in channel mode */594static int hclge_setup_tc(struct hnae3_handle *h,595			  struct tc_mqprio_qopt_offload *mqprio_qopt)596{597	struct hclge_vport *vport = hclge_get_vport(h);598	struct hnae3_knic_private_info *kinfo;599	struct hclge_dev *hdev = vport->back;600	struct hnae3_tc_info old_tc_info;601	u8 tc = mqprio_qopt->qopt.num_tc;602	int ret;603 604	/* if client unregistered, it's not allowed to change605	 * mqprio configuration, which may cause uninit ring606	 * fail.607	 */608	if (!test_bit(HCLGE_STATE_NIC_REGISTERED, &hdev->state))609		return -EBUSY;610 611	kinfo = &vport->nic.kinfo;612	if (kinfo->tc_info.dcb_ets_active)613		return -EINVAL;614 615	ret = hclge_mqprio_qopt_check(hdev, mqprio_qopt);616	if (ret) {617		dev_err(&hdev->pdev->dev,618			"failed to check mqprio qopt params, ret = %d\n", ret);619		return ret;620	}621 622	kinfo->tc_info.mqprio_destroy = !tc;623 624	ret = hclge_notify_down_uinit(hdev);625	if (ret)626		return ret;627 628	memcpy(&old_tc_info, &kinfo->tc_info, sizeof(old_tc_info));629	hclge_sync_mqprio_qopt(&kinfo->tc_info, mqprio_qopt);630	kinfo->tc_info.mqprio_active = tc > 0;631 632	ret = hclge_config_tc(hdev, &kinfo->tc_info);633	if (ret)634		goto err_out;635 636	return hclge_notify_init_up(hdev);637 638err_out:639	if (!tc) {640		dev_warn(&hdev->pdev->dev,641			 "failed to destroy mqprio, will active after reset, ret = %d\n",642			 ret);643	} else {644		/* roll-back */645		memcpy(&kinfo->tc_info, &old_tc_info, sizeof(old_tc_info));646		if (hclge_config_tc(hdev, &kinfo->tc_info))647			dev_err(&hdev->pdev->dev,648				"failed to roll back tc configuration\n");649	}650	hclge_notify_init_up(hdev);651 652	return ret;653}654 655static const struct hnae3_dcb_ops hns3_dcb_ops = {656	.ieee_getets	= hclge_ieee_getets,657	.ieee_setets	= hclge_ieee_setets,658	.ieee_getpfc	= hclge_ieee_getpfc,659	.ieee_setpfc	= hclge_ieee_setpfc,660	.ieee_setapp    = hclge_ieee_setapp,661	.ieee_delapp    = hclge_ieee_delapp,662	.getdcbx	= hclge_getdcbx,663	.setdcbx	= hclge_setdcbx,664	.setup_tc	= hclge_setup_tc,665};666 667void hclge_dcb_ops_set(struct hclge_dev *hdev)668{669	struct hclge_vport *vport = hdev->vport;670	struct hnae3_knic_private_info *kinfo;671 672	/* Hdev does not support DCB or vport is673	 * not a pf, then dcb_ops is not set.674	 */675	if (!hnae3_dev_dcb_supported(hdev) ||676	    vport->vport_id != 0)677		return;678 679	kinfo = &vport->nic.kinfo;680	kinfo->dcb_ops = &hns3_dcb_ops;681	hdev->dcbx_cap = DCB_CAP_DCBX_VER_IEEE | DCB_CAP_DCBX_HOST;682}683