ocelot.c 43.7 KB
Newer Older
1 2 3 4 5 6 7
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
 * Microsemi Ocelot Switch driver
 *
 * Copyright (c) 2017 Microsemi Corporation
 */
#include <linux/if_bridge.h>
8
#include <soc/mscc/ocelot_vcap.h>
9
#include "ocelot.h"
10
#include "ocelot_vcap.h"
11

12 13 14
#define TABLE_UPDATE_SLEEP_US 10
#define TABLE_UPDATE_TIMEOUT_US 100000

15 16 17 18 19 20
struct ocelot_mact_entry {
	u8 mac[ETH_ALEN];
	u16 vid;
	enum macaccess_entry_type type;
};

21
static inline u32 ocelot_mact_read_macaccess(struct ocelot *ocelot)
22
{
23 24
	return ocelot_read(ocelot, ANA_TABLES_MACACCESS);
}
25

26 27 28
static inline int ocelot_mact_wait_for_completion(struct ocelot *ocelot)
{
	u32 val;
29

30 31 32 33 34
	return readx_poll_timeout(ocelot_mact_read_macaccess,
		ocelot, val,
		(val & ANA_TABLES_MACACCESS_MAC_TABLE_CMD_M) ==
		MACACCESS_CMD_IDLE,
		TABLE_UPDATE_SLEEP_US, TABLE_UPDATE_TIMEOUT_US);
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
}

static void ocelot_mact_select(struct ocelot *ocelot,
			       const unsigned char mac[ETH_ALEN],
			       unsigned int vid)
{
	u32 macl = 0, mach = 0;

	/* Set the MAC address to handle and the vlan associated in a format
	 * understood by the hardware.
	 */
	mach |= vid    << 16;
	mach |= mac[0] << 8;
	mach |= mac[1] << 0;
	macl |= mac[2] << 24;
	macl |= mac[3] << 16;
	macl |= mac[4] << 8;
	macl |= mac[5] << 0;

	ocelot_write(ocelot, macl, ANA_TABLES_MACLDATA);
	ocelot_write(ocelot, mach, ANA_TABLES_MACHDATA);

}

59 60 61
int ocelot_mact_learn(struct ocelot *ocelot, int port,
		      const unsigned char mac[ETH_ALEN],
		      unsigned int vid, enum macaccess_entry_type type)
62 63 64 65 66 67 68 69 70 71 72 73
{
	ocelot_mact_select(ocelot, mac, vid);

	/* Issue a write command */
	ocelot_write(ocelot, ANA_TABLES_MACACCESS_VALID |
			     ANA_TABLES_MACACCESS_DEST_IDX(port) |
			     ANA_TABLES_MACACCESS_ENTRYTYPE(type) |
			     ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_LEARN),
			     ANA_TABLES_MACACCESS);

	return ocelot_mact_wait_for_completion(ocelot);
}
74
EXPORT_SYMBOL(ocelot_mact_learn);
75

76 77
int ocelot_mact_forget(struct ocelot *ocelot,
		       const unsigned char mac[ETH_ALEN], unsigned int vid)
78 79 80 81 82 83 84 85 86 87
{
	ocelot_mact_select(ocelot, mac, vid);

	/* Issue a forget command */
	ocelot_write(ocelot,
		     ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_FORGET),
		     ANA_TABLES_MACACCESS);

	return ocelot_mact_wait_for_completion(ocelot);
}
88
EXPORT_SYMBOL(ocelot_mact_forget);
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105

static void ocelot_mact_init(struct ocelot *ocelot)
{
	/* Configure the learning mode entries attributes:
	 * - Do not copy the frame to the CPU extraction queues.
	 * - Use the vlan and mac_cpoy for dmac lookup.
	 */
	ocelot_rmw(ocelot, 0,
		   ANA_AGENCTRL_LEARN_CPU_COPY | ANA_AGENCTRL_IGNORE_DMAC_FLAGS
		   | ANA_AGENCTRL_LEARN_FWD_KILL
		   | ANA_AGENCTRL_LEARN_IGNORE_VLAN,
		   ANA_AGENCTRL);

	/* Clear the MAC table */
	ocelot_write(ocelot, MACACCESS_CMD_INIT, ANA_TABLES_MACACCESS);
}

106
static void ocelot_vcap_enable(struct ocelot *ocelot, int port)
107 108 109
{
	ocelot_write_gix(ocelot, ANA_PORT_VCAP_S2_CFG_S2_ENA |
			 ANA_PORT_VCAP_S2_CFG_S2_IP6_CFG(0xa),
110
			 ANA_PORT_VCAP_S2_CFG, port);
111 112 113

	ocelot_write_gix(ocelot, ANA_PORT_VCAP_CFG_S1_ENA,
			 ANA_PORT_VCAP_CFG, port);
114 115 116 117

	ocelot_rmw_gix(ocelot, REW_PORT_CFG_ES0_EN,
		       REW_PORT_CFG_ES0_EN,
		       REW_PORT_CFG, port);
118 119
}

120
static inline u32 ocelot_vlant_read_vlanaccess(struct ocelot *ocelot)
121
{
122 123
	return ocelot_read(ocelot, ANA_TABLES_VLANACCESS);
}
124

125 126 127 128 129 130 131 132 133 134
static inline int ocelot_vlant_wait_for_completion(struct ocelot *ocelot)
{
	u32 val;

	return readx_poll_timeout(ocelot_vlant_read_vlanaccess,
		ocelot,
		val,
		(val & ANA_TABLES_VLANACCESS_VLAN_TBL_CMD_M) ==
		ANA_TABLES_VLANACCESS_CMD_IDLE,
		TABLE_UPDATE_SLEEP_US, TABLE_UPDATE_TIMEOUT_US);
135 136
}

137 138 139 140 141 142 143 144 145 146 147 148 149
static int ocelot_vlant_set_mask(struct ocelot *ocelot, u16 vid, u32 mask)
{
	/* Select the VID to configure */
	ocelot_write(ocelot, ANA_TABLES_VLANTIDX_V_INDEX(vid),
		     ANA_TABLES_VLANTIDX);
	/* Set the vlan port members mask and issue a write command */
	ocelot_write(ocelot, ANA_TABLES_VLANACCESS_VLAN_PORT_MASK(mask) |
			     ANA_TABLES_VLANACCESS_CMD_WRITE,
		     ANA_TABLES_VLANACCESS);

	return ocelot_vlant_wait_for_completion(ocelot);
}

150 151
static void ocelot_port_set_native_vlan(struct ocelot *ocelot, int port,
					struct ocelot_vlan native_vlan)
152
{
153
	struct ocelot_port *ocelot_port = ocelot->ports[port];
154
	u32 val = 0;
155

156 157
	ocelot_port->native_vlan = native_vlan;

158
	ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_VID(native_vlan.vid),
159 160
		       REW_PORT_VLAN_CFG_PORT_VID_M,
		       REW_PORT_VLAN_CFG, port);
161

162
	if (ocelot_port->vlan_aware) {
163
		if (native_vlan.valid)
164
			/* Tag all frames except when VID == DEFAULT_VLAN */
165
			val = REW_TAG_CFG_TAG_CFG(1);
166 167
		else
			/* Tag all frames */
168
			val = REW_TAG_CFG_TAG_CFG(3);
169 170 171
	} else {
		/* Port tagging disabled. */
		val = REW_TAG_CFG_TAG_CFG(0);
172 173 174
	}
	ocelot_rmw_gix(ocelot, val,
		       REW_TAG_CFG_TAG_CFG_M,
175 176 177
		       REW_TAG_CFG, port);
}

178
/* Default vlan to clasify for untagged frames (may be zero) */
179 180
static void ocelot_port_set_pvid(struct ocelot *ocelot, int port,
				 struct ocelot_vlan pvid_vlan)
