ixgbe_dcb_nl.c 22.3 KB
Newer Older
1 2 3
/*******************************************************************************

  Intel 10 Gigabit PCI Express Linux driver
D
Don Skidmore 已提交
4
  Copyright(c) 1999 - 2013 Intel Corporation.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

  This program is free software; you can redistribute it and/or modify it
  under the terms and conditions of the GNU General Public License,
  version 2, as published by the Free Software Foundation.

  This program is distributed in the hope it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  more details.

  You should have received a copy of the GNU General Public License along with
  this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.

  The full GNU General Public License is included in this distribution in
  the file called "COPYING".

  Contact Information:
  Linux NICS <linux.nics@intel.com>
  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497

*******************************************************************************/

#include "ixgbe.h"
#include <linux/dcbnl.h>
31 32
#include "ixgbe_dcb_82598.h"
#include "ixgbe_dcb_82599.h"
33
#include "ixgbe_sriov.h"
34 35 36 37 38 39

/* Callbacks for DCB netlink in the kernel */
#define BIT_DCB_MODE	0x01
#define BIT_PFC		0x02
#define BIT_PG_RX	0x04
#define BIT_PG_TX	0x08
40
#define BIT_APP_UPCHG	0x10
41
#define BIT_LINKSPEED   0x80
42

43 44 45 46 47
/* Responses for the DCB_C_SET_ALL command */
#define DCB_HW_CHG_RST  0  /* DCB configuration changed with reset */
#define DCB_NO_HW_CHG   1  /* DCB configuration did not change */
#define DCB_HW_CHG      2  /* DCB configuration changed, no reset */

48
static int ixgbe_copy_dcb_cfg(struct ixgbe_adapter *adapter, int tc_max)
49
{
50 51
	struct ixgbe_dcb_config *scfg = &adapter->temp_dcb_cfg;
	struct ixgbe_dcb_config *dcfg = &adapter->dcb_cfg;
52 53 54 55 56 57
	struct tc_configuration *src = NULL;
	struct tc_configuration *dst = NULL;
	int i, j;
	int tx = DCB_TX_CONFIG;
	int rx = DCB_RX_CONFIG;
	int changes = 0;
58 59 60 61 62 63
#ifdef IXGBE_FCOE
	struct dcb_app app = {
			      .selector = DCB_APP_IDTYPE_ETHTYPE,
			      .protocol = ETH_P_FCOE,
			     };
	u8 up = dcb_getapp(adapter->netdev, &app);
64

65 66 67
	if (up && !(up & (1 << adapter->fcoe.up)))
		changes |= BIT_APP_UPCHG;
#endif
68 69

	for (i = DCB_PG_ATTR_TC_0; i < tc_max + DCB_PG_ATTR_TC_0; i++) {
70 71
		src = &scfg->tc_config[i - DCB_PG_ATTR_TC_0];
		dst = &dcfg->tc_config[i - DCB_PG_ATTR_TC_0];
72

73 74 75 76
		if (dst->path[tx].prio_type != src->path[tx].prio_type) {
			dst->path[tx].prio_type = src->path[tx].prio_type;
			changes |= BIT_PG_TX;
		}
77

78 79 80 81
		if (dst->path[tx].bwg_id != src->path[tx].bwg_id) {
			dst->path[tx].bwg_id = src->path[tx].bwg_id;
			changes |= BIT_PG_TX;
		}
82

83 84 85 86
		if (dst->path[tx].bwg_percent != src->path[tx].bwg_percent) {
			dst->path[tx].bwg_percent = src->path[tx].bwg_percent;
			changes |= BIT_PG_TX;
		}
87

88 89 90 91 92 93
		if (dst->path[tx].up_to_tc_bitmap !=
				src->path[tx].up_to_tc_bitmap) {
			dst->path[tx].up_to_tc_bitmap =
				src->path[tx].up_to_tc_bitmap;
			changes |= (BIT_PG_TX | BIT_PFC | BIT_APP_UPCHG);
		}
94

95 96 97 98
		if (dst->path[rx].prio_type != src->path[rx].prio_type) {
			dst->path[rx].prio_type = src->path[rx].prio_type;
			changes |= BIT_PG_RX;
		}
99

100 101 102 103
		if (dst->path[rx].bwg_id != src->path[rx].bwg_id) {
			dst->path[rx].bwg_id = src->path[rx].bwg_id;
			changes |= BIT_PG_RX;
		}
104

105 106 107 108
		if (dst->path[rx].bwg_percent != src->path[rx].bwg_percent) {
			dst->path[rx].bwg_percent = src->path[rx].bwg_percent;
			changes |= BIT_PG_RX;
		}
109

110 111 112 113 114 115
		if (dst->path[rx].up_to_tc_bitmap !=
				src->path[rx].up_to_tc_bitmap) {
			dst->path[rx].up_to_tc_bitmap =
				src->path[rx].up_to_tc_bitmap;
			changes |= (BIT_PG_RX | BIT_PFC | BIT_APP_UPCHG);
		}
116 117 118
	}

	for (i = DCB_PG_ATTR_BW_ID_0; i < DCB_PG_ATTR_BW_ID_MAX; i++) {
119 120 121 122 123 124 125 126 127
		j = i - DCB_PG_ATTR_BW_ID_0;
		if (dcfg->bw_percentage[tx][j] != scfg->bw_percentage[tx][j]) {
			dcfg->bw_percentage[tx][j] = scfg->bw_percentage[tx][j];
			changes |= BIT_PG_TX;
		}
		if (dcfg->bw_percentage[rx][j] != scfg->bw_percentage[rx][j]) {
			dcfg->bw_percentage[rx][j] = scfg->bw_percentage[rx][j];
			changes |= BIT_PG_RX;
		}
128 129 130
	}

	for (i = DCB_PFC_UP_ATTR_0; i < DCB_PFC_UP_ATTR_MAX; i++) {
131 132 133 134 135
		j = i - DCB_PFC_UP_ATTR_0;
		if (dcfg->tc_config[j].dcb_pfc != scfg->tc_config[j].dcb_pfc) {
			dcfg->tc_config[j].dcb_pfc = scfg->tc_config[j].dcb_pfc;
			changes |= BIT_PFC;
		}
136 137
	}

138 139 140 141
	if (dcfg->pfc_mode_enable != scfg->pfc_mode_enable) {
		dcfg->pfc_mode_enable = scfg->pfc_mode_enable;
		changes |= BIT_PFC;
	}
142

143
	return changes;
144 145 146 147 148 149 150 151 152
}

