ocelot.c (abc7220b2233df9b13d8e0e312fb6f31e5402d7d) ocelot.c (2d44b097bbb9d0af0f3b94304fee4b639ab14171)
1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
2/*
3 * Microsemi Ocelot Switch driver
4 *
5 * Copyright (c) 2017 Microsemi Corporation
6 */
7#include <linux/if_bridge.h>
8#include "ocelot.h"

--- 399 unchanged lines hidden (view full) ---

408{
409 struct ocelot_port *ocelot_port = ocelot->ports[port];
410
411 ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
412 ocelot_fields_write(ocelot, port, QSYS_SWITCH_PORT_MODE_PORT_ENA, 0);
413}
414EXPORT_SYMBOL(ocelot_port_disable);
415
1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
2/*
3 * Microsemi Ocelot Switch driver
4 *
5 * Copyright (c) 2017 Microsemi Corporation
6 */
7#include <linux/if_bridge.h>
8#include "ocelot.h"

--- 399 unchanged lines hidden (view full) ---

408{
409 struct ocelot_port *ocelot_port = ocelot->ports[port];
410
411 ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
412 ocelot_fields_write(ocelot, port, QSYS_SWITCH_PORT_MODE_PORT_ENA, 0);
413}
414EXPORT_SYMBOL(ocelot_port_disable);
415
416int ocelot_port_add_txtstamp_skb(struct ocelot_port *ocelot_port,
417 struct sk_buff *skb)
416void ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port,
417 struct sk_buff *clone)
418{
418{
419 struct skb_shared_info *shinfo = skb_shinfo(skb);
420 struct ocelot *ocelot = ocelot_port->ocelot;
419 struct ocelot_port *ocelot_port = ocelot->ports[port];
421
420
422 if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP &&
423 ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
424 shinfo->tx_flags |= SKBTX_IN_PROGRESS;
425 /* Store timestamp ID in cb[0] of sk_buff */
426 skb->cb[0] = ocelot_port->ts_id % 4;
427 skb_queue_tail(&ocelot_port->tx_skbs, skb);
428 return 0;
429 }
430 return -ENODATA;
421 spin_lock(&ocelot_port->ts_id_lock);
422
423 skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS;
424 /* Store timestamp ID in cb[0] of sk_buff */
425 clone->cb[0] = ocelot_port->ts_id;
426 ocelot_port->ts_id = (ocelot_port->ts_id + 1) % 4;
427 skb_queue_tail(&ocelot_port->tx_skbs, clone);
428
429 spin_unlock(&ocelot_port->ts_id_lock);
431}
432EXPORT_SYMBOL(ocelot_port_add_txtstamp_skb);
433
434static void ocelot_get_hwtimestamp(struct ocelot *ocelot,
435 struct timespec64 *ts)
436{
437 unsigned long flags;
438 u32 val;

--- 62 unchanged lines hidden (view full) ---

501 ocelot_get_hwtimestamp(ocelot, &ts);
502
503 if (unlikely(!skb_match))
504 continue;
505
506 /* Set the timestamp into the skb */
507 memset(&shhwtstamps, 0, sizeof(shhwtstamps));
508 shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
430}
431EXPORT_SYMBOL(ocelot_port_add_txtstamp_skb);
432
433static void ocelot_get_hwtimestamp(struct ocelot *ocelot,
434 struct timespec64 *ts)
435{
436 unsigned long flags;
437 u32 val;

--- 62 unchanged lines hidden (view full) ---

500 ocelot_get_hwtimestamp(ocelot, &ts);
501
502 if (unlikely(!skb_match))
503 continue;
504
505 /* Set the timestamp into the skb */
506 memset(&shhwtstamps, 0, sizeof(shhwtstamps));
507 shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
509 skb_tstamp_tx(skb_match, &shhwtstamps);
508 skb_complete_tx_timestamp(skb_match, &shhwtstamps);
510
509
511 dev_kfree_skb_any(skb_match);
512
513 /* Next ts */
514 ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
515 }
516}
517EXPORT_SYMBOL(ocelot_get_txtstamp);
518
519int ocelot_fdb_add(struct ocelot *ocelot, int port,
520 const unsigned char *addr, u16 vid)

--- 774 unchanged lines hidden (view full) ---

1295}
1296EXPORT_SYMBOL(ocelot_get_max_mtu);
1297
1298void ocelot_init_port(struct ocelot *ocelot, int port)
1299{
1300 struct ocelot_port *ocelot_port = ocelot->ports[port];
1301
1302 skb_queue_head_init(&ocelot_port->tx_skbs);
510 /* Next ts */
511 ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
512 }
513}
514EXPORT_SYMBOL(ocelot_get_txtstamp);
515
516int ocelot_fdb_add(struct ocelot *ocelot, int port,
517 const unsigned char *addr, u16 vid)

--- 774 unchanged lines hidden (view full) ---