181 182
{
	struct ocelot_port *ocelot_port = ocelot->ports[port];
183
	u32 val = 0;
184

185
	ocelot_port->pvid_vlan = pvid_vlan;
186 187

	if (!ocelot_port->vlan_aware)
188
		pvid_vlan.vid = 0;
189 190

	ocelot_rmw_gix(ocelot,
191
		       ANA_PORT_VLAN_CFG_VLAN_VID(pvid_vlan.vid),
192 193
		       ANA_PORT_VLAN_CFG_VLAN_VID_M,
		       ANA_PORT_VLAN_CFG, port);
194 195 196 197 198 199 200 201 202 203 204 205 206 207

	/* If there's no pvid, we should drop not only untagged traffic (which
	 * happens automatically), but also 802.1p traffic which gets
	 * classified to VLAN 0, but that is always in our RX filter, so it
	 * would get accepted were it not for this setting.
	 */
	if (!pvid_vlan.valid && ocelot_port->vlan_aware)
		val = ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |
		      ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA;

	ocelot_rmw_gix(ocelot, val,
		       ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |
		       ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA,
		       ANA_PORT_DROP_CFG, port);
208 209
}

210 211
int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
			       bool vlan_aware, struct switchdev_trans *trans)
212 213
{
	struct ocelot_port *ocelot_port = ocelot->ports[port];
214
	u32 val;
215

216 217 218 219 220 221 222 223 224 225 226 227 228
	if (switchdev_trans_ph_prepare(trans)) {
		struct ocelot_vcap_block *block = &ocelot->block[VCAP_IS1];
		struct ocelot_vcap_filter *filter;

		list_for_each_entry(filter, &block->rules, list) {
			if (filter->ingress_port_mask & BIT(port) &&
			    filter->action.vid_replace_ena) {
				dev_err(ocelot->dev,
					"Cannot change VLAN state with vlan modify rules active\n");
				return -EBUSY;
			}
		}

229
		return 0;
230
	}
231

232
	ocelot_port->vlan_aware = vlan_aware;
233

234 235 236 237 238 239 240 241 242
	if (vlan_aware)
		val = ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
		      ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1);
	else
		val = 0;
	ocelot_rmw_gix(ocelot, val,
		       ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
		       ANA_PORT_VLAN_CFG_VLAN_POP_CNT_M,
		       ANA_PORT_VLAN_CFG, port);
243

244 245
	ocelot_port_set_pvid(ocelot, port, ocelot_port->pvid_vlan);
	ocelot_port_set_native_vlan(ocelot, port, ocelot_port->native_vlan);
246 247

	return 0;
248
}
249
EXPORT_SYMBOL(ocelot_port_vlan_filtering);
250

251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
int ocelot_vlan_prepare(struct ocelot *ocelot, int port, u16 vid, bool pvid,
			bool untagged)
{
	struct ocelot_port *ocelot_port = ocelot->ports[port];

	/* Deny changing the native VLAN, but always permit deleting it */
	if (untagged && ocelot_port->native_vlan.vid != vid &&
	    ocelot_port->native_vlan.valid) {
		dev_err(ocelot->dev,
			"Port already has a native VLAN: %d\n",
			ocelot_port->native_vlan.vid);
		return -EBUSY;
	}

	return 0;
}
EXPORT_SYMBOL(ocelot_vlan_prepare);

269 270
int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid,
		    bool untagged)
271 272 273 274
{
	int ret;

	/* Make the port a member of the VLAN */
275
	ocelot->vlan_mask[vid] |= BIT(port);
276 277 278 279 280
	ret = ocelot_vlant_set_mask(ocelot, vid, ocelot->vlan_mask[vid]);
	if (ret)
		return ret;

	/* Default ingress vlan classification */
281 282 283 284
	if (pvid) {
		struct ocelot_vlan pvid_vlan;

		pvid_vlan.vid = vid;
285
		pvid_vlan.valid = true;
286 287
		ocelot_port_set_pvid(ocelot, port, pvid_vlan);
	}
288 289

	/* Untagged egress vlan clasification */
290
	if (untagged) {
291 292 293
		struct ocelot_vlan native_vlan;

		native_vlan.vid = vid;
294
		native_vlan.valid = true;
295
		ocelot_port_set_native_vlan(ocelot, port, native_vlan);
296
	}
297 298 299

	return 0;
}
300
EXPORT_SYMBOL(ocelot_vlan_add);
301

302
int ocelot_vlan_del(struct ocelot *ocelot, int port, u16 vid)
303 304 305
{
	struct ocelot_port *ocelot_port = ocelot->ports[port];
	int ret;
306 307

	/* Stop the port from being a member of the vlan */
308
	ocelot->vlan_mask[vid] &= ~BIT(port);
309 310 311 312
	ret = ocelot_vlant_set_mask(ocelot, vid, ocelot->vlan_mask[vid]);
	if (ret)
		return ret;

313 314 315 316 317 318 319
	/* Ingress */
	if (ocelot_port->pvid_vlan.vid == vid) {
		struct ocelot_vlan pvid_vlan = {0};

		ocelot_port_set_pvid(ocelot, port, pvid_vlan);
	}

320
	/* Egress */
321
	if (ocelot_port->native_vlan.vid == vid) {
322
		struct ocelot_vlan native_vlan = {0};
323 324 325

		ocelot_port_set_native_vlan(ocelot, port, native_vlan);
	}
326 327 328

	return 0;
}
329
EXPORT_SYMBOL(ocelot_vlan_del);
330

331 332
static void ocelot_vlan_init(struct ocelot *ocelot)
{
333 334
	u16 port, vid;

335 336 337 338
	/* Clear VLAN table, by default all ports are members of all VLANs */
	ocelot_write(ocelot, ANA_TABLES_VLANACCESS_CMD_INIT,
		     ANA_TABLES_VLANACCESS);
	ocelot_vlant_wait_for_completion(ocelot);
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355

	/* Configure the port VLAN memberships */
	for (vid = 1; vid < VLAN_N_VID; vid++) {
		ocelot->vlan_mask[vid] = 0;
		ocelot_vlant_set_mask(ocelot, vid, ocelot->vlan_mask[vid]);
	}

	/* Because VLAN filtering is enabled, we need VID 0 to get untagged
	 * traffic.  It is added automatically if 8021q module is loaded, but
	 * we can't rely on it since module may be not loaded.
	 */
	ocelot->vlan_mask[0] = GENMASK(ocelot->num_phys_ports - 1, 0);
	ocelot_vlant_set_mask(ocelot, 0, ocelot->vlan_mask[0]);

	/* Set vlan ingress filter mask to all ports but the CPU port by
	 * default.
	 */
356 357
	ocelot_write(ocelot, GENMASK(ocelot->num_phys_ports - 1, 0),
		     ANA_VLANMASK);
358 359 360 361 362

	for (port = 0; port < ocelot->num_phys_ports; port++) {
		ocelot_write_gix(ocelot, 0, REW_PORT_VLAN_CFG, port);
		ocelot_write_gix(ocelot, 0, REW_TAG_CFG, port);
	}
363 364
}

365 366
void ocelot_adjust_link(struct ocelot *ocelot, int port,
			struct phy_device *phydev)
367
{
368
	struct ocelot_port *ocelot_port = ocelot->ports[port];
369
	int speed, mode = 0;
370

371
	switch (phydev->speed) {
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
	case SPEED_10:
		speed = OCELOT_SPEED_10;
		break;
	case SPEED_100:
		speed = OCELOT_SPEED_100;
		break;
	case SPEED_1000:
		speed = OCELOT_SPEED_1000;
		mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA;
		break;
	case SPEED_2500:
		speed = OCELOT_SPEED_2500;
		mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA;
		break;
	default:
387 388
		dev_err(ocelot->dev, "Unsupported PHY speed on port %d: %d\n",
			port, phydev->speed);
389 390 391
		return;
	}

392
	phy_print_status(phydev);
393

394
	if (!phydev->link)
395 396 397
		return;

	/* Only full duplex supported for now */
398
	ocelot_port_writel(ocelot_port, DEV_MAC_MODE_CFG_FDX_ENA |
399 400
			   mode, DEV_MAC_MODE_CFG);

401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
	/* Disable HDX fast control */
	ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS,
			   DEV_PORT_MISC);

	/* SGMII only for now */
	ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA,
			   PCS1G_MODE_CFG);
	ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG);

	/* Enable PCS */
	ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG);

	/* No aneg on SGMII */
	ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG);

	/* No loopback */
	ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG);
418 419

	/* Enable MAC module */
420
	ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA |
421 422 423 424
			   DEV_MAC_ENA_CFG_TX_ENA, DEV_MAC_ENA_CFG);

	/* Take MAC, Port, Phy (intern) and PCS (SGMII/Serdes) clock out of
	 * reset */