static u8 ixgbe_dcbnl_get_state(struct net_device *netdev)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);

	return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED);
}

153
static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
154 155
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);
156
	int err = 0;
157

158 159 160 161
	/* Fail command if not in CEE mode */
	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
		return 1;

162
	/* verify there is something to do, if not then exit */
163
	if (!state == !(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
164
		goto out;
165

166 167
	err = ixgbe_setup_tc(netdev,
			     state ? adapter->dcb_cfg.num_tcs.pg_tcs : 0);
168
out:
169
	return !!err;
170 171 172 173 174 175
}

static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev,
					 u8 *perm_addr)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);
176
	int i, j;
177

178 179
	memset(perm_addr, 0xff, MAX_ADDR_LEN);

180 181
	for (i = 0; i < netdev->addr_len; i++)
		perm_addr[i] = adapter->hw.mac.perm_addr[i];
182

D
Don Skidmore 已提交
183 184 185
	switch (adapter->hw.mac.type) {
	case ixgbe_mac_82599EB:
	case ixgbe_mac_X540:
186 187
		for (j = 0; j < netdev->addr_len; j++, i++)
			perm_addr[i] = adapter->hw.mac.san_addr[j];
D
Don Skidmore 已提交
188 189 190
		break;
	default:
		break;
191
	}
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
}

static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
                                         u8 prio, u8 bwg_id, u8 bw_pct,
                                         u8 up_map)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);

	if (prio != DCB_ATTR_VALUE_UNDEFINED)
		adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type = prio;
	if (bwg_id != DCB_ATTR_VALUE_UNDEFINED)
		adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id = bwg_id;
	if (bw_pct != DCB_ATTR_VALUE_UNDEFINED)
		adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent =
			bw_pct;
	if (up_map != DCB_ATTR_VALUE_UNDEFINED)
		adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap =
			up_map;
}

static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
                                          u8 bw_pct)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);

	adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct;
}