1292}
1293EXPORT_SYMBOL(ocelot_get_max_mtu);
1294
1295void ocelot_init_port(struct ocelot *ocelot, int port)
1296{
1297 struct ocelot_port *ocelot_port = ocelot->ports[port];
1298
1299 skb_queue_head_init(&ocelot_port->tx_skbs);
1300 spin_lock_init(&ocelot_port->ts_id_lock);
1303
1304 /* Basic L2 initialization */
1305
1306 /* Set MAC IFG Gaps
1307 * FDX: TX_IFG = 5, RX_IFG1 = RX_IFG2 = 0
1308 * !FDX: TX_IFG = 5, RX_IFG1 = RX_IFG2 = 5
1309 */
1310 ocelot_port_writel(ocelot_port, DEV_MAC_IFG_CFG_TX_IFG(5),

--- 32 unchanged lines hidden (view full) ---

1343 REW_PORT_VLAN_CFG_PORT_TPID_M,
1344 REW_PORT_VLAN_CFG, port);
1345
1346 /* Enable vcap lookups */
1347 ocelot_vcap_enable(ocelot, port);
1348}
1349EXPORT_SYMBOL(ocelot_init_port);
1350
1301
1302 /* Basic L2 initialization */
1303
1304 /* Set MAC IFG Gaps
1305 * FDX: TX_IFG = 5, RX_IFG1 = RX_IFG2 = 0
1306 * !FDX: TX_IFG = 5, RX_IFG1 = RX_IFG2 = 5
1307 */
1308 ocelot_port_writel(ocelot_port, DEV_MAC_IFG_CFG_TX_IFG(5),

--- 32 unchanged lines hidden (view full) ---

1341 REW_PORT_VLAN_CFG_PORT_TPID_M,
1342 REW_PORT_VLAN_CFG, port);
1343
1344 /* Enable vcap lookups */
1345 ocelot_vcap_enable(ocelot, port);
1346}
1347EXPORT_SYMBOL(ocelot_init_port);
1348
1351/* Configure and enable the CPU port module, which is a set of queues.
1352 * If @npi contains a valid port index, the CPU port module is connected
1353 * to the Node Processor Interface (NPI). This is the mode through which
1354 * frames can be injected from and extracted to an external CPU,
1355 * over Ethernet.
1349/* Configure and enable the CPU port module, which is a set of queues
1350 * accessible through register MMIO, frame DMA or Ethernet (in case
1351 * NPI mode is used).
1356 */
1352 */
1357void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
1358 enum ocelot_tag_prefix injection,
1359 enum ocelot_tag_prefix extraction)
1353static void ocelot_cpu_port_init(struct ocelot *ocelot)
1360{
1361 int cpu = ocelot->num_phys_ports;
1362
1354{
1355 int cpu = ocelot->num_phys_ports;
1356
1363 ocelot->npi = npi;
1364 ocelot->inj_prefix = injection;
1365 ocelot->xtr_prefix = extraction;
1366
1367 /* The unicast destination PGID for the CPU port module is unused */
1368 ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu);
1369 /* Instead set up a multicast destination PGID for traffic copied to
1370 * the CPU. Whitelisted MAC addresses like the port netdevice MAC
1371 * addresses will be copied to the CPU via this PGID.
1372 */
1373 ocelot_write_rix(ocelot, BIT(cpu), ANA_PGID_PGID, PGID_CPU);
1374 ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_RECV_ENA |
1375 ANA_PORT_PORT_CFG_PORTID_VAL(cpu),
1376 ANA_PORT_PORT_CFG, cpu);
1377
1357 /* The unicast destination PGID for the CPU port module is unused */
1358 ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu);
1359 /* Instead set up a multicast destination PGID for traffic copied to
1360 * the CPU. Whitelisted MAC addresses like the port netdevice MAC
1361 * addresses will be copied to the CPU via this PGID.
1362 */
1363 ocelot_write_rix(ocelot, BIT(cpu), ANA_PGID_PGID, PGID_CPU);
1364 ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_RECV_ENA |
1365 ANA_PORT_PORT_CFG_PORTID_VAL(cpu),
1366 ANA_PORT_PORT_CFG, cpu);
1367
1378 if (npi >= 0 && npi < ocelot->num_phys_ports) {
1379 ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M |
1380 QSYS_EXT_CPU_CFG_EXT_CPU_PORT(npi),
1381 QSYS_EXT_CPU_CFG);
1382
1383 /* Enable NPI port */
1384 ocelot_fields_write(ocelot, npi,
1385 QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
1386 /* NPI port Injection/Extraction configuration */
1387 ocelot_fields_write(ocelot, npi, SYS_PORT_MODE_INCL_XTR_HDR,
1388 extraction);
1389 ocelot_fields_write(ocelot, npi, SYS_PORT_MODE_INCL_INJ_HDR,
1390 injection);
1391
1392 /* Disable transmission of pause frames */
1393 ocelot_fields_write(ocelot, npi, SYS_PAUSE_CFG_PAUSE_ENA, 0);
1394 }
1395
1396 /* Enable CPU port module */
1397 ocelot_fields_write(ocelot, cpu, QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
1398 /* CPU port Injection/Extraction configuration */
1399 ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_XTR_HDR,
1368 /* Enable CPU port module */
1369 ocelot_fields_write(ocelot, cpu, QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
1370 /* CPU port Injection/Extraction configuration */
1371 ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_XTR_HDR,
1400 extraction);
1372 ocelot->xtr_prefix);
1401 ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_INJ_HDR,
1373 ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_INJ_HDR,
1402 injection);
1374 ocelot->inj_prefix);
1403
1404 /* Configure the CPU port to be VLAN aware */
1405 ocelot_write_gix(ocelot, ANA_PORT_VLAN_CFG_VLAN_VID(0) |
1406 ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
1407 ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1),
1408 ANA_PORT_VLAN_CFG, cpu);
1409}
1375
1376 /* Configure the CPU port to be VLAN aware */
1377 ocelot_write_gix(ocelot, ANA_PORT_VLAN_CFG_VLAN_VID(0) |
1378 ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
1379 ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1),
1380 ANA_PORT_VLAN_CFG, cpu);
1381}
1410EXPORT_SYMBOL(ocelot_configure_cpu);
1411
1412int ocelot_init(struct ocelot *ocelot)
1413{
1414 char queue_name[32];
1415 int i, ret;
1416 u32 port;
1417
1418 if (ocelot->ops->reset) {

--- 23 unchanged lines hidden (view full) ---

1442 ocelot->stats_queue = create_singlethread_workqueue(queue_name);
1443 if (!ocelot->stats_queue)
1444 return -ENOMEM;
1445
1446 INIT_LIST_HEAD(&ocelot->multicast);
1447 ocelot_mact_init(ocelot);
1448 ocelot_vlan_init(ocelot);
1449 ocelot_vcap_init(ocelot);
1382
1383int ocelot_init(struct ocelot *ocelot)
1384{
1385 char queue_name[32];
1386 int i, ret;
1387 u32 port;
1388
1389 if (ocelot->ops->reset) {

--- 23 unchanged lines hidden (view full) ---

1413 ocelot->stats_queue = create_singlethread_workqueue(queue_name);
1414 if (!ocelot->stats_queue)
1415 return -ENOMEM;
1416
1417 INIT_LIST_HEAD(&ocelot->multicast);
1418 ocelot_mact_init(ocelot);
1419 ocelot_vlan_init(ocelot);
1420 ocelot_vcap_init(ocelot);
1421 ocelot_cpu_port_init(ocelot);
1450
1451 for (port = 0; port < ocelot->num_phys_ports; port++) {
1452 /* Clear all counters (5 groups) */
1453 ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port) |
1454 SYS_STAT_CFG_STAT_CLEAR_SHOT(0x7f),
1455 SYS_STAT_CFG);
1456 }
1457

--- 81 unchanged lines hidden (view full) ---

1539 OCELOT_STATS_CHECK_DELAY);
1540
1541 return 0;
1542}
1543EXPORT_SYMBOL(ocelot_init);
1544
1545void ocelot_deinit(struct ocelot *ocelot)
1546{
1422
1423 for (port = 0; port < ocelot->num_phys_ports; port++) {
1424 /* Clear all counters (5 groups) */
1425 ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port) |
1426 SYS_STAT_CFG_STAT_CLEAR_SHOT(0x7f),
1427 SYS_STAT_CFG);
1428 }
1429