425
	ocelot_port_writel(ocelot_port, DEV_CLOCK_CFG_LINK_SPEED(speed),
426 427 428 429
			   DEV_CLOCK_CFG);

	/* No PFC */
	ocelot_write_gix(ocelot, ANA_PFC_PFC_CFG_FC_LINK_SPEED(speed),
430
			 ANA_PFC_PFC_CFG, port);
431 432

	/* Core: Enable port for frame transfer */
433 434
	ocelot_fields_write(ocelot, port,
			    QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
435 436 437 438 439 440 441

	/* Flow control */
	ocelot_write_rix(ocelot, SYS_MAC_FC_CFG_PAUSE_VAL_CFG(0xffff) |
			 SYS_MAC_FC_CFG_RX_FC_ENA | SYS_MAC_FC_CFG_TX_FC_ENA |
			 SYS_MAC_FC_CFG_ZERO_PAUSE_ENA |
			 SYS_MAC_FC_CFG_FC_LATENCY_CFG(0x7) |
			 SYS_MAC_FC_CFG_FC_LINK_SPEED(speed),
442 443
			 SYS_MAC_FC_CFG, port);
	ocelot_write_rix(ocelot, 0, ANA_POL_FLOWC, port);
444
}
445
EXPORT_SYMBOL(ocelot_adjust_link);
446

447 448
void ocelot_port_enable(struct ocelot *ocelot, int port,
			struct phy_device *phy)
449 450 451 452 453 454
{
	/* Enable receiving frames on the port, and activate auto-learning of
	 * MAC addresses.
	 */
	ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_LEARNAUTO |
			 ANA_PORT_PORT_CFG_RECV_ENA |
455 456
			 ANA_PORT_PORT_CFG_PORTID_VAL(port),
			 ANA_PORT_PORT_CFG, port);
457
}
458
EXPORT_SYMBOL(ocelot_port_enable);
459

460
void ocelot_port_disable(struct ocelot *ocelot, int port)
461 462 463 464
{
	struct ocelot_port *ocelot_port = ocelot->ports[port];

	ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
465
	ocelot_fields_write(ocelot, port, QSYS_SWITCH_PORT_MODE_PORT_ENA, 0);
466
}
467
EXPORT_SYMBOL(ocelot_port_disable);
468

469 470
void ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port,
				  struct sk_buff *clone)
471
{
472
	struct ocelot_port *ocelot_port = ocelot->ports[port];
473

474
	spin_lock(&ocelot_port->ts_id_lock);
475

476 477 478 479 480
	skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS;
	/* Store timestamp ID in cb[0] of sk_buff */
	clone->cb[0] = ocelot_port->ts_id;
	ocelot_port->ts_id = (ocelot_port->ts_id + 1) % 4;
	skb_queue_tail(&ocelot_port->tx_skbs, clone);
481

482
	spin_unlock(&ocelot_port->ts_id_lock);
483 484 485
}
EXPORT_SYMBOL(ocelot_port_add_txtstamp_skb);

486 487
static void ocelot_get_hwtimestamp(struct ocelot *ocelot,
				   struct timespec64 *ts)
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
{
	unsigned long flags;
	u32 val;

	spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);

	/* Read current PTP time to get seconds */
	val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);

	val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
	val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_SAVE);
	ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
	ts->tv_sec = ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);

	/* Read packet HW timestamp from FIFO */
	val = ocelot_read(ocelot, SYS_PTP_TXSTAMP);
	ts->tv_nsec = SYS_PTP_TXSTAMP_PTP_TXSTAMP(val);

	/* Sec has incremented since the ts was registered */
	if ((ts->tv_sec & 0x1) != !!(val & SYS_PTP_TXSTAMP_PTP_TXSTAMP_SEC))
		ts->tv_sec--;

	spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
}
512 513 514 515 516 517

void ocelot_get_txtstamp(struct ocelot *ocelot)
{
	int budget = OCELOT_PTP_QUEUE_SZ;

	while (budget--) {
518
		struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
519 520 521
		struct skb_shared_hwtstamps shhwtstamps;
		struct ocelot_port *port;
		struct timespec64 ts;
522
		unsigned long flags;
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
		u32 val, id, txport;

		val = ocelot_read(ocelot, SYS_PTP_STATUS);

		/* Check if a timestamp can be retrieved */
		if (!(val & SYS_PTP_STATUS_PTP_MESS_VLD))
			break;

		WARN_ON(val & SYS_PTP_STATUS_PTP_OVFL);

		/* Retrieve the ts ID and Tx port */
		id = SYS_PTP_STATUS_PTP_MESS_ID_X(val);
		txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val);

		/* Retrieve its associated skb */
		port = ocelot->ports[txport];

540
		spin_lock_irqsave(&port->tx_skbs.lock, flags);
541

542 543 544 545 546
		skb_queue_walk_safe(&port->tx_skbs, skb, skb_tmp) {
			if (skb->cb[0] != id)
				continue;
			__skb_unlink(skb, &port->tx_skbs);
			skb_match = skb;
547
			break;
548 549
		}

550 551
		spin_unlock_irqrestore(&port->tx_skbs.lock, flags);

552 553
		/* Get the h/w timestamp */
		ocelot_get_hwtimestamp(ocelot, &ts);
554

555
		if (unlikely(!skb_match))
556 557 558 559 560
			continue;

		/* Set the timestamp into the skb */
		memset(&shhwtstamps, 0, sizeof(shhwtstamps));
		shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
561
		skb_complete_tx_timestamp(skb_match, &shhwtstamps);
562 563 564

		/* Next ts */
		ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
565 566 567
	}
}
EXPORT_SYMBOL(ocelot_get_txtstamp);
568

569
int ocelot_fdb_add(struct ocelot *ocelot, int port,
570
		   const unsigned char *addr, u16 vid)
571
{
572 573 574 575
	int pgid = port;

	if (port == ocelot->npi)
		pgid = PGID_CPU;
576

577
	return ocelot_mact_learn(ocelot, pgid, addr, vid, ENTRYTYPE_LOCKED);
578
}
579
EXPORT_SYMBOL(ocelot_fdb_add);
580

581 582
int ocelot_fdb_del(struct ocelot *ocelot, int port,
		   const unsigned char *addr, u16 vid)
583
{
584 585
	return ocelot_mact_forget(ocelot, addr, vid);
}
586
EXPORT_SYMBOL(ocelot_fdb_del);
587

588 589
int ocelot_port_fdb_do_dump(const unsigned char *addr, u16 vid,
			    bool is_static, void *data)
590
{
591
	struct ocelot_dump_ctx *dump = data;
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
	u32 portid = NETLINK_CB(dump->cb->skb).portid;
	u32 seq = dump->cb->nlh->nlmsg_seq;
	struct nlmsghdr *nlh;
	struct ndmsg *ndm;

	if (dump->idx < dump->cb->args[2])
		goto skip;

	nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH,
			sizeof(*ndm), NLM_F_MULTI);
	if (!nlh)
		return -EMSGSIZE;

	ndm = nlmsg_data(nlh);
	ndm->ndm_family  = AF_BRIDGE;
	ndm->ndm_pad1    = 0;
	ndm->ndm_pad2    = 0;
	ndm->ndm_flags   = NTF_SELF;
	ndm->ndm_type    = 0;
	ndm->ndm_ifindex = dump->dev->ifindex;
612
	ndm->ndm_state   = is_static ? NUD_NOARP : NUD_REACHABLE;
613

614
	if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, addr))
615 616
		goto nla_put_failure;

617
	if (vid && nla_put_u16(dump->skb, NDA_VLAN, vid))
618 619 620 621 622 623 624 625 626 627 628 629
		goto nla_put_failure;

	nlmsg_end(dump->skb, nlh);

skip:
	dump->idx++;
	return 0;

nla_put_failure:
	nlmsg_cancel(dump->skb, nlh);
	return -EMSGSIZE;
}
630
EXPORT_SYMBOL(ocelot_port_fdb_do_dump);
631

632 633
static int ocelot_mact_read(struct ocelot *ocelot, int port, int row, int col,
			    struct ocelot_mact_entry *entry)