static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
                                         u8 prio, u8 bwg_id, u8 bw_pct,
                                         u8 up_map)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);

	if (prio != DCB_ATTR_VALUE_UNDEFINED)
		adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type = prio;
	if (bwg_id != DCB_ATTR_VALUE_UNDEFINED)
		adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id = bwg_id;
	if (bw_pct != DCB_ATTR_VALUE_UNDEFINED)
		adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent =
			bw_pct;
	if (up_map != DCB_ATTR_VALUE_UNDEFINED)
		adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap =
			up_map;
}

static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
                                          u8 bw_pct)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);

	adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct;
}

static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc,
                                         u8 *prio, u8 *bwg_id, u8 *bw_pct,
                                         u8 *up_map)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);

	*prio = adapter->dcb_cfg.tc_config[tc].path[0].prio_type;
	*bwg_id = adapter->dcb_cfg.tc_config[tc].path[0].bwg_id;
	*bw_pct = adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent;
	*up_map = adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap;
}

static void ixgbe_dcbnl_get_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
                                          u8 *bw_pct)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);

	*bw_pct = adapter->dcb_cfg.bw_percentage[0][bwg_id];
}

static void ixgbe_dcbnl_get_pg_tc_cfg_rx(struct net_device *netdev, int tc,
                                         u8 *prio, u8 *bwg_id, u8 *bw_pct,
                                         u8 *up_map)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);

	*prio = adapter->dcb_cfg.tc_config[tc].path[1].prio_type;
	*bwg_id = adapter->dcb_cfg.tc_config[tc].path[1].bwg_id;
	*bw_pct = adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent;
	*up_map = adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap;
}

static void ixgbe_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
                                          u8 *bw_pct)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);

	*bw_pct = adapter->dcb_cfg.bw_percentage[1][bwg_id];
}

static void ixgbe_dcbnl_set_pfc_cfg(struct net_device *netdev, int priority,
                                    u8 setting)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);

	adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc = setting;
	if (adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc !=
293
	    adapter->dcb_cfg.tc_config[priority].dcb_pfc)
294
		adapter->temp_dcb_cfg.pfc_mode_enable = true;
295 296 297 298 299 300 301 302 303 304
}

static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority,
                                    u8 *setting)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);

	*setting = adapter->dcb_cfg.tc_config[priority].dcb_pfc;
}

305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
static void ixgbe_dcbnl_devreset(struct net_device *dev)
{
	struct ixgbe_adapter *adapter = netdev_priv(dev);

	while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
		usleep_range(1000, 2000);

	if (netif_running(dev))
		dev->netdev_ops->ndo_stop(dev);

	ixgbe_clear_interrupt_scheme(adapter);
	ixgbe_init_interrupt_scheme(adapter);

	if (netif_running(dev))
		dev->netdev_ops->ndo_open(dev);

	clear_bit(__IXGBE_RESETTING, &adapter->state);
}

324 325 326
static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);
327 328
	struct ixgbe_dcb_config *dcb_cfg = &adapter->dcb_cfg;
	struct ixgbe_hw *hw = &adapter->hw;
329 330
	int ret = DCB_NO_HW_CHG;
	int i;
331

332 333
	/* Fail command if not in CEE mode */
	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
334
		return ret;
335

336
	adapter->dcb_set_bitmap |= ixgbe_copy_dcb_cfg(adapter,
337 338 339
						      MAX_TRAFFIC_CLASS);
	if (!adapter->dcb_set_bitmap)
		return ret;
340