--- 81 unchanged lines hidden (view full) ---

1511 OCELOT_STATS_CHECK_DELAY);
1512
1513 return 0;
1514}
1515EXPORT_SYMBOL(ocelot_init);
1516
1517void ocelot_deinit(struct ocelot *ocelot)
1518{
1547 struct ocelot_port *port;
1548 int i;
1549
1550 cancel_delayed_work(&ocelot->stats_work);
1551 destroy_workqueue(ocelot->stats_queue);
1552 mutex_destroy(&ocelot->stats_lock);
1519 cancel_delayed_work(&ocelot->stats_work);
1520 destroy_workqueue(ocelot->stats_queue);
1521 mutex_destroy(&ocelot->stats_lock);
1553
1554 for (i = 0; i < ocelot->num_phys_ports; i++) {
1555 port = ocelot->ports[i];
1556 skb_queue_purge(&port->tx_skbs);
1557 }
1558}
1559EXPORT_SYMBOL(ocelot_deinit);
1560
1522}
1523EXPORT_SYMBOL(ocelot_deinit);
1524
1525void ocelot_deinit_port(struct ocelot *ocelot, int port)
1526{
1527 struct ocelot_port *ocelot_port = ocelot->ports[port];
1528
1529 skb_queue_purge(&ocelot_port->tx_skbs);
1530}
1531EXPORT_SYMBOL(ocelot_deinit_port);
1532
1561MODULE_LICENSE("Dual MIT/GPL");
1533MODULE_LICENSE("Dual MIT/GPL");