634 635
{
	u32 val, dst, macl, mach;
636
	char mac[ETH_ALEN];
637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658

	/* Set row and column to read from */
	ocelot_field_write(ocelot, ANA_TABLES_MACTINDX_M_INDEX, row);
	ocelot_field_write(ocelot, ANA_TABLES_MACTINDX_BUCKET, col);

	/* Issue a read command */
	ocelot_write(ocelot,
		     ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_READ),
		     ANA_TABLES_MACACCESS);

	if (ocelot_mact_wait_for_completion(ocelot))
		return -ETIMEDOUT;

	/* Read the entry flags */
	val = ocelot_read(ocelot, ANA_TABLES_MACACCESS);
	if (!(val & ANA_TABLES_MACACCESS_VALID))
		return -EINVAL;

	/* If the entry read has another port configured as its destination,
	 * do not report it.
	 */
	dst = (val & ANA_TABLES_MACACCESS_DEST_IDX_M) >> 3;
659
	if (dst != port)
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
		return -EINVAL;

	/* Get the entry's MAC address and VLAN id */
	macl = ocelot_read(ocelot, ANA_TABLES_MACLDATA);
	mach = ocelot_read(ocelot, ANA_TABLES_MACHDATA);

	mac[0] = (mach >> 8)  & 0xff;
	mac[1] = (mach >> 0)  & 0xff;
	mac[2] = (macl >> 24) & 0xff;
	mac[3] = (macl >> 16) & 0xff;
	mac[4] = (macl >> 8)  & 0xff;
	mac[5] = (macl >> 0)  & 0xff;

	entry->vid = (mach >> 16) & 0xfff;
	ether_addr_copy(entry->mac, mac);

	return 0;
}

679 680
int ocelot_fdb_dump(struct ocelot *ocelot, int port,
		    dsa_fdb_dump_cb_t *cb, void *data)
681
{
682
	int i, j;
683

684 685
	/* Loop through all the mac tables entries. */
	for (i = 0; i < ocelot->num_mact_rows; i++) {
686
		for (j = 0; j < 4; j++) {
687 688 689 690 691
			struct ocelot_mact_entry entry;
			bool is_static;
			int ret;

			ret = ocelot_mact_read(ocelot, port, i, j, &entry);
692 693 694 695 696 697
			/* If the entry is invalid (wrong port, invalid...),
			 * skip it.
			 */
			if (ret == -EINVAL)
				continue;
			else if (ret)
698 699 700
				return ret;

			is_static = (entry.type == ENTRYTYPE_LOCKED);
701

702
			ret = cb(entry.mac, entry.vid, is_static, data);
703
			if (ret)
704
				return ret;
705 706 707
		}
	}

708 709
	return 0;
}
710
EXPORT_SYMBOL(ocelot_fdb_dump);
711

712
int ocelot_hwstamp_get(struct ocelot *ocelot, int port, struct ifreq *ifr)
713 714 715 716
{
	return copy_to_user(ifr->ifr_data, &ocelot->hwtstamp_config,
			    sizeof(ocelot->hwtstamp_config)) ? -EFAULT : 0;
}
717
EXPORT_SYMBOL(ocelot_hwstamp_get);
718

719
int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
720
{
721
	struct ocelot_port *ocelot_port = ocelot->ports[port];
722 723 724 725 726 727 728 729 730 731 732 733
	struct hwtstamp_config cfg;

	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
		return -EFAULT;

	/* reserved for future extensions */
	if (cfg.flags)
		return -EINVAL;

	/* Tx type sanity check */
	switch (cfg.tx_type) {
	case HWTSTAMP_TX_ON:
734
		ocelot_port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
735 736 737 738 739
		break;
	case HWTSTAMP_TX_ONESTEP_SYNC:
		/* IFH_REW_OP_ONE_STEP_PTP updates the correctional field, we
		 * need to update the origin time.
		 */
740
		ocelot_port->ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
741 742
		break;
	case HWTSTAMP_TX_OFF:
743
		ocelot_port->ptp_cmd = 0;
744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781
		break;
	default:
		return -ERANGE;
	}

	mutex_lock(&ocelot->ptp_lock);

	switch (cfg.rx_filter) {
	case HWTSTAMP_FILTER_NONE:
		break;
	case HWTSTAMP_FILTER_ALL:
	case HWTSTAMP_FILTER_SOME:
	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
	case HWTSTAMP_FILTER_NTP_ALL:
	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
	case HWTSTAMP_FILTER_PTP_V2_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
		cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
		break;
	default:
		mutex_unlock(&ocelot->ptp_lock);
		return -ERANGE;
	}

	/* Commit back the result & save it */
	memcpy(&ocelot->hwtstamp_config, &cfg, sizeof(cfg));
	mutex_unlock(&ocelot->ptp_lock);

	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
}
782
EXPORT_SYMBOL(ocelot_hwstamp_set);
783

784
void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data)
785 786 787 788 789 790 791 792 793 794
{
	int i;

	if (sset != ETH_SS_STATS)
		return;

	for (i = 0; i < ocelot->num_stats; i++)
		memcpy(data + i * ETH_GSTRING_LEN, ocelot->stats_layout[i].name,
		       ETH_GSTRING_LEN);
}
795
EXPORT_SYMBOL(ocelot_get_strings);
796

797
static void ocelot_update_stats(struct ocelot *ocelot)
798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821
{
	int i, j;

	mutex_lock(&ocelot->stats_lock);

	for (i = 0; i < ocelot->num_phys_ports; i++) {
		/* Configure the port to read the stats from */
		ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(i), SYS_STAT_CFG);

		for (j = 0; j < ocelot->num_stats; j++) {
			u32 val;
			unsigned int idx = i * ocelot->num_stats + j;

			val = ocelot_read_rix(ocelot, SYS_COUNT_RX_OCTETS,
					      ocelot->stats_layout[j].offset);

			if (val < (ocelot->stats[idx] & U32_MAX))
				ocelot->stats[idx] += (u64)1 << 32;

			ocelot->stats[idx] = (ocelot->stats[idx] &
					      ~(u64)U32_MAX) + val;
		}
	}

822 823 824 825 826 827 828 829 830 831 832
	mutex_unlock(&ocelot->stats_lock);
}

static void ocelot_check_stats_work(struct work_struct *work)
{
	struct delayed_work *del_work = to_delayed_work(work);
	struct ocelot *ocelot = container_of(del_work, struct ocelot,
					     stats_work);

	ocelot_update_stats(ocelot);

833 834 835 836
	queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work,
			   OCELOT_STATS_CHECK_DELAY);
}

837
void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data)
838 839 840 841
{
	int i;

	/* check and update now */
842
	ocelot_update_stats(ocelot);
843 844 845

	/* Copy all counters */
	for (i = 0; i < ocelot->num_stats; i++)
846
		*data++ = ocelot->stats[port * ocelot->num_stats + i];
847
}
848
EXPORT_SYMBOL(ocelot_get_ethtool_stats);
849

850
int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset)
851
{
852 853
	if (sset != ETH_SS_STATS)
		return -EOPNOTSUPP;
854

855 856
	return ocelot->num_stats;
}
857
EXPORT_SYMBOL(ocelot_get_sset_count);
858

859 860
int ocelot_get_ts_info(struct ocelot *ocelot, int port,
		       struct ethtool_ts_info *info)
861
{
862 863
	info->phc_index = ocelot->ptp_clock ?
			  ptp_clock_index(ocelot->ptp_clock) : -1;
864 865 866 867 868 869
	if (info->phc_index == -1) {
		info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
					 SOF_TIMESTAMPING_RX_SOFTWARE |
					 SOF_TIMESTAMPING_SOFTWARE;
		return 0;
	}
870 871 872 873 874 875 876 877 878 879 880 881
	info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
				 SOF_TIMESTAMPING_RX_SOFTWARE |
				 SOF_TIMESTAMPING_SOFTWARE |
				 SOF_TIMESTAMPING_TX_HARDWARE |
				 SOF_TIMESTAMPING_RX_HARDWARE |
				 SOF_TIMESTAMPING_RAW_HARDWARE;
	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |
			 BIT(HWTSTAMP_TX_ONESTEP_SYNC);
	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);

	return 0;
}
882
EXPORT_SYMBOL(ocelot_get_ts_info);
883