341 342 343
	if (adapter->dcb_set_bitmap & (BIT_PG_TX|BIT_PG_RX)) {
		u16 refill[MAX_TRAFFIC_CLASS], max[MAX_TRAFFIC_CLASS];
		u8 bwg_id[MAX_TRAFFIC_CLASS], prio_type[MAX_TRAFFIC_CLASS];
344
		/* Priority to TC mapping in CEE case default to 1:1 */
345
		u8 prio_tc[MAX_USER_PRIORITY];
346 347
		int max_frame = adapter->netdev->mtu + ETH_HLEN + ETH_FCS_LEN;

348
#ifdef IXGBE_FCOE
349 350 351 352
		if (adapter->netdev->features & NETIF_F_FCOE_MTU)
			max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
#endif

353 354 355 356
		ixgbe_dcb_calculate_tc_credits(hw, dcb_cfg, max_frame,
					       DCB_TX_CONFIG);
		ixgbe_dcb_calculate_tc_credits(hw, dcb_cfg, max_frame,
					       DCB_RX_CONFIG);
357

358 359 360 361 362
		ixgbe_dcb_unpack_refill(dcb_cfg, DCB_TX_CONFIG, refill);
		ixgbe_dcb_unpack_max(dcb_cfg, max);
		ixgbe_dcb_unpack_bwgid(dcb_cfg, DCB_TX_CONFIG, bwg_id);
		ixgbe_dcb_unpack_prio(dcb_cfg, DCB_TX_CONFIG, prio_type);
		ixgbe_dcb_unpack_map(dcb_cfg, DCB_TX_CONFIG, prio_tc);
363

364 365
		ixgbe_dcb_hw_ets_config(hw, refill, max, bwg_id,
					prio_type, prio_tc);
366 367 368

		for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
			netdev_set_prio_tc_map(netdev, i, prio_tc[i]);
369 370

		ret = DCB_HW_CHG_RST;
371 372 373
	}

	if (adapter->dcb_set_bitmap & BIT_PFC) {
374 375 376 377 378 379 380 381 382 383
		if (dcb_cfg->pfc_mode_enable) {
			u8 pfc_en;
			u8 prio_tc[MAX_USER_PRIORITY];

			ixgbe_dcb_unpack_map(dcb_cfg, DCB_TX_CONFIG, prio_tc);
			ixgbe_dcb_unpack_pfc(dcb_cfg, &pfc_en);
			ixgbe_dcb_hw_pfc_config(hw, pfc_en, prio_tc);
		} else {
			hw->mac.ops.fc_enable(hw);
		}
384 385 386

		ixgbe_set_rx_drop_en(adapter);

387
		ret = DCB_HW_CHG;
388 389
	}

390
#ifdef IXGBE_FCOE
391 392 393 394
	/* Reprogam FCoE hardware offloads when the traffic class
	 * FCoE is using changes. This happens if the APP info
	 * changes or the up2tc mapping is updated.
	 */
395 396 397 398 399 400 401
	if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) {
		struct dcb_app app = {
				      .selector = DCB_APP_IDTYPE_ETHTYPE,
				      .protocol = ETH_P_FCOE,
				     };
		u8 up = dcb_getapp(netdev, &app);

402 403 404 405 406 407
		adapter->fcoe.up = ffs(up) - 1;
		ixgbe_dcbnl_devreset(netdev);
		ret = DCB_HW_CHG_RST;
	}
#endif

408 409 410 411
	adapter->dcb_set_bitmap = 0x00;
	return ret;
}

412 413 414 415
static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);

416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
	switch (capid) {
	case DCB_CAP_ATTR_PG:
		*cap = true;
		break;
	case DCB_CAP_ATTR_PFC:
		*cap = true;
		break;
	case DCB_CAP_ATTR_UP2TC:
		*cap = false;
		break;
	case DCB_CAP_ATTR_PG_TCS:
		*cap = 0x80;
		break;
	case DCB_CAP_ATTR_PFC_TCS:
		*cap = 0x80;
		break;
	case DCB_CAP_ATTR_GSP:
		*cap = true;
		break;
	case DCB_CAP_ATTR_BCN:
		*cap = false;
		break;
	case DCB_CAP_ATTR_DCBX:
		*cap = adapter->dcbx_cap;
		break;
	default:
		*cap = false;
		break;
444 445
	}

446
	return 0;
447 448
}

449
static int ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num)
450 451 452 453 454 455
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);

	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
		switch (tcid) {
		case DCB_NUMTCS_ATTR_PG:
456
			*num = adapter->dcb_cfg.num_tcs.pg_tcs;
457 458
			break;
		case DCB_NUMTCS_ATTR_PFC:
459
			*num = adapter->dcb_cfg.num_tcs.pfc_tcs;
460 461
			break;
		default:
462
			return -EINVAL;
463 464 465
			break;
		}
	} else {
466
		return -EINVAL;
467 468
	}

469
	return 0;
470 471
}

472
static int ixgbe_dcbnl_setnumtcs(struct net_device *netdev, int tcid, u8 num)
473 474 475 476
{
	return -EINVAL;
}

477 478 479 480
static u8 ixgbe_dcbnl_getpfcstate(struct net_device *netdev)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);

481
	return adapter->dcb_cfg.pfc_mode_enable;
482 483 484 485
}

