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"); |