884
void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state)
885 886
{
	u32 port_cfg;
887
	int p, i;
888

889 890
	if (!(BIT(port) & ocelot->bridge_mask))
		return;
891

892
	port_cfg = ocelot_read_gix(ocelot, ANA_PORT_PORT_CFG, port);
893 894 895

	switch (state) {
	case BR_STATE_FORWARDING:
896
		ocelot->bridge_fwd_mask |= BIT(port);
897
		fallthrough;
898 899 900 901 902 903
	case BR_STATE_LEARNING:
		port_cfg |= ANA_PORT_PORT_CFG_LEARN_ENA;
		break;

	default:
		port_cfg &= ~ANA_PORT_PORT_CFG_LEARN_ENA;
904
		ocelot->bridge_fwd_mask &= ~BIT(port);
905 906 907
		break;
	}

908
	ocelot_write_gix(ocelot, port_cfg, ANA_PORT_PORT_CFG, port);
909 910 911 912

	/* Apply FWD mask. The loop is needed to add/remove the current port as
	 * a source for the other ports.
	 */
913
	for (p = 0; p < ocelot->num_phys_ports; p++) {
914
		if (ocelot->bridge_fwd_mask & BIT(p)) {
915
			unsigned long mask = ocelot->bridge_fwd_mask & ~BIT(p);
916 917 918 919 920 921 922

			for (i = 0; i < ocelot->num_phys_ports; i++) {
				unsigned long bond_mask = ocelot->lags[i];

				if (!bond_mask)
					continue;

923
				if (bond_mask & BIT(p)) {
924 925 926 927 928
					mask &= ~bond_mask;
					break;
				}
			}

929
			ocelot_write_rix(ocelot, mask,
930
					 ANA_PGID_PGID, PGID_SRC + p);
931
		} else {
932
			ocelot_write_rix(ocelot, 0,
933
					 ANA_PGID_PGID, PGID_SRC + p);
934 935
		}
	}
936
}
937
EXPORT_SYMBOL(ocelot_bridge_stp_state_set);
938

939
void ocelot_set_ageing_time(struct ocelot *ocelot, unsigned int msecs)
940
{
941 942 943 944 945 946 947 948 949
	unsigned int age_period = ANA_AUTOAGE_AGE_PERIOD(msecs / 2000);

	/* Setting AGE_PERIOD to zero effectively disables automatic aging,
	 * which is clearly not what our intention is. So avoid that.
	 */
	if (!age_period)
		age_period = 1;

	ocelot_rmw(ocelot, age_period, ANA_AUTOAGE_AGE_PERIOD_M, ANA_AUTOAGE);
950
}
951
EXPORT_SYMBOL(ocelot_set_ageing_time);
952 953 954 955 956 957 958 959 960 961 962 963 964 965 966

static struct ocelot_multicast *ocelot_multicast_get(struct ocelot *ocelot,
						     const unsigned char *addr,
						     u16 vid)
{
	struct ocelot_multicast *mc;

	list_for_each_entry(mc, &ocelot->multicast, list) {
		if (ether_addr_equal(mc->addr, addr) && mc->vid == vid)
			return mc;
	}

	return NULL;
}

967 968 969 970 971 972
static enum macaccess_entry_type ocelot_classify_mdb(const unsigned char *addr)
{
	if (addr[0] == 0x01 && addr[1] == 0x00 && addr[2] == 0x5e)
		return ENTRYTYPE_MACv4;
	if (addr[0] == 0x33 && addr[1] == 0x33)
		return ENTRYTYPE_MACv6;
973
	return ENTRYTYPE_LOCKED;
974 975
}

976 977
static struct ocelot_pgid *ocelot_pgid_alloc(struct ocelot *ocelot, int index,
					     unsigned long ports)
978
{
979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006
	struct ocelot_pgid *pgid;

	pgid = kzalloc(sizeof(*pgid), GFP_KERNEL);
	if (!pgid)
		return ERR_PTR(-ENOMEM);

	pgid->ports = ports;
	pgid->index = index;
	refcount_set(&pgid->refcount, 1);
	list_add_tail(&pgid->list, &ocelot->pgids);

	return pgid;
}

static void ocelot_pgid_free(struct ocelot *ocelot, struct ocelot_pgid *pgid)
{
	if (!refcount_dec_and_test(&pgid->refcount))
		return;

	list_del(&pgid->list);
	kfree(pgid);
}

static struct ocelot_pgid *ocelot_mdb_get_pgid(struct ocelot *ocelot,
					       const struct ocelot_multicast *mc)
{
	struct ocelot_pgid *pgid;
	int index;
1007 1008 1009 1010 1011 1012

	/* According to VSC7514 datasheet 3.9.1.5 IPv4 Multicast Entries and
	 * 3.9.1.6 IPv6 Multicast Entries, "Instead of a lookup in the
	 * destination mask table (PGID), the destination set is programmed as
	 * part of the entry MAC address.", and the DEST_IDX is set to 0.
	 */
1013 1014
	if (mc->entry_type == ENTRYTYPE_MACv4 ||
	    mc->entry_type == ENTRYTYPE_MACv6)
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
		return ocelot_pgid_alloc(ocelot, 0, mc->ports);

	list_for_each_entry(pgid, &ocelot->pgids, list) {
		/* When searching for a nonreserved multicast PGID, ignore the
		 * dummy PGID of zero that we have for MACv4/MACv6 entries
		 */
		if (pgid->index && pgid->ports == mc->ports) {
			refcount_inc(&pgid->refcount);
			return pgid;
		}
	}
1026

1027 1028
	/* Search for a free index in the nonreserved multicast PGID area */
	for_each_nonreserved_multicast_dest_pgid(ocelot, index) {
1029 1030
		bool used = false;

1031 1032
		list_for_each_entry(pgid, &ocelot->pgids, list) {
			if (pgid->index == index) {
1033 1034 1035 1036 1037 1038
				used = true;
				break;
			}
		}

		if (!used)
1039
			return ocelot_pgid_alloc(ocelot, index, mc->ports);
1040 1041
	}

1042
	return ERR_PTR(-ENOSPC);
1043 1044 1045
}

static void ocelot_encode_ports_to_mdb(unsigned char *addr,
1046
				       struct ocelot_multicast *mc)
1047
{
1048
	ether_addr_copy(addr, mc->addr);
1049

1050
	if (mc->entry_type == ENTRYTYPE_MACv4) {
1051 1052 1053
		addr[0] = 0;
		addr[1] = mc->ports >> 8;
		addr[2] = mc->ports & 0xff;
1054
	} else if (mc->entry_type == ENTRYTYPE_MACv6) {
1055 1056 1057 1058 1059
		addr[0] = mc->ports >> 8;
		addr[1] = mc->ports & 0xff;
	}
}

1060 1061
int ocelot_port_mdb_add(struct ocelot *ocelot, int port,
			const struct switchdev_obj_port_mdb *mdb)
1062 1063
{
	unsigned char addr[ETH_ALEN];
1064
	struct ocelot_multicast *mc;
1065
	struct ocelot_pgid *pgid;
1066 1067
	u16 vid = mdb->vid;

1068 1069 1070
	if (port == ocelot->npi)
		port = ocelot->num_phys_ports;

1071 1072
	mc = ocelot_multicast_get(ocelot, mdb->addr, vid);
	if (!mc) {
1073
		/* New entry */
1074 1075 1076 1077 1078 1079 1080 1081
		mc = devm_kzalloc(ocelot->dev, sizeof(*mc), GFP_KERNEL);
		if (!mc)
			return -ENOMEM;

		mc->entry_type = ocelot_classify_mdb(mdb->addr);
		ether_addr_copy(mc->addr, mdb->addr);
		mc->vid = vid;

1082
		list_add_tail(&mc->list, &ocelot->multicast);
1083
	} else {
1084 1085 1086 1087
		/* Existing entry. Clean up the current port mask from
		 * hardware now, because we'll be modifying it.
		 */
		ocelot_pgid_free(ocelot, mc->pgid);
1088
		ocelot_encode_ports_to_mdb(addr, mc);
1089 1090 1091
		ocelot_mact_forget(ocelot, addr, vid);
	}

1092
	mc->ports |= BIT(port);
1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103

	pgid = ocelot_mdb_get_pgid(ocelot, mc);
	if (IS_ERR(pgid)) {
		dev_err(ocelot->dev,
			"Cannot allocate PGID for mdb %pM vid %d\n",
			mc->addr, mc->vid);
		devm_kfree(ocelot->dev, mc);
		return PTR_ERR(pgid);
	}
	mc->pgid = pgid;

1104
	ocelot_encode_ports_to_mdb(addr, mc);
1105

1106 1107 1108 1109 1110 1111
	if (mc->entry_type != ENTRYTYPE_MACv4 &&
	    mc->entry_type != ENTRYTYPE_MACv6)
		ocelot_write_rix(ocelot, pgid->ports, ANA_PGID_PGID,
				 pgid->index);

	return ocelot_mact_learn(ocelot, pgid->index, addr, vid,
1112
				 mc->entry_type);
1113
}
1114
EXPORT_SYMBOL(ocelot_port_mdb_add);
1115