static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
{
486 487 488
	struct ixgbe_adapter *adapter = netdev_priv(netdev);

	adapter->temp_dcb_cfg.pfc_mode_enable = state;
489 490
}

491 492 493 494 495 496 497 498 499 500 501 502
/**
 * ixgbe_dcbnl_getapp - retrieve the DCBX application user priority
 * @netdev : the corresponding netdev
 * @idtype : identifies the id as ether type or TCP/UDP port number
 * @id: id is either ether type or TCP/UDP port number
 *
 * Returns : on success, returns a non-zero 802.1p user priority bitmap
 * otherwise returns 0 as the invalid user priority bitmap to indicate an
 * error.
 */
static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
{
503
	struct ixgbe_adapter *adapter = netdev_priv(netdev);
504 505 506 507
	struct dcb_app app = {
				.selector = idtype,
				.protocol = id,
			     };
508

509
	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
510
		return 0;
511

512
	return dcb_getapp(netdev, &app);
513 514
}

515 516 517 518 519 520
static int ixgbe_dcbnl_ieee_getets(struct net_device *dev,
				   struct ieee_ets *ets)
{
	struct ixgbe_adapter *adapter = netdev_priv(dev);
	struct ieee_ets *my_ets = adapter->ixgbe_ieee_ets;

521 522
	ets->ets_cap = adapter->dcb_cfg.num_tcs.pg_tcs;

523 524
	/* No IEEE PFC settings available */
	if (!my_ets)
525
		return 0;
526 527 528 529 530 531 532 533 534 535 536 537 538 539

	ets->cbs = my_ets->cbs;
	memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw));
	memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw));
	memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa));
	memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc));
	return 0;
}

static int ixgbe_dcbnl_ieee_setets(struct net_device *dev,
				   struct ieee_ets *ets)
{
	struct ixgbe_adapter *adapter = netdev_priv(dev);
	int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
540
	int i, err = 0;
541
	__u8 max_tc = 0;
542
	__u8 map_chg = 0;
543

544 545 546
	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
		return -EINVAL;

547 548 549 550 551 552
	if (!adapter->ixgbe_ieee_ets) {
		adapter->ixgbe_ieee_ets = kmalloc(sizeof(struct ieee_ets),
						  GFP_KERNEL);
		if (!adapter->ixgbe_ieee_ets)
			return -ENOMEM;

553 554 555 556
		/* initialize UP2TC mappings to invalid value */
		for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
			adapter->ixgbe_ieee_ets->prio_tc[i] =
				IEEE_8021QAZ_MAX_TCS;
557 558 559
		/* if possible update UP2TC mappings from HW */
		ixgbe_dcb_read_rtrup2tc(&adapter->hw,
					adapter->ixgbe_ieee_ets->prio_tc);
560
	}
561

562
	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
563 564
		if (ets->prio_tc[i] > max_tc)
			max_tc = ets->prio_tc[i];
565 566
		if (ets->prio_tc[i] != adapter->ixgbe_ieee_ets->prio_tc[i])
			map_chg = 1;
567 568
	}

569 570
	memcpy(adapter->ixgbe_ieee_ets, ets, sizeof(*adapter->ixgbe_ieee_ets));

571 572
	if (max_tc)
		max_tc++;
573

574 575 576
	if (max_tc > adapter->dcb_cfg.num_tcs.pg_tcs)
		return -EINVAL;

577
	if (max_tc != netdev_get_num_tc(dev))
578
		err = ixgbe_setup_tc(dev, max_tc);
579 580
	else if (map_chg)
		ixgbe_dcbnl_devreset(dev);
581 582 583

	if (err)
		goto err_out;
584

585 586 587
	err = ixgbe_dcb_hw_ets(&adapter->hw, ets, max_frame);
err_out:
	return err;
588 589 590 591 592 593 594 595 596
}

static int ixgbe_dcbnl_ieee_getpfc(struct net_device *dev,
				   struct ieee_pfc *pfc)
{
	struct ixgbe_adapter *adapter = netdev_priv(dev);
	struct ieee_pfc *my_pfc = adapter->ixgbe_ieee_pfc;
	int i;

597 598
	pfc->pfc_cap = adapter->dcb_cfg.num_tcs.pfc_tcs;

599 600
	/* No IEEE PFC settings available */
	if (!my_pfc)
601
		return 0;
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618

