cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hclge_dcb.c (12946B)


      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	100
     10
     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 value
     33			 * 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		ets->tc_tx_bw[i] = hdev->tm_info.pg_info[0].tc_dwrr[i];
     56
     57		if (hdev->tm_info.tc_info[i].tc_sch_mode ==
     58		    HCLGE_SCH_MODE_SP)
     59			ets->tc_tsa[i] = IEEE_8021QAZ_TSA_STRICT;
     60		else
     61			ets->tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
     62	}
     63}
     64
     65/* IEEE std */
     66static int hclge_ieee_getets(struct hnae3_handle *h, struct ieee_ets *ets)
     67{
     68	struct hclge_vport *vport = hclge_get_vport(h);
     69	struct hclge_dev *hdev = vport->back;
     70
     71	hclge_tm_info_to_ieee_ets(hdev, ets);
     72
     73	return 0;
     74}
     75
     76static int hclge_dcb_common_validate(struct hclge_dev *hdev, u8 num_tc,
     77				     u8 *prio_tc)
     78{
     79	int i;
     80
     81	if (num_tc > hdev->tc_max) {
     82		dev_err(&hdev->pdev->dev,
     83			"tc num checking failed, %u > tc_max(%u)\n",
     84			num_tc, hdev->tc_max);
     85		return -EINVAL;
     86	}
     87
     88	for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) {
     89		if (prio_tc[i] >= num_tc) {
     90			dev_err(&hdev->pdev->dev,
     91				"prio_tc[%d] checking failed, %u >= num_tc(%u)\n",
     92				i, prio_tc[i], num_tc);
     93			return -EINVAL;
     94		}
     95	}
     96
     97	if (num_tc > hdev->vport[0].alloc_tqps) {
     98		dev_err(&hdev->pdev->dev,
     99			"allocated tqp checking failed, %u > tqp(%u)\n",
    100			num_tc, hdev->vport[0].alloc_tqps);
    101		return -EINVAL;
    102	}
    103
    104	return 0;
    105}
    106
    107static u8 hclge_ets_tc_changed(struct hclge_dev *hdev, struct ieee_ets *ets,
    108			       bool *changed)
    109{
    110	u8 max_tc_id = 0;
    111	u8 i;
    112
    113	for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) {
    114		if (ets->prio_tc[i] != hdev->tm_info.prio_tc[i])
    115			*changed = true;
    116
    117		if (ets->prio_tc[i] > max_tc_id)
    118			max_tc_id = ets->prio_tc[i];
    119	}
    120
    121	/* return max tc number, max tc id need to plus 1 */
    122	return max_tc_id + 1;
    123}
    124
    125static int hclge_ets_sch_mode_validate(struct hclge_dev *hdev,
    126				       struct ieee_ets *ets, bool *changed)
    127{
    128	bool has_ets_tc = false;
    129	u32 total_ets_bw = 0;
    130	u8 i;
    131
    132	for (i = 0; i < HNAE3_MAX_TC; i++) {
    133		switch (ets->tc_tsa[i]) {
    134		case IEEE_8021QAZ_TSA_STRICT:
    135			if (hdev->tm_info.tc_info[i].tc_sch_mode !=
    136				HCLGE_SCH_MODE_SP)
    137				*changed = true;
    138			break;
    139		case IEEE_8021QAZ_TSA_ETS:
    140			/* The hardware will switch to sp mode if bandwidth is
    141			 * 0, so limit ets bandwidth must be greater than 0.
    142			 */
    143			if (!ets->tc_tx_bw[i]) {
    144				dev_err(&hdev->pdev->dev,
    145					"tc%u ets bw cannot be 0\n", i);
    146				return -EINVAL;
    147			}
    148
    149			if (hdev->tm_info.tc_info[i].tc_sch_mode !=
    150				HCLGE_SCH_MODE_DWRR)
    151				*changed = true;
    152
    153			total_ets_bw += ets->tc_tx_bw[i];
    154			has_ets_tc = true;
    155			break;
    156		default:
    157			return -EINVAL;
    158		}
    159	}
    160
    161	if (has_ets_tc && total_ets_bw != BW_PERCENT)
    162		return -EINVAL;
    163
    164	return 0;
    165}
    166
    167static int hclge_ets_validate(struct hclge_dev *hdev, struct ieee_ets *ets,
    168			      u8 *tc, bool *changed)
    169{
    170	u8 tc_num;
    171	int ret;
    172
    173	tc_num = hclge_ets_tc_changed(hdev, ets, changed);
    174
    175	ret = hclge_dcb_common_validate(hdev, tc_num, ets->prio_tc);
    176	if (ret)
    177		return ret;
    178
    179	ret = hclge_ets_sch_mode_validate(hdev, ets, changed);
    180	if (ret)
    181		return ret;
    182
    183	*tc = tc_num;
    184	if (*tc != hdev->tm_info.num_tc)
    185		*changed = true;
    186
    187	return 0;
    188}
    189
    190static int hclge_map_update(struct hclge_dev *hdev)
    191{
    192	int ret;
    193
    194	ret = hclge_tm_schd_setup_hw(hdev);
    195	if (ret)
    196		return ret;
    197
    198	ret = hclge_pause_setup_hw(hdev, false);
    199	if (ret)
    200		return ret;
    201
    202	ret = hclge_buffer_alloc(hdev);
    203	if (ret)
    204		return ret;
    205
    206	hclge_comm_rss_indir_init_cfg(hdev->ae_dev, &hdev->rss_cfg);
    207
    208	return hclge_rss_init_hw(hdev);
    209}
    210
    211static int hclge_notify_down_uinit(struct hclge_dev *hdev)
    212{
    213	int ret;
    214
    215	ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT);
    216	if (ret)
    217		return ret;
    218
    219	return hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT);
    220}
    221
    222static int hclge_notify_init_up(struct hclge_dev *hdev)
    223{
    224	int ret;
    225
    226	ret = hclge_notify_client(hdev, HNAE3_INIT_CLIENT);
    227	if (ret)
    228		return ret;
    229
    230	return hclge_notify_client(hdev, HNAE3_UP_CLIENT);
    231}
    232
    233static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets)
    234{
    235	struct hclge_vport *vport = hclge_get_vport(h);
    236	struct net_device *netdev = h->kinfo.netdev;
    237	struct hclge_dev *hdev = vport->back;
    238	bool map_changed = false;
    239	u8 num_tc = 0;
    240	int ret;
    241
    242	if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
    243	    hdev->flag & HCLGE_FLAG_MQPRIO_ENABLE)
    244		return -EINVAL;
    245
    246	ret = hclge_ets_validate(hdev, ets, &num_tc, &map_changed);
    247	if (ret)
    248		return ret;
    249
    250	if (map_changed) {
    251		netif_dbg(h, drv, netdev, "set ets\n");
    252
    253		ret = hclge_notify_down_uinit(hdev);
    254		if (ret)
    255			return ret;
    256	}
    257
    258	hclge_tm_schd_info_update(hdev, num_tc);
    259	if (num_tc > 1)
    260		hdev->flag |= HCLGE_FLAG_DCB_ENABLE;
    261	else
    262		hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE;
    263
    264	ret = hclge_ieee_ets_to_tm_info(hdev, ets);
    265	if (ret)
    266		goto err_out;
    267
    268	if (map_changed) {
    269		ret = hclge_map_update(hdev);
    270		if (ret)
    271			goto err_out;
    272
    273		return hclge_notify_init_up(hdev);
    274	}
    275
    276	return hclge_tm_dwrr_cfg(hdev);
    277
    278err_out:
    279	if (!map_changed)
    280		return ret;
    281
    282	hclge_notify_init_up(hdev);
    283
    284	return ret;
    285}
    286
    287static int hclge_ieee_getpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
    288{
    289	struct hclge_vport *vport = hclge_get_vport(h);
    290	struct hclge_dev *hdev = vport->back;
    291	int ret;
    292
    293	memset(pfc, 0, sizeof(*pfc));
    294	pfc->pfc_cap = hdev->pfc_max;
    295	pfc->pfc_en = hdev->tm_info.pfc_en;
    296
    297	ret = hclge_mac_update_stats(hdev);
    298	if (ret) {
    299		dev_err(&hdev->pdev->dev,
    300			"failed to update MAC stats, ret = %d.\n", ret);
    301		return ret;
    302	}
    303
    304	hclge_pfc_tx_stats_get(hdev, pfc->requests);
    305	hclge_pfc_rx_stats_get(hdev, pfc->indications);
    306
    307	return 0;
    308}
    309
    310static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
    311{
    312	struct hclge_vport *vport = hclge_get_vport(h);
    313	struct net_device *netdev = h->kinfo.netdev;
    314	struct hclge_dev *hdev = vport->back;
    315	u8 i, j, pfc_map, *prio_tc;
    316	int ret;
    317
    318	if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
    319		return -EINVAL;
    320
    321	if (pfc->pfc_en == hdev->tm_info.pfc_en)
    322		return 0;
    323
    324	prio_tc = hdev->tm_info.prio_tc;
    325	pfc_map = 0;
    326
    327	for (i = 0; i < hdev->tm_info.num_tc; i++) {
    328		for (j = 0; j < HNAE3_MAX_USER_PRIO; j++) {
    329			if ((prio_tc[j] == i) && (pfc->pfc_en & BIT(j))) {
    330				pfc_map |= BIT(i);
    331				break;
    332			}
    333		}
    334	}
    335
    336	hdev->tm_info.hw_pfc_map = pfc_map;
    337	hdev->tm_info.pfc_en = pfc->pfc_en;
    338
    339	netif_dbg(h, drv, netdev,
    340		  "set pfc: pfc_en=%x, pfc_map=%x, num_tc=%u\n",
    341		  pfc->pfc_en, pfc_map, hdev->tm_info.num_tc);
    342
    343	hclge_tm_pfc_info_update(hdev);
    344
    345	ret = hclge_pause_setup_hw(hdev, false);
    346	if (ret)
    347		return ret;
    348
    349	ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT);
    350	if (ret)
    351		return ret;
    352
    353	ret = hclge_buffer_alloc(hdev);
    354	if (ret) {
    355		hclge_notify_client(hdev, HNAE3_UP_CLIENT);
    356		return ret;
    357	}
    358
    359	return hclge_notify_client(hdev, HNAE3_UP_CLIENT);
    360}
    361
    362/* DCBX configuration */
    363static u8 hclge_getdcbx(struct hnae3_handle *h)
    364{
    365	struct hclge_vport *vport = hclge_get_vport(h);
    366	struct hclge_dev *hdev = vport->back;
    367
    368	if (hdev->flag & HCLGE_FLAG_MQPRIO_ENABLE)
    369		return 0;
    370
    371	return hdev->dcbx_cap;
    372}
    373
    374static u8 hclge_setdcbx(struct hnae3_handle *h, u8 mode)
    375{
    376	struct hclge_vport *vport = hclge_get_vport(h);
    377	struct net_device *netdev = h->kinfo.netdev;
    378	struct hclge_dev *hdev = vport->back;
    379
    380	netif_dbg(h, drv, netdev, "set dcbx: mode=%u\n", mode);
    381
    382	/* No support for LLD_MANAGED modes or CEE */
    383	if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
    384	    (mode & DCB_CAP_DCBX_VER_CEE) ||
    385	    !(mode & DCB_CAP_DCBX_HOST))
    386		return 1;
    387
    388	hdev->dcbx_cap = mode;
    389
    390	return 0;
    391}
    392
    393static int hclge_mqprio_qopt_check(struct hclge_dev *hdev,
    394				   struct tc_mqprio_qopt_offload *mqprio_qopt)
    395{
    396	u16 queue_sum = 0;
    397	int ret;
    398	int i;
    399
    400	if (!mqprio_qopt->qopt.num_tc) {
    401		mqprio_qopt->qopt.num_tc = 1;
    402		return 0;
    403	}
    404
    405	ret = hclge_dcb_common_validate(hdev, mqprio_qopt->qopt.num_tc,
    406					mqprio_qopt->qopt.prio_tc_map);
    407	if (ret)
    408		return ret;
    409
    410	for (i = 0; i < mqprio_qopt->qopt.num_tc; i++) {
    411		if (!is_power_of_2(mqprio_qopt->qopt.count[i])) {
    412			dev_err(&hdev->pdev->dev,
    413				"qopt queue count must be power of 2\n");
    414			return -EINVAL;
    415		}
    416
    417		if (mqprio_qopt->qopt.count[i] > hdev->pf_rss_size_max) {
    418			dev_err(&hdev->pdev->dev,
    419				"qopt queue count should be no more than %u\n",
    420				hdev->pf_rss_size_max);
    421			return -EINVAL;
    422		}
    423
    424		if (mqprio_qopt->qopt.offset[i] != queue_sum) {
    425			dev_err(&hdev->pdev->dev,
    426				"qopt queue offset must start from 0, and being continuous\n");
    427			return -EINVAL;
    428		}
    429
    430		if (mqprio_qopt->min_rate[i] || mqprio_qopt->max_rate[i]) {
    431			dev_err(&hdev->pdev->dev,
    432				"qopt tx_rate is not supported\n");
    433			return -EOPNOTSUPP;
    434		}
    435
    436		queue_sum = mqprio_qopt->qopt.offset[i];
    437		queue_sum += mqprio_qopt->qopt.count[i];
    438	}
    439	if (hdev->vport[0].alloc_tqps < queue_sum) {
    440		dev_err(&hdev->pdev->dev,
    441			"qopt queue count sum should be less than %u\n",
    442			hdev->vport[0].alloc_tqps);
    443		return -EINVAL;
    444	}
    445
    446	return 0;
    447}
    448
    449static void hclge_sync_mqprio_qopt(struct hnae3_tc_info *tc_info,
    450				   struct tc_mqprio_qopt_offload *mqprio_qopt)
    451{
    452	memset(tc_info, 0, sizeof(*tc_info));
    453	tc_info->num_tc = mqprio_qopt->qopt.num_tc;
    454	memcpy(tc_info->prio_tc, mqprio_qopt->qopt.prio_tc_map,
    455	       sizeof_field(struct hnae3_tc_info, prio_tc));
    456	memcpy(tc_info->tqp_count, mqprio_qopt->qopt.count,
    457	       sizeof_field(struct hnae3_tc_info, tqp_count));
    458	memcpy(tc_info->tqp_offset, mqprio_qopt->qopt.offset,
    459	       sizeof_field(struct hnae3_tc_info, tqp_offset));
    460}
    461
    462static int hclge_config_tc(struct hclge_dev *hdev,
    463			   struct hnae3_tc_info *tc_info)
    464{
    465	int i;
    466
    467	hclge_tm_schd_info_update(hdev, tc_info->num_tc);
    468	for (i = 0; i < HNAE3_MAX_USER_PRIO; i++)
    469		hdev->tm_info.prio_tc[i] = tc_info->prio_tc[i];
    470
    471	return hclge_map_update(hdev);
    472}
    473
    474/* Set up TC for hardware offloaded mqprio in channel mode */
    475static int hclge_setup_tc(struct hnae3_handle *h,
    476			  struct tc_mqprio_qopt_offload *mqprio_qopt)
    477{
    478	struct hclge_vport *vport = hclge_get_vport(h);
    479	struct hnae3_knic_private_info *kinfo;
    480	struct hclge_dev *hdev = vport->back;
    481	struct hnae3_tc_info old_tc_info;
    482	u8 tc = mqprio_qopt->qopt.num_tc;
    483	int ret;
    484
    485	/* if client unregistered, it's not allowed to change
    486	 * mqprio configuration, which may cause uninit ring
    487	 * fail.
    488	 */
    489	if (!test_bit(HCLGE_STATE_NIC_REGISTERED, &hdev->state))
    490		return -EBUSY;
    491
    492	if (hdev->flag & HCLGE_FLAG_DCB_ENABLE)
    493		return -EINVAL;
    494
    495	ret = hclge_mqprio_qopt_check(hdev, mqprio_qopt);
    496	if (ret) {
    497		dev_err(&hdev->pdev->dev,
    498			"failed to check mqprio qopt params, ret = %d\n", ret);
    499		return ret;
    500	}
    501
    502	ret = hclge_notify_down_uinit(hdev);
    503	if (ret)
    504		return ret;
    505
    506	kinfo = &vport->nic.kinfo;
    507	memcpy(&old_tc_info, &kinfo->tc_info, sizeof(old_tc_info));
    508	hclge_sync_mqprio_qopt(&kinfo->tc_info, mqprio_qopt);
    509	kinfo->tc_info.mqprio_active = tc > 0;
    510
    511	ret = hclge_config_tc(hdev, &kinfo->tc_info);
    512	if (ret)
    513		goto err_out;
    514
    515	hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE;
    516
    517	if (tc > 1)
    518		hdev->flag |= HCLGE_FLAG_MQPRIO_ENABLE;
    519	else
    520		hdev->flag &= ~HCLGE_FLAG_MQPRIO_ENABLE;
    521
    522	return hclge_notify_init_up(hdev);
    523
    524err_out:
    525	if (!tc) {
    526		dev_warn(&hdev->pdev->dev,
    527			 "failed to destroy mqprio, will active after reset, ret = %d\n",
    528			 ret);
    529	} else {
    530		/* roll-back */
    531		memcpy(&kinfo->tc_info, &old_tc_info, sizeof(old_tc_info));
    532		if (hclge_config_tc(hdev, &kinfo->tc_info))
    533			dev_err(&hdev->pdev->dev,
    534				"failed to roll back tc configuration\n");
    535	}
    536	hclge_notify_init_up(hdev);
    537
    538	return ret;
    539}
    540
    541static const struct hnae3_dcb_ops hns3_dcb_ops = {
    542	.ieee_getets	= hclge_ieee_getets,
    543	.ieee_setets	= hclge_ieee_setets,
    544	.ieee_getpfc	= hclge_ieee_getpfc,
    545	.ieee_setpfc	= hclge_ieee_setpfc,
    546	.getdcbx	= hclge_getdcbx,
    547	.setdcbx	= hclge_setdcbx,
    548	.setup_tc	= hclge_setup_tc,
    549};
    550
    551void hclge_dcb_ops_set(struct hclge_dev *hdev)
    552{
    553	struct hclge_vport *vport = hdev->vport;
    554	struct hnae3_knic_private_info *kinfo;
    555
    556	/* Hdev does not support DCB or vport is
    557	 * not a pf, then dcb_ops is not set.
    558	 */
    559	if (!hnae3_dev_dcb_supported(hdev) ||
    560	    vport->vport_id != 0)
    561		return;
    562
    563	kinfo = &vport->nic.kinfo;
    564	kinfo->dcb_ops = &hns3_dcb_ops;
    565	hdev->dcbx_cap = DCB_CAP_DCBX_VER_IEEE | DCB_CAP_DCBX_HOST;
    566}