1116 1117
int ocelot_port_mdb_del(struct ocelot *ocelot, int port,
			const struct switchdev_obj_port_mdb *mdb)
1118 1119
{
	unsigned char addr[ETH_ALEN];
1120
	struct ocelot_multicast *mc;
1121
	struct ocelot_pgid *pgid;
1122 1123
	u16 vid = mdb->vid;

1124 1125 1126
	if (port == ocelot->npi)
		port = ocelot->num_phys_ports;

1127 1128 1129 1130
	mc = ocelot_multicast_get(ocelot, mdb->addr, vid);
	if (!mc)
		return -ENOENT;

1131
	ocelot_encode_ports_to_mdb(addr, mc);
1132 1133
	ocelot_mact_forget(ocelot, addr, vid);

1134
	ocelot_pgid_free(ocelot, mc->pgid);
1135
	mc->ports &= ~BIT(port);
1136 1137 1138 1139 1140 1141
	if (!mc->ports) {
		list_del(&mc->list);
		devm_kfree(ocelot->dev, mc);
		return 0;
	}

1142 1143 1144 1145 1146 1147
	/* We have a PGID with fewer ports now */
	pgid = ocelot_mdb_get_pgid(ocelot, mc);
	if (IS_ERR(pgid))
		return PTR_ERR(pgid);
	mc->pgid = pgid;

1148
	ocelot_encode_ports_to_mdb(addr, mc);
1149

1150 1151 1152 1153 1154 1155
	if (mc->entry_type != ENTRYTYPE_MACv4 &&
	    mc->entry_type != ENTRYTYPE_MACv6)
		ocelot_write_rix(ocelot, pgid->ports, ANA_PGID_PGID,
				 pgid->index);

	return ocelot_mact_learn(ocelot, pgid->index, addr, vid,
1156
				 mc->entry_type);
1157
}
1158
EXPORT_SYMBOL(ocelot_port_mdb_del);
1159

1160 1161
int ocelot_port_bridge_join(struct ocelot *ocelot, int port,
			    struct net_device *bridge)
1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
{
	if (!ocelot->bridge_mask) {
		ocelot->hw_bridge_dev = bridge;
	} else {
		if (ocelot->hw_bridge_dev != bridge)
			/* This is adding the port to a second bridge, this is
			 * unsupported */
			return -ENODEV;
	}

1172
	ocelot->bridge_mask |= BIT(port);
1173 1174 1175

	return 0;
}
1176
EXPORT_SYMBOL(ocelot_port_bridge_join);
1177

1178 1179
int ocelot_port_bridge_leave(struct ocelot *ocelot, int port,
			     struct net_device *bridge)
1180
{
1181
	struct ocelot_vlan pvid = {0}, native_vlan = {0};
1182 1183 1184
	struct switchdev_trans trans;
	int ret;

1185
	ocelot->bridge_mask &= ~BIT(port);
1186 1187 1188

	if (!ocelot->bridge_mask)
		ocelot->hw_bridge_dev = NULL;
1189

1190 1191 1192 1193 1194 1195 1196 1197 1198 1199
	trans.ph_prepare = true;
	ret = ocelot_port_vlan_filtering(ocelot, port, false, &trans);
	if (ret)
		return ret;

	trans.ph_prepare = false;
	ret = ocelot_port_vlan_filtering(ocelot, port, false, &trans);
	if (ret)
		return ret;

1200
	ocelot_port_set_pvid(ocelot, port, pvid);
1201 1202 1203
	ocelot_port_set_native_vlan(ocelot, port, native_vlan);

	return 0;
1204
}
1205
EXPORT_SYMBOL(ocelot_port_bridge_leave);
1206

1207 1208 1209 1210 1211
static void ocelot_set_aggr_pgids(struct ocelot *ocelot)
{
	int i, port, lag;

	/* Reset destination and aggregation PGIDS */
1212
	for_each_unicast_dest_pgid(ocelot, port)
1213 1214
		ocelot_write_rix(ocelot, BIT(port), ANA_PGID_PGID, port);

1215
	for_each_aggr_pgid(ocelot, i)
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236
		ocelot_write_rix(ocelot, GENMASK(ocelot->num_phys_ports - 1, 0),
				 ANA_PGID_PGID, i);

	/* Now, set PGIDs for each LAG */
	for (lag = 0; lag < ocelot->num_phys_ports; lag++) {
		unsigned long bond_mask;
		int aggr_count = 0;
		u8 aggr_idx[16];

		bond_mask = ocelot->lags[lag];
		if (!bond_mask)
			continue;

		for_each_set_bit(port, &bond_mask, ocelot->num_phys_ports) {
			// Destination mask
			ocelot_write_rix(ocelot, bond_mask,
					 ANA_PGID_PGID, port);
			aggr_idx[aggr_count] = port;
			aggr_count++;
		}

1237
		for_each_aggr_pgid(ocelot, i) {
1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264
			u32 ac;

			ac = ocelot_read_rix(ocelot, ANA_PGID_PGID, i);
			ac &= ~bond_mask;
			ac |= BIT(aggr_idx[i % aggr_count]);
			ocelot_write_rix(ocelot, ac, ANA_PGID_PGID, i);
		}
	}
}

static void ocelot_setup_lag(struct ocelot *ocelot, int lag)
{
	unsigned long bond_mask = ocelot->lags[lag];
	unsigned int p;

	for_each_set_bit(p, &bond_mask, ocelot->num_phys_ports) {
		u32 port_cfg = ocelot_read_gix(ocelot, ANA_PORT_PORT_CFG, p);

		port_cfg &= ~ANA_PORT_PORT_CFG_PORTID_VAL_M;

		/* Use lag port as logical port for port i */
		ocelot_write_gix(ocelot, port_cfg |
				 ANA_PORT_PORT_CFG_PORTID_VAL(lag),
				 ANA_PORT_PORT_CFG, p);
	}
}

1265 1266
int ocelot_port_lag_join(struct ocelot *ocelot, int port,
			 struct net_device *bond)
1267 1268 1269
{
	struct net_device *ndev;
	u32 bond_mask = 0;
1270
	int lag, lp;
1271 1272 1273

	rcu_read_lock();
	for_each_netdev_in_bond_rcu(bond, ndev) {
1274
		struct ocelot_port_private *priv = netdev_priv(ndev);
1275

1276
		bond_mask |= BIT(priv->chip_port);
1277 1278 1279 1280 1281 1282 1283 1284
	}
	rcu_read_unlock();

	lp = __ffs(bond_mask);

	/* If the new port is the lowest one, use it as the logical port from
	 * now on
	 */
1285 1286 1287 1288
	if (port == lp) {
		lag = port;
		ocelot->lags[port] = bond_mask;
		bond_mask &= ~BIT(port);
1289 1290 1291 1292 1293 1294
		if (bond_mask) {
			lp = __ffs(bond_mask);
			ocelot->lags[lp] = 0;
		}
	} else {
		lag = lp;
1295
		ocelot->lags[lp] |= BIT(port);
1296 1297 1298 1299 1300 1301 1302
	}

	ocelot_setup_lag(ocelot, lag);
	ocelot_set_aggr_pgids(ocelot);

	return 0;
}
1303
EXPORT_SYMBOL(ocelot_port_lag_join);
1304

1305 1306
void ocelot_port_lag_leave(struct ocelot *ocelot, int port,
			   struct net_device *bond)