	pfc->pfc_en = my_pfc->pfc_en;
	pfc->mbc = my_pfc->mbc;
	pfc->delay = my_pfc->delay;

	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
		pfc->requests[i] = adapter->stats.pxoffrxc[i];
		pfc->indications[i] = adapter->stats.pxofftxc[i];
	}

	return 0;
}

static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
				   struct ieee_pfc *pfc)
{
	struct ixgbe_adapter *adapter = netdev_priv(dev);
619
	struct ixgbe_hw *hw = &adapter->hw;
620
	u8 *prio_tc;
621
	int err;
622

623 624 625
	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
		return -EINVAL;

626 627 628 629 630 631 632
	if (!adapter->ixgbe_ieee_pfc) {
		adapter->ixgbe_ieee_pfc = kmalloc(sizeof(struct ieee_pfc),
						  GFP_KERNEL);
		if (!adapter->ixgbe_ieee_pfc)
			return -ENOMEM;
	}

633
	prio_tc = adapter->ixgbe_ieee_ets->prio_tc;
634
	memcpy(adapter->ixgbe_ieee_pfc, pfc, sizeof(*adapter->ixgbe_ieee_pfc));
635 636 637 638 639 640 641

	/* Enable link flow control parameters if PFC is disabled */
	if (pfc->pfc_en)
		err = ixgbe_dcb_hw_pfc_config(hw, pfc->pfc_en, prio_tc);
	else
		err = hw->mac.ops.fc_enable(hw);

642 643
	ixgbe_set_rx_drop_en(adapter);

644
	return err;
645 646
}

647 648 649 650
static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev,
				   struct dcb_app *app)
{
	struct ixgbe_adapter *adapter = netdev_priv(dev);
651
	int err = -EINVAL;
652 653

	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
654
		return err;
655

656
	err = dcb_ieee_setapp(dev, app);
657 658
	if (err)
		return err;
659

660
#ifdef IXGBE_FCOE
661
	if (app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
662 663 664 665 666 667 668
	    app->protocol == ETH_P_FCOE) {
		u8 app_mask = dcb_ieee_getapp_mask(dev, app);

		if (app_mask & (1 << adapter->fcoe.up))
			return err;

		adapter->fcoe.up = app->priority;
669 670 671
		ixgbe_dcbnl_devreset(dev);
	}
#endif
672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688

	/* VF devices should use default UP when available */
	if (app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
	    app->protocol == 0) {
		int vf;

		adapter->default_up = app->priority;

		for (vf = 0; vf < adapter->num_vfs; vf++) {
			struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];

			if (!vfinfo->pf_qos)
				ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
						app->priority, vf);
		}
	}

689 690 691 692 693 694 695 696 697 698 699
	return 0;
}

static int ixgbe_dcbnl_ieee_delapp(struct net_device *dev,
				   struct dcb_app *app)
{
	struct ixgbe_adapter *adapter = netdev_priv(dev);
	int err;

	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
		return -EINVAL;
700

701
	err = dcb_ieee_delapp(dev, app);
702

703 704 705 706 707 708 709
#ifdef IXGBE_FCOE
	if (!err && app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
	    app->protocol == ETH_P_FCOE) {
		u8 app_mask = dcb_ieee_getapp_mask(dev, app);

		if (app_mask & (1 << adapter->fcoe.up))
			return err;
710

711 712 713
		adapter->fcoe.up = app_mask ?
				   ffs(app_mask) - 1 : IXGBE_FCOE_DEFTC;
		ixgbe_dcbnl_devreset(dev);
714
	}
715
#endif
716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733
	/* IF default priority is being removed clear VF default UP */
	if (app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
	    app->protocol == 0 && adapter->default_up == app->priority) {
		int vf;
		long unsigned int app_mask = dcb_ieee_getapp_mask(dev, app);
		int qos = app_mask ? find_first_bit(&app_mask, 8) : 0;

		adapter->default_up = qos;

		for (vf = 0; vf < adapter->num_vfs; vf++) {
			struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];

			if (!vfinfo->pf_qos)
				ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
						qos, vf);
		}
	}

734
	return err;
735 736
}

737 738 739 740 741 742 743 744 745 746 747
static u8 ixgbe_dcbnl_getdcbx(struct net_device *dev)
{
	struct ixgbe_adapter *adapter = netdev_priv(dev);
	return adapter->dcbx_cap;
}