1307 1308 1309 1310 1311 1312
{
	u32 port_cfg;
	int i;

	/* Remove port from any lag */
	for (i = 0; i < ocelot->num_phys_ports; i++)
1313
		ocelot->lags[i] &= ~BIT(port);
1314 1315 1316 1317

	/* if it was the logical port of the lag, move the lag config to the
	 * next port
	 */
1318 1319
	if (ocelot->lags[port]) {
		int n = __ffs(ocelot->lags[port]);
1320

1321 1322
		ocelot->lags[n] = ocelot->lags[port];
		ocelot->lags[port] = 0;
1323 1324 1325 1326

		ocelot_setup_lag(ocelot, n);
	}

1327
	port_cfg = ocelot_read_gix(ocelot, ANA_PORT_PORT_CFG, port);
1328
	port_cfg &= ~ANA_PORT_PORT_CFG_PORTID_VAL_M;
1329 1330
	ocelot_write_gix(ocelot, port_cfg | ANA_PORT_PORT_CFG_PORTID_VAL(port),
			 ANA_PORT_PORT_CFG, port);
1331 1332 1333

	ocelot_set_aggr_pgids(ocelot);
}
1334
EXPORT_SYMBOL(ocelot_port_lag_leave);
1335

1336 1337
/* Configure the maximum SDU (L2 payload) on RX to the value specified in @sdu.
 * The length of VLAN tags is accounted for automatically via DEV_MAC_TAGS_CFG.
1338 1339 1340
 * In the special case that it's the NPI port that we're configuring, the
 * length of the tag and optional prefix needs to be accounted for privately,
 * in order to be able to sustain communication at the requested @sdu.
1341
 */
1342
void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)
1343 1344
{
	struct ocelot_port *ocelot_port = ocelot->ports[port];
1345
	int maxlen = sdu + ETH_HLEN + ETH_FCS_LEN;
1346
	int pause_start, pause_stop;
1347
	int atop, atop_tot;
1348

1349 1350 1351 1352 1353 1354 1355 1356 1357
	if (port == ocelot->npi) {
		maxlen += OCELOT_TAG_LEN;

		if (ocelot->inj_prefix == OCELOT_TAG_PREFIX_SHORT)
			maxlen += OCELOT_SHORT_PREFIX_LEN;
		else if (ocelot->inj_prefix == OCELOT_TAG_PREFIX_LONG)
			maxlen += OCELOT_LONG_PREFIX_LEN;
	}

1358
	ocelot_port_writel(ocelot_port, maxlen, DEV_MAC_MAXLEN_CFG);
1359

1360 1361 1362
	/* Set Pause watermark hysteresis */
	pause_start = 6 * maxlen / OCELOT_BUFFER_CELL_SZ;
	pause_stop = 4 * maxlen / OCELOT_BUFFER_CELL_SZ;
1363 1364 1365 1366
	ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_START,
			    pause_start);
	ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_STOP,
			    pause_stop);
1367

1368 1369
	/* Tail dropping watermarks */
	atop_tot = (ocelot->shared_queue_sz - 9 * maxlen) /
1370
		   OCELOT_BUFFER_CELL_SZ;
1371 1372 1373
	atop = (9 * maxlen) / OCELOT_BUFFER_CELL_SZ;
	ocelot_write_rix(ocelot, ocelot->ops->wm_enc(atop), SYS_ATOP, port);
	ocelot_write(ocelot, ocelot->ops->wm_enc(atop_tot), SYS_ATOP_TOT_CFG);
1374
}
1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392
EXPORT_SYMBOL(ocelot_port_set_maxlen);

int ocelot_get_max_mtu(struct ocelot *ocelot, int port)
{
	int max_mtu = 65535 - ETH_HLEN - ETH_FCS_LEN;

	if (port == ocelot->npi) {
		max_mtu -= OCELOT_TAG_LEN;

		if (ocelot->inj_prefix == OCELOT_TAG_PREFIX_SHORT)
			max_mtu -= OCELOT_SHORT_PREFIX_LEN;
		else if (ocelot->inj_prefix == OCELOT_TAG_PREFIX_LONG)
			max_mtu -= OCELOT_LONG_PREFIX_LEN;
	}

	return max_mtu;
}
EXPORT_SYMBOL(ocelot_get_max_mtu);
1393

1394
void ocelot_init_port(struct ocelot *ocelot, int port)
1395 1396 1397
{
	struct ocelot_port *ocelot_port = ocelot->ports[port];

1398
	skb_queue_head_init(&ocelot_port->tx_skbs);
1399
	spin_lock_init(&ocelot_port->ts_id_lock);
1400 1401 1402

	/* Basic L2 initialization */

1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418
	/* Set MAC IFG Gaps
	 * FDX: TX_IFG = 5, RX_IFG1 = RX_IFG2 = 0
	 * !FDX: TX_IFG = 5, RX_IFG1 = RX_IFG2 = 5
	 */
	ocelot_port_writel(ocelot_port, DEV_MAC_IFG_CFG_TX_IFG(5),
			   DEV_MAC_IFG_CFG);

	/* Load seed (0) and set MAC HDX late collision  */
	ocelot_port_writel(ocelot_port, DEV_MAC_HDX_CFG_LATE_COL_POS(67) |
			   DEV_MAC_HDX_CFG_SEED_LOAD,
			   DEV_MAC_HDX_CFG);
	mdelay(1);
	ocelot_port_writel(ocelot_port, DEV_MAC_HDX_CFG_LATE_COL_POS(67),
			   DEV_MAC_HDX_CFG);

	/* Set Max Length and maximum tags allowed */
1419
	ocelot_port_set_maxlen(ocelot, port, ETH_DATA_LEN);
1420 1421
	ocelot_port_writel(ocelot_port, DEV_MAC_TAGS_CFG_TAG_ID(ETH_P_8021AD) |
			   DEV_MAC_TAGS_CFG_VLAN_AWR_ENA |
1422
			   DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA |
1423 1424 1425 1426 1427 1428 1429
			   DEV_MAC_TAGS_CFG_VLAN_LEN_AWR_ENA,
			   DEV_MAC_TAGS_CFG);

	/* Set SMAC of Pause frame (00:00:00:00:00:00) */
	ocelot_port_writel(ocelot_port, 0, DEV_MAC_FC_MAC_HIGH_CFG);
	ocelot_port_writel(ocelot_port, 0, DEV_MAC_FC_MAC_LOW_CFG);

1430
	/* Enable transmission of pause frames */
1431
	ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, 1);
1432

1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445
	/* Drop frames with multicast source address */
	ocelot_rmw_gix(ocelot, ANA_PORT_DROP_CFG_DROP_MC_SMAC_ENA,
		       ANA_PORT_DROP_CFG_DROP_MC_SMAC_ENA,
		       ANA_PORT_DROP_CFG, port);

	/* Set default VLAN and tag type to 8021Q. */
	ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_TPID(ETH_P_8021Q),
		       REW_PORT_VLAN_CFG_PORT_TPID_M,
		       REW_PORT_VLAN_CFG, port);

	/* Enable vcap lookups */
	ocelot_vcap_enable(ocelot, port);
}
1446
EXPORT_SYMBOL(ocelot_init_port);
1447

1448 1449 1450
/* Configure and enable the CPU port module, which is a set of queues
 * accessible through register MMIO, frame DMA or Ethernet (in case
 * NPI mode is used).
1451
 */
1452
static void ocelot_cpu_port_init(struct ocelot *ocelot)
1453
{
1454 1455 1456
	int cpu = ocelot->num_phys_ports;

	/* The unicast destination PGID for the CPU port module is unused */
1457
	ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu);
1458 1459 1460 1461
	/* Instead set up a multicast destination PGID for traffic copied to
	 * the CPU. Whitelisted MAC addresses like the port netdevice MAC
	 * addresses will be copied to the CPU via this PGID.
	 */
1462 1463 1464 1465 1466
	ocelot_write_rix(ocelot, BIT(cpu), ANA_PGID_PGID, PGID_CPU);
	ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_RECV_ENA |
			 ANA_PORT_PORT_CFG_PORTID_VAL(cpu),
			 ANA_PORT_PORT_CFG, cpu);

1467
	/* Enable CPU port module */
1468
	ocelot_fields_write(ocelot, cpu, QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
1469
	/* CPU port Injection/Extraction configuration */
1470
	ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_XTR_HDR,
1471
			    ocelot->xtr_prefix);
1472
	ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_INJ_HDR,
1473
			    ocelot->inj_prefix);
1474 1475 1476 1477 1478 1479 1480 1481

	/* Configure the CPU port to be VLAN aware */
	ocelot_write_gix(ocelot, ANA_PORT_VLAN_CFG_VLAN_VID(0) |
				 ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
				 ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1),
			 ANA_PORT_VLAN_CFG, cpu);
}

1482 1483 1484
int ocelot_init(struct ocelot *ocelot)
{
	char queue_name[32];
1485 1486
	int i, ret;
	u32 port;
1487

1488 1489 1490 1491 1492 1493 1494 1495
	if (ocelot->ops->reset) {
		ret = ocelot->ops->reset(ocelot);
		if (ret) {
			dev_err(ocelot->dev, "Switch reset failed\n");
			return ret;
		}
	}

1496 1497 1498 1499 1500
	ocelot->lags = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports,
				    sizeof(u32), GFP_KERNEL);
	if (!ocelot->lags)
		return -ENOMEM;

1501 1502 1503 1504 1505 1506 1507
	ocelot->stats = devm_kcalloc(ocelot->dev,
				     ocelot->num_phys_ports * ocelot->num_stats,
				     sizeof(u64), GFP_KERNEL);
	if (!ocelot->stats)
		return -ENOMEM;

	mutex_init(&ocelot->stats_lock);
1508 1509
	mutex_init(&ocelot->ptp_lock);
	spin_lock_init(&ocelot->ptp_clock_lock);
1510 1511 1512 1513 1514 1515
	snprintf(queue_name, sizeof(queue_name), "%s-stats",
		 dev_name(ocelot->dev));
	ocelot->stats_queue = create_singlethread_workqueue(queue_name);
	if (!ocelot->stats_queue)
		return -ENOMEM;

1516 1517 1518 1519 1520 1521
	ocelot->owq = alloc_ordered_workqueue("ocelot-owq", 0);
	if (!ocelot->owq) {
		destroy_workqueue(ocelot->stats_queue);
		return -ENOMEM;
	}

1522
	INIT_LIST_HEAD(&ocelot->multicast);
1523
	INIT_LIST_HEAD(&ocelot->pgids);
1524 1525
	ocelot_mact_init(ocelot);
	ocelot_vlan_init(ocelot);
1526
	ocelot_vcap_init(ocelot);
1527
	ocelot_cpu_port_init(ocelot);
1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559

	for (port = 0; port < ocelot->num_phys_ports; port++) {
		/* Clear all counters (5 groups) */
		ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port) |
				     SYS_STAT_CFG_STAT_CLEAR_SHOT(0x7f),
			     SYS_STAT_CFG);
	}

	/* Only use S-Tag */
	ocelot_write(ocelot, ETH_P_8021AD, SYS_VLAN_ETYPE_CFG);

	/* Aggregation mode */
	ocelot_write(ocelot, ANA_AGGR_CFG_AC_SMAC_ENA |
			     ANA_AGGR_CFG_AC_DMAC_ENA |
			     ANA_AGGR_CFG_AC_IP4_SIPDIP_ENA |
			     ANA_AGGR_CFG_AC_IP4_TCPUDP_ENA, ANA_AGGR_CFG);

	/* Set MAC age time to default value. The entry is aged after
	 * 2*AGE_PERIOD
	 */
	ocelot_write(ocelot,
		     ANA_AUTOAGE_AGE_PERIOD(BR_DEFAULT_AGEING_TIME / 2 / HZ),
		     ANA_AUTOAGE);

	/* Disable learning for frames discarded by VLAN ingress filtering */
	regmap_field_write(ocelot->regfields[ANA_ADVLEARN_VLAN_CHK], 1);

	/* Setup frame ageing - fixed value "2 sec" - in 6.5 us units */
	ocelot_write(ocelot, SYS_FRM_AGING_AGE_TX_ENA |
		     SYS_FRM_AGING_MAX_AGE(307692), SYS_FRM_AGING);

	/* Setup flooding PGIDs */
1560 1561 1562 1563 1564
	for (i = 0; i < ocelot->num_flooding_pgids; i++)
		ocelot_write_rix(ocelot, ANA_FLOODING_FLD_MULTICAST(PGID_MC) |
				 ANA_FLOODING_FLD_BROADCAST(PGID_MC) |
				 ANA_FLOODING_FLD_UNICAST(PGID_UC),
				 ANA_FLOODING, i);
1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583
	ocelot_write(ocelot, ANA_FLOODING_IPMC_FLD_MC6_DATA(PGID_MCIPV6) |
		     ANA_FLOODING_IPMC_FLD_MC6_CTRL(PGID_MC) |
		     ANA_FLOODING_IPMC_FLD_MC4_DATA(PGID_MCIPV4) |
		     ANA_FLOODING_IPMC_FLD_MC4_CTRL(PGID_MC),
		     ANA_FLOODING_IPMC);

	for (port = 0; port < ocelot->num_phys_ports; port++) {
		/* Transmit the frame to the local port. */
		ocelot_write_rix(ocelot, BIT(port), ANA_PGID_PGID, port);
		/* Do not forward BPDU frames to the front ports. */
		ocelot_write_gix(ocelot,
				 ANA_PORT_CPU_FWD_BPDU_CFG_BPDU_REDIR_ENA(0xffff),
				 ANA_PORT_CPU_FWD_BPDU_CFG,
				 port);
		/* Ensure bridging is disabled */
		ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_SRC + port);
	}

	/* Allow broadcast MAC frames. */
1584
	for_each_nonreserved_multicast_dest_pgid(ocelot, i) {
1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615
		u32 val = ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports - 1, 0));

		ocelot_write_rix(ocelot, val, ANA_PGID_PGID, i);
	}
	ocelot_write_rix(ocelot,
			 ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports, 0)),
			 ANA_PGID_PGID, PGID_MC);
	ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_MCIPV4);
	ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_MCIPV6);

	/* Allow manual injection via DEVCPU_QS registers, and byte swap these
	 * registers endianness.
	 */
	ocelot_write_rix(ocelot, QS_INJ_GRP_CFG_BYTE_SWAP |
			 QS_INJ_GRP_CFG_MODE(1), QS_INJ_GRP_CFG, 0);
	ocelot_write_rix(ocelot, QS_XTR_GRP_CFG_BYTE_SWAP |
			 QS_XTR_GRP_CFG_MODE(1), QS_XTR_GRP_CFG, 0);
	ocelot_write(ocelot, ANA_CPUQ_CFG_CPUQ_MIRROR(2) |
		     ANA_CPUQ_CFG_CPUQ_LRN(2) |
		     ANA_CPUQ_CFG_CPUQ_MAC_COPY(2) |
		     ANA_CPUQ_CFG_CPUQ_SRC_COPY(2) |
		     ANA_CPUQ_CFG_CPUQ_LOCKED_PORTMOVE(2) |
		     ANA_CPUQ_CFG_CPUQ_ALLBRIDGE(6) |
		     ANA_CPUQ_CFG_CPUQ_IPMC_CTRL(6) |
		     ANA_CPUQ_CFG_CPUQ_IGMP(6) |
		     ANA_CPUQ_CFG_CPUQ_MLD(6), ANA_CPUQ_CFG);
	for (i = 0; i < 16; i++)
		ocelot_write_rix(ocelot, ANA_CPUQ_8021_CFG_CPUQ_GARP_VAL(6) |
				 ANA_CPUQ_8021_CFG_CPUQ_BPDU_VAL(6),
				 ANA_CPUQ_8021_CFG, i);

1616
	INIT_DELAYED_WORK(&ocelot->stats_work, ocelot_check_stats_work);
1617 1618
	queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work,
			   OCELOT_STATS_CHECK_DELAY);
1619

1620 1621 1622 1623 1624 1625
	return 0;
}
EXPORT_SYMBOL(ocelot_init);

void ocelot_deinit(struct ocelot *ocelot)
{
1626
	cancel_delayed_work(&ocelot->stats_work);
1627
	destroy_workqueue(ocelot->stats_queue);
1628
	destroy_workqueue(ocelot->owq);
1629 1630 1631 1632
	mutex_destroy(&ocelot->stats_lock);
}
EXPORT_SYMBOL(ocelot_deinit);

1633 1634 1635 1636 1637 1638 1639 1640
void ocelot_deinit_port(struct ocelot *ocelot, int port)
{
	struct ocelot_port *ocelot_port = ocelot->ports[port];

	skb_queue_purge(&ocelot_port->tx_skbs);
}
EXPORT_SYMBOL(ocelot_deinit_port);

1641
MODULE_LICENSE("Dual MIT/GPL");