static u8 ixgbe_dcbnl_setdcbx(struct net_device *dev, u8 mode)
{
	struct ixgbe_adapter *adapter = netdev_priv(dev);
	struct ieee_ets ets = {0};
	struct ieee_pfc pfc = {0};
748
	int err = 0;
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768

	/* no support for LLD_MANAGED modes or CEE+IEEE */
	if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
	    ((mode & DCB_CAP_DCBX_VER_IEEE) && (mode & DCB_CAP_DCBX_VER_CEE)) ||
	    !(mode & DCB_CAP_DCBX_HOST))
		return 1;

	if (mode == adapter->dcbx_cap)
		return 0;

	adapter->dcbx_cap = mode;

	/* ETS and PFC defaults */
	ets.ets_cap = 8;
	pfc.pfc_cap = 8;

	if (mode & DCB_CAP_DCBX_VER_IEEE) {
		ixgbe_dcbnl_ieee_setets(dev, &ets);
		ixgbe_dcbnl_ieee_setpfc(dev, &pfc);
	} else if (mode & DCB_CAP_DCBX_VER_CEE) {
769 770 771
		u8 mask = BIT_PFC | BIT_PG_TX | BIT_PG_RX | BIT_APP_UPCHG;

		adapter->dcb_set_bitmap |= mask;
772 773 774 775 776 777 778
		ixgbe_dcbnl_set_all(dev);
	} else {
		/* Drop into single TC mode strict priority as this
		 * indicates CEE and IEEE versions are disabled
		 */
		ixgbe_dcbnl_ieee_setets(dev, &ets);
		ixgbe_dcbnl_ieee_setpfc(dev, &pfc);
779
		err = ixgbe_setup_tc(dev, 0);
780 781
	}

782
	return err ? 1 : 0;
783 784
}

785
const struct dcbnl_rtnl_ops dcbnl_ops = {
786 787 788 789
	.ieee_getets	= ixgbe_dcbnl_ieee_getets,
	.ieee_setets	= ixgbe_dcbnl_ieee_setets,
	.ieee_getpfc	= ixgbe_dcbnl_ieee_getpfc,
	.ieee_setpfc	= ixgbe_dcbnl_ieee_setpfc,
790
	.ieee_setapp	= ixgbe_dcbnl_ieee_setapp,
791
	.ieee_delapp	= ixgbe_dcbnl_ieee_delapp,
792 793 794 795 796 797 798 799 800 801 802 803 804
	.getstate	= ixgbe_dcbnl_get_state,
	.setstate	= ixgbe_dcbnl_set_state,
	.getpermhwaddr	= ixgbe_dcbnl_get_perm_hw_addr,
	.setpgtccfgtx	= ixgbe_dcbnl_set_pg_tc_cfg_tx,
	.setpgbwgcfgtx	= ixgbe_dcbnl_set_pg_bwg_cfg_tx,
	.setpgtccfgrx	= ixgbe_dcbnl_set_pg_tc_cfg_rx,
	.setpgbwgcfgrx	= ixgbe_dcbnl_set_pg_bwg_cfg_rx,
	.getpgtccfgtx	= ixgbe_dcbnl_get_pg_tc_cfg_tx,
	.getpgbwgcfgtx	= ixgbe_dcbnl_get_pg_bwg_cfg_tx,
	.getpgtccfgrx	= ixgbe_dcbnl_get_pg_tc_cfg_rx,
	.getpgbwgcfgrx	= ixgbe_dcbnl_get_pg_bwg_cfg_rx,
	.setpfccfg	= ixgbe_dcbnl_set_pfc_cfg,
	.getpfccfg	= ixgbe_dcbnl_get_pfc_cfg,
805
	.setall		= ixgbe_dcbnl_set_all,
806 807
	.getcap		= ixgbe_dcbnl_getcap,
	.getnumtcs	= ixgbe_dcbnl_getnumtcs,
808 809
	.setnumtcs	= ixgbe_dcbnl_setnumtcs,
	.getpfcstate	= ixgbe_dcbnl_getpfcstate,
A
Alexander Duyck 已提交
810
	.setpfcstate	= ixgbe_dcbnl_setpfcstate,
811
	.getapp		= ixgbe_dcbnl_getapp,
812 813
	.getdcbx	= ixgbe_dcbnl_getdcbx,
	.setdcbx	= ixgbe_dcbnl_setdcbx,
814
};