Lines Matching +full:ocelot +full:- +full:1

1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
3 * Copyright 2018-2019 NXP
13 #include <soc/mscc/ocelot.h>
14 #include <linux/dsa/ocelot.h>
15 #include <linux/pcs-lynx.h>
587 [ANA_ANEVENTS_SEQ_GEN_ERR_0] = REG_FIELD(ANA_ANEVENTS, 1, 1),
599 [QSYS_SWITCH_PORT_MODE_TX_PFC_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 1, 8, 7, 4),
603 [SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 7, 4),
606 [SYS_PAUSE_CFG_PAUSE_STOP] = REG_FIELD_ID(SYS_PAUSE_CFG, 1, 9, 7, 4),
607 [SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 7, 4),
614 [VCAP_ES0_L2_MC] = { 8, 1},
615 [VCAP_ES0_L2_BC] = { 9, 1},
617 [VCAP_ES0_DP] = { 22, 1},
623 [VCAP_ES0_ACT_PUSH_INNER_TAG] = { 2, 1},
625 [VCAP_ES0_ACT_TAG_A_VID_SEL] = { 5, 1},
629 [VCAP_ES0_ACT_TAG_B_VID_SEL] = { 12, 1},
634 [VCAP_ES0_ACT_DEI_A_VAL] = { 32, 1},
637 [VCAP_ES0_ACT_DEI_B_VAL] = { 48, 1},
639 [VCAP_ES0_ACT_HIT_STICKY] = { 72, 1},
643 [VCAP_IS1_HK_TYPE] = { 0, 1},
644 [VCAP_IS1_HK_LOOKUP] = { 1, 2},
647 [VCAP_IS1_HK_OAM_Y1731] = { 19, 1},
648 [VCAP_IS1_HK_L2_MC] = { 20, 1},
649 [VCAP_IS1_HK_L2_BC] = { 21, 1},
650 [VCAP_IS1_HK_IP_MC] = { 22, 1},
651 [VCAP_IS1_HK_VLAN_TAGGED] = { 23, 1},
652 [VCAP_IS1_HK_VLAN_DBL_TAGGED] = { 24, 1},
653 [VCAP_IS1_HK_TPID] = { 25, 1},
655 [VCAP_IS1_HK_DEI] = { 38, 1},
659 [VCAP_IS1_HK_ETYPE_LEN] = { 90, 1},
661 [VCAP_IS1_HK_IP_SNAP] = {107, 1},
662 [VCAP_IS1_HK_IP4] = {108, 1},
663 /* Layer-3 Information */
664 [VCAP_IS1_HK_L3_FRAGMENT] = {109, 1},
665 [VCAP_IS1_HK_L3_FRAG_OFS_GT0] = {110, 1},
666 [VCAP_IS1_HK_L3_OPTIONS] = {111, 1},
669 /* Layer-4 Information */
670 [VCAP_IS1_HK_TCP_UDP] = {150, 1},
671 [VCAP_IS1_HK_TCP] = {151, 1},
675 [VCAP_IS1_HK_IP4_INNER_TPID] = { 42, 1},
677 [VCAP_IS1_HK_IP4_INNER_DEI] = { 55, 1},
679 [VCAP_IS1_HK_IP4_IP4] = { 59, 1},
680 [VCAP_IS1_HK_IP4_L3_FRAGMENT] = { 60, 1},
681 [VCAP_IS1_HK_IP4_L3_FRAG_OFS_GT0] = { 61, 1},
682 [VCAP_IS1_HK_IP4_L3_OPTIONS] = { 62, 1},
687 [VCAP_IS1_HK_IP4_TCP_UDP] = {141, 1},
688 [VCAP_IS1_HK_IP4_TCP] = {142, 1},
694 [VCAP_IS1_ACT_DSCP_ENA] = { 0, 1},
695 [VCAP_IS1_ACT_DSCP_VAL] = { 1, 6},
696 [VCAP_IS1_ACT_QOS_ENA] = { 7, 1},
698 [VCAP_IS1_ACT_DP_ENA] = { 11, 1},
699 [VCAP_IS1_ACT_DP_VAL] = { 12, 1},
704 [VCAP_IS1_ACT_VID_REPLACE_ENA] = { 38, 1},
708 [VCAP_IS1_ACT_PCP_DEI_ENA] = { 66, 1},
710 [VCAP_IS1_ACT_DEI_VAL] = { 70, 1},
711 [VCAP_IS1_ACT_VLAN_POP_CNT_ENA] = { 71, 1},
714 [VCAP_IS1_ACT_HIT_STICKY] = { 78, 1},
720 [VCAP_IS2_HK_FIRST] = { 4, 1},
723 [VCAP_IS2_HK_RSV2] = { 20, 1},
724 [VCAP_IS2_HK_HOST_MATCH] = { 21, 1},
725 [VCAP_IS2_HK_L2_MC] = { 22, 1},
726 [VCAP_IS2_HK_L2_BC] = { 23, 1},
727 [VCAP_IS2_HK_VLAN_TAGGED] = { 24, 1},
729 [VCAP_IS2_HK_DEI] = { 37, 1},
745 [VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK] = { 89, 1},
746 [VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK] = { 90, 1},
747 [VCAP_IS2_HK_MAC_ARP_LEN_OK] = { 91, 1},
748 [VCAP_IS2_HK_MAC_ARP_TARGET_MATCH] = { 92, 1},
749 [VCAP_IS2_HK_MAC_ARP_SENDER_MATCH] = { 93, 1},
750 [VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN] = { 94, 1},
754 [VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP] = {161, 1},
756 [VCAP_IS2_HK_IP4] = { 41, 1},
757 [VCAP_IS2_HK_L3_FRAGMENT] = { 42, 1},
758 [VCAP_IS2_HK_L3_FRAG_OFS_GT0] = { 43, 1},
759 [VCAP_IS2_HK_L3_OPTIONS] = { 44, 1},
760 [VCAP_IS2_HK_IP4_L3_TTL_GT0] = { 45, 1},
764 [VCAP_IS2_HK_DIP_EQ_SIP] = {118, 1},
766 [VCAP_IS2_HK_TCP] = {119, 1},
770 [VCAP_IS2_HK_L4_SPORT_EQ_DPORT] = {160, 1},
771 [VCAP_IS2_HK_L4_SEQUENCE_EQ0] = {161, 1},
772 [VCAP_IS2_HK_L4_FIN] = {162, 1},
773 [VCAP_IS2_HK_L4_SYN] = {163, 1},
774 [VCAP_IS2_HK_L4_RST] = {164, 1},
775 [VCAP_IS2_HK_L4_PSH] = {165, 1},
776 [VCAP_IS2_HK_L4_ACK] = {166, 1},
777 [VCAP_IS2_HK_L4_URG] = {167, 1},
784 [VCAP_IS2_HK_IP6_L3_TTL_GT0] = { 41, 1},
793 [VCAP_IS2_HK_OAM_CCM_CNTS_EQ0] = {181, 1},
794 [VCAP_IS2_HK_OAM_IS_Y1731] = {182, 1},
798 [VCAP_IS2_ACT_HIT_ME_ONCE] = { 0, 1},
799 [VCAP_IS2_ACT_CPU_COPY_ENA] = { 1, 1},
802 [VCAP_IS2_ACT_MIRROR_ENA] = { 7, 1},
803 [VCAP_IS2_ACT_LRN_DIS] = { 8, 1},
804 [VCAP_IS2_ACT_POLICE_ENA] = { 9, 1},
806 [VCAP_IS2_ACT_POLICE_VCAP_ONLY] = { 19, 1},
809 [VCAP_IS2_ACT_SMAC_REPLACE_ENA] = { 35, 1},
821 .count = 1,
841 .action_type_width = 1,
879 static int vsc9959_gcb_soft_rst_status(struct ocelot *ocelot) in vsc9959_gcb_soft_rst_status() argument
883 ocelot_field_read(ocelot, GCB_SOFT_RST_SWC_RST, &val); in vsc9959_gcb_soft_rst_status()
888 static int vsc9959_sys_ram_init_status(struct ocelot *ocelot) in vsc9959_sys_ram_init_status() argument
890 return ocelot_read(ocelot, SYS_RAM_INIT); in vsc9959_sys_ram_init_status()
896 static int vsc9959_reset(struct ocelot *ocelot) in vsc9959_reset() argument
900 /* soft-reset the switch core */ in vsc9959_reset()
901 ocelot_field_write(ocelot, GCB_SOFT_RST_SWC_RST, 1); in vsc9959_reset()
903 err = readx_poll_timeout(vsc9959_gcb_soft_rst_status, ocelot, val, !val, in vsc9959_reset()
906 dev_err(ocelot->dev, "timeout: switch core reset\n"); in vsc9959_reset()
911 ocelot_write(ocelot, SYS_RAM_INIT_RAM_INIT, SYS_RAM_INIT); in vsc9959_reset()
912 err = readx_poll_timeout(vsc9959_sys_ram_init_status, ocelot, val, !val, in vsc9959_reset()
916 dev_err(ocelot->dev, "timeout: switch sram init\n"); in vsc9959_reset()
921 ocelot_field_write(ocelot, SYS_RESET_CFG_CORE_ENA, 1); in vsc9959_reset()
927 * Bit 8: Unit; 0:1, 1:16
928 * Bit 7-0: Value to be multiplied with unit
956 static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) in vsc9959_mdio_bus_alloc() argument
958 struct pci_dev *pdev = to_pci_dev(ocelot->dev); in vsc9959_mdio_bus_alloc()
959 struct felix *felix = ocelot_to_felix(ocelot); in vsc9959_mdio_bus_alloc()
961 struct device *dev = ocelot->dev; in vsc9959_mdio_bus_alloc()
970 felix->pcs = devm_kcalloc(dev, felix->info->num_ports, in vsc9959_mdio_bus_alloc()
973 if (!felix->pcs) { in vsc9959_mdio_bus_alloc()
975 return -ENOMEM; in vsc9959_mdio_bus_alloc()
996 return -ENOMEM; in vsc9959_mdio_bus_alloc()
998 bus->name = "VSC9959 internal MDIO bus"; in vsc9959_mdio_bus_alloc()
999 bus->read = enetc_mdio_read_c22; in vsc9959_mdio_bus_alloc()
1000 bus->write = enetc_mdio_write_c22; in vsc9959_mdio_bus_alloc()
1001 bus->read_c45 = enetc_mdio_read_c45; in vsc9959_mdio_bus_alloc()
1002 bus->write_c45 = enetc_mdio_write_c45; in vsc9959_mdio_bus_alloc()
1003 bus->parent = dev; in vsc9959_mdio_bus_alloc()
1004 mdio_priv = bus->priv; in vsc9959_mdio_bus_alloc()
1005 mdio_priv->hw = hw; in vsc9959_mdio_bus_alloc()
1009 mdio_priv->mdio_base = 0; in vsc9959_mdio_bus_alloc()
1010 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev)); in vsc9959_mdio_bus_alloc()
1020 felix->imdio = bus; in vsc9959_mdio_bus_alloc()
1022 for (port = 0; port < felix->info->num_ports; port++) { in vsc9959_mdio_bus_alloc()
1023 struct ocelot_port *ocelot_port = ocelot->ports[port]; in vsc9959_mdio_bus_alloc()
1026 if (dsa_is_unused_port(felix->ds, port)) in vsc9959_mdio_bus_alloc()
1029 if (ocelot_port->phy_mode == PHY_INTERFACE_MODE_INTERNAL) in vsc9959_mdio_bus_alloc()
1032 phylink_pcs = lynx_pcs_create_mdiodev(felix->imdio, port); in vsc9959_mdio_bus_alloc()
1036 felix->pcs[port] = phylink_pcs; in vsc9959_mdio_bus_alloc()
1044 static void vsc9959_mdio_bus_free(struct ocelot *ocelot) in vsc9959_mdio_bus_free() argument
1046 struct felix *felix = ocelot_to_felix(ocelot); in vsc9959_mdio_bus_free()
1049 for (port = 0; port < ocelot->num_phys_ports; port++) { in vsc9959_mdio_bus_free()
1050 struct phylink_pcs *phylink_pcs = felix->pcs[port]; in vsc9959_mdio_bus_free()
1055 mdiobus_unregister(felix->imdio); in vsc9959_mdio_bus_free()
1056 mdiobus_free(felix->imdio); in vsc9959_mdio_bus_free()
1080 return (gate_len_ns - VSC9959_TAS_MIN_GATE_LEN_NS) * PSEC_PER_NSEC; in vsc9959_tas_remaining_gate_len_ps()
1084 * of a cyclic tc-taprio schedule. If a gate is always open, the duration is
1105 n = taprio->num_entries; in vsc9959_tas_min_gate_lengths()
1115 entry = &taprio->entries[i % n]; in vsc9959_tas_min_gate_lengths()
1118 if (entry->gate_mask & BIT(tc)) { in vsc9959_tas_min_gate_lengths()
1119 gate_len[tc] += entry->interval; in vsc9959_tas_min_gate_lengths()
1148 static void vsc9959_port_qmaxsdu_set(struct ocelot *ocelot, int port, int tc, in vsc9959_port_qmaxsdu_set() argument
1153 ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_0, in vsc9959_port_qmaxsdu_set()
1156 case 1: in vsc9959_port_qmaxsdu_set()
1157 ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_1, in vsc9959_port_qmaxsdu_set()
1161 ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_2, in vsc9959_port_qmaxsdu_set()
1165 ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_3, in vsc9959_port_qmaxsdu_set()
1169 ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_4, in vsc9959_port_qmaxsdu_set()
1173 ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_5, in vsc9959_port_qmaxsdu_set()
1177 ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_6, in vsc9959_port_qmaxsdu_set()
1181 ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_7, in vsc9959_port_qmaxsdu_set()
1187 static u32 vsc9959_port_qmaxsdu_get(struct ocelot *ocelot, int port, int tc) in vsc9959_port_qmaxsdu_get() argument
1190 case 0: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_0, port); in vsc9959_port_qmaxsdu_get()
1191 case 1: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_1, port); in vsc9959_port_qmaxsdu_get()
1192 case 2: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_2, port); in vsc9959_port_qmaxsdu_get()
1193 case 3: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_3, port); in vsc9959_port_qmaxsdu_get()
1194 case 4: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_4, port); in vsc9959_port_qmaxsdu_get()
1195 case 5: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_5, port); in vsc9959_port_qmaxsdu_get()
1196 case 6: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_6, port); in vsc9959_port_qmaxsdu_get()
1197 case 7: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_7, port); in vsc9959_port_qmaxsdu_get()
1205 if (!taprio || !taprio->max_sdu[tc]) in vsc9959_tas_tc_max_sdu()
1208 return taprio->max_sdu[tc] + ETH_HLEN + 2 * VLAN_HLEN + ETH_FCS_LEN; in vsc9959_tas_tc_max_sdu()
1217 static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port) in vsc9959_tas_guard_bands_update() argument
1219 struct ocelot_port *ocelot_port = ocelot->ports[port]; in vsc9959_tas_guard_bands_update()
1220 struct ocelot_mm_state *mm = &ocelot->mm[port]; in vsc9959_tas_guard_bands_update()
1230 lockdep_assert_held(&ocelot->fwd_domain_lock); in vsc9959_tas_guard_bands_update()
1232 taprio = ocelot_port->taprio; in vsc9959_tas_guard_bands_update()
1234 val = ocelot_read_rix(ocelot, QSYS_TAG_CONFIG, port); in vsc9959_tas_guard_bands_update()
1269 val = ocelot_read_rix(ocelot, QSYS_PREEMPTION_CFG, port); in vsc9959_tas_guard_bands_update()
1274 dev_dbg(ocelot->dev, in vsc9959_tas_guard_bands_update()
1289 if ((mm->active_preemptible_tcs & BIT(tc)) ? in vsc9959_tas_guard_bands_update()
1296 dev_dbg(ocelot->dev, in vsc9959_tas_guard_bands_update()
1307 * per-tc static guard band lengths, so it reduces the in vsc9959_tas_guard_bands_update()
1319 max_sdu = 1; in vsc9959_tas_guard_bands_update()
1326 max_sdu -= 20; in vsc9959_tas_guard_bands_update()
1331 dev_info(ocelot->dev, in vsc9959_tas_guard_bands_update()
1340 vsc9959_port_qmaxsdu_set(ocelot, port, tc, max_sdu); in vsc9959_tas_guard_bands_update()
1343 ocelot_write_rix(ocelot, maxlen, QSYS_PORT_MAX_SDU, port); in vsc9959_tas_guard_bands_update()
1345 ocelot->ops->cut_through_fwd(ocelot); in vsc9959_tas_guard_bands_update()
1348 static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port, in vsc9959_sched_speed_set() argument
1351 struct ocelot_port *ocelot_port = ocelot->ports[port]; in vsc9959_sched_speed_set()
1372 mutex_lock(&ocelot->fwd_domain_lock); in vsc9959_sched_speed_set()
1374 ocelot_rmw_rix(ocelot, in vsc9959_sched_speed_set()
1379 if (ocelot_port->taprio) in vsc9959_sched_speed_set()
1380 vsc9959_tas_guard_bands_update(ocelot, port); in vsc9959_sched_speed_set()
1382 mutex_unlock(&ocelot->fwd_domain_lock); in vsc9959_sched_speed_set()
1385 static void vsc9959_new_base_time(struct ocelot *ocelot, ktime_t base_time, in vsc9959_new_base_time() argument
1393 ocelot_ptp_gettime64(&ocelot->ptp_info, &ts); in vsc9959_new_base_time()
1398 u64 nr_of_cycles = current_time - base_time; in vsc9959_new_base_time()
1401 new_base_time += cycle_time * (nr_of_cycles + 1); in vsc9959_new_base_time()
1407 static u32 vsc9959_tas_read_cfg_status(struct ocelot *ocelot) in vsc9959_tas_read_cfg_status() argument
1409 return ocelot_read(ocelot, QSYS_TAS_PARAM_CFG_CTRL); in vsc9959_tas_read_cfg_status()
1412 static void vsc9959_tas_gcl_set(struct ocelot *ocelot, const u32 gcl_ix, in vsc9959_tas_gcl_set() argument
1415 ocelot_write(ocelot, in vsc9959_tas_gcl_set()
1417 QSYS_GCL_CFG_REG_1_GATE_STATE(entry->gate_mask), in vsc9959_tas_gcl_set()
1419 ocelot_write(ocelot, entry->interval, QSYS_GCL_CFG_REG_2); in vsc9959_tas_gcl_set()
1422 static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, in vsc9959_qos_port_tas_set() argument
1425 struct ocelot_port *ocelot_port = ocelot->ports[port]; in vsc9959_qos_port_tas_set()
1430 mutex_lock(&ocelot->fwd_domain_lock); in vsc9959_qos_port_tas_set()
1432 if (taprio->cmd == TAPRIO_CMD_DESTROY) { in vsc9959_qos_port_tas_set()
1433 ocelot_port_mqprio(ocelot, port, &taprio->mqprio); in vsc9959_qos_port_tas_set()
1434 ocelot_rmw_rix(ocelot, 0, QSYS_TAG_CONFIG_ENABLE, in vsc9959_qos_port_tas_set()
1437 taprio_offload_free(ocelot_port->taprio); in vsc9959_qos_port_tas_set()
1438 ocelot_port->taprio = NULL; in vsc9959_qos_port_tas_set()
1440 vsc9959_tas_guard_bands_update(ocelot, port); in vsc9959_qos_port_tas_set()
1442 mutex_unlock(&ocelot->fwd_domain_lock); in vsc9959_qos_port_tas_set()
1444 } else if (taprio->cmd != TAPRIO_CMD_REPLACE) { in vsc9959_qos_port_tas_set()
1445 ret = -EOPNOTSUPP; in vsc9959_qos_port_tas_set()
1449 ret = ocelot_port_mqprio(ocelot, port, &taprio->mqprio); in vsc9959_qos_port_tas_set()
1453 if (taprio->cycle_time > NSEC_PER_SEC || in vsc9959_qos_port_tas_set()
1454 taprio->cycle_time_extension >= NSEC_PER_SEC) { in vsc9959_qos_port_tas_set()
1455 ret = -EINVAL; in vsc9959_qos_port_tas_set()
1459 if (taprio->num_entries > VSC9959_TAS_GCL_ENTRY_MAX) { in vsc9959_qos_port_tas_set()
1460 ret = -ERANGE; in vsc9959_qos_port_tas_set()
1473 ocelot_rmw(ocelot, QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM(port) | in vsc9959_qos_port_tas_set()
1479 /* Hardware errata - Admin config could not be overwritten if in vsc9959_qos_port_tas_set()
1482 val = ocelot_read_rix(ocelot, QSYS_TAG_CONFIG, port); in vsc9959_qos_port_tas_set()
1484 val = ocelot_read(ocelot, QSYS_PARAM_STATUS_REG_8); in vsc9959_qos_port_tas_set()
1486 ret = -EBUSY; in vsc9959_qos_port_tas_set()
1491 ocelot_rmw_rix(ocelot, in vsc9959_qos_port_tas_set()
1500 vsc9959_new_base_time(ocelot, taprio->base_time, in vsc9959_qos_port_tas_set()
1501 taprio->cycle_time, &base_ts); in vsc9959_qos_port_tas_set()
1502 ocelot_write(ocelot, base_ts.tv_nsec, QSYS_PARAM_CFG_REG_1); in vsc9959_qos_port_tas_set()
1503 ocelot_write(ocelot, lower_32_bits(base_ts.tv_sec), QSYS_PARAM_CFG_REG_2); in vsc9959_qos_port_tas_set()
1505 ocelot_write(ocelot, in vsc9959_qos_port_tas_set()
1507 QSYS_PARAM_CFG_REG_3_LIST_LENGTH(taprio->num_entries), in vsc9959_qos_port_tas_set()
1509 ocelot_write(ocelot, taprio->cycle_time, QSYS_PARAM_CFG_REG_4); in vsc9959_qos_port_tas_set()
1510 ocelot_write(ocelot, taprio->cycle_time_extension, QSYS_PARAM_CFG_REG_5); in vsc9959_qos_port_tas_set()
1512 for (i = 0; i < taprio->num_entries; i++) in vsc9959_qos_port_tas_set()
1513 vsc9959_tas_gcl_set(ocelot, i, &taprio->entries[i]); in vsc9959_qos_port_tas_set()
1515 ocelot_rmw(ocelot, QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE, in vsc9959_qos_port_tas_set()
1519 ret = readx_poll_timeout(vsc9959_tas_read_cfg_status, ocelot, val, in vsc9959_qos_port_tas_set()
1525 ocelot_port->taprio = taprio_offload_get(taprio); in vsc9959_qos_port_tas_set()
1526 vsc9959_tas_guard_bands_update(ocelot, port); in vsc9959_qos_port_tas_set()
1528 mutex_unlock(&ocelot->fwd_domain_lock); in vsc9959_qos_port_tas_set()
1533 taprio->mqprio.qopt.num_tc = 0; in vsc9959_qos_port_tas_set()
1534 ocelot_port_mqprio(ocelot, port, &taprio->mqprio); in vsc9959_qos_port_tas_set()
1536 mutex_unlock(&ocelot->fwd_domain_lock); in vsc9959_qos_port_tas_set()
1541 static void vsc9959_tas_clock_adjust(struct ocelot *ocelot) in vsc9959_tas_clock_adjust() argument
1549 mutex_lock(&ocelot->fwd_domain_lock); in vsc9959_tas_clock_adjust()
1551 for (port = 0; port < ocelot->num_phys_ports; port++) { in vsc9959_tas_clock_adjust()
1552 ocelot_port = ocelot->ports[port]; in vsc9959_tas_clock_adjust()
1553 taprio = ocelot_port->taprio; in vsc9959_tas_clock_adjust()
1557 ocelot_rmw(ocelot, in vsc9959_tas_clock_adjust()
1562 /* Disable time-aware shaper */ in vsc9959_tas_clock_adjust()
1563 ocelot_rmw_rix(ocelot, 0, QSYS_TAG_CONFIG_ENABLE, in vsc9959_tas_clock_adjust()
1566 vsc9959_new_base_time(ocelot, taprio->base_time, in vsc9959_tas_clock_adjust()
1567 taprio->cycle_time, &base_ts); in vsc9959_tas_clock_adjust()
1569 ocelot_write(ocelot, base_ts.tv_nsec, QSYS_PARAM_CFG_REG_1); in vsc9959_tas_clock_adjust()
1570 ocelot_write(ocelot, lower_32_bits(base_ts.tv_sec), in vsc9959_tas_clock_adjust()
1573 ocelot_rmw(ocelot, in vsc9959_tas_clock_adjust()
1578 ocelot_rmw(ocelot, QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE, in vsc9959_tas_clock_adjust()
1582 /* Re-enable time-aware shaper */ in vsc9959_tas_clock_adjust()
1583 ocelot_rmw_rix(ocelot, QSYS_TAG_CONFIG_ENABLE, in vsc9959_tas_clock_adjust()
1587 mutex_unlock(&ocelot->fwd_domain_lock); in vsc9959_tas_clock_adjust()
1593 struct ocelot *ocelot = ds->priv; in vsc9959_qos_port_cbs_set() local
1594 int port_ix = port * 8 + cbs_qopt->queue; in vsc9959_qos_port_cbs_set()
1597 if (cbs_qopt->queue >= ds->num_tx_queues) in vsc9959_qos_port_cbs_set()
1598 return -EINVAL; in vsc9959_qos_port_cbs_set()
1600 if (!cbs_qopt->enable) { in vsc9959_qos_port_cbs_set()
1601 ocelot_write_gix(ocelot, QSYS_CIR_CFG_CIR_RATE(0) | in vsc9959_qos_port_cbs_set()
1605 ocelot_rmw_gix(ocelot, 0, QSYS_SE_CFG_SE_AVB_ENA, in vsc9959_qos_port_cbs_set()
1612 rate = DIV_ROUND_UP(cbs_qopt->idleslope, 100); in vsc9959_qos_port_cbs_set()
1614 rate = clamp_t(u32, rate, 1, GENMASK(14, 0)); in vsc9959_qos_port_cbs_set()
1616 burst = DIV_ROUND_UP(cbs_qopt->hicredit, 4096); in vsc9959_qos_port_cbs_set()
1618 burst = clamp_t(u32, burst, 1, GENMASK(5, 0)); in vsc9959_qos_port_cbs_set()
1619 ocelot_write_gix(ocelot, in vsc9959_qos_port_cbs_set()
1625 ocelot_rmw_gix(ocelot, in vsc9959_qos_port_cbs_set()
1638 switch (base->type) { in vsc9959_qos_query_caps()
1640 struct tc_mqprio_caps *caps = base->caps; in vsc9959_qos_query_caps()
1642 caps->validate_queue_counts = true; in vsc9959_qos_query_caps()
1647 struct tc_taprio_caps *caps = base->caps; in vsc9959_qos_query_caps()
1649 caps->supports_queue_max_sdu = true; in vsc9959_qos_query_caps()
1654 return -EOPNOTSUPP; in vsc9959_qos_query_caps()
1658 static int vsc9959_qos_port_mqprio(struct ocelot *ocelot, int port, in vsc9959_qos_port_mqprio() argument
1663 mutex_lock(&ocelot->fwd_domain_lock); in vsc9959_qos_port_mqprio()
1664 ret = ocelot_port_mqprio(ocelot, port, mqprio); in vsc9959_qos_port_mqprio()
1665 mutex_unlock(&ocelot->fwd_domain_lock); in vsc9959_qos_port_mqprio()
1674 struct ocelot *ocelot = ds->priv; in vsc9959_port_setup_tc() local
1680 return vsc9959_qos_port_tas_set(ocelot, port, type_data); in vsc9959_port_setup_tc()
1682 return vsc9959_qos_port_mqprio(ocelot, port, type_data); in vsc9959_port_setup_tc()
1686 return -EOPNOTSUPP; in vsc9959_port_setup_tc()
1757 struct flow_dissector *dissector = rule->match.dissector; in vsc9959_stream_identify()
1759 if (dissector->used_keys & in vsc9959_stream_identify()
1764 return -EOPNOTSUPP; in vsc9959_stream_identify()
1770 ether_addr_copy(stream->dmac, match.key->dst); in vsc9959_stream_identify()
1771 if (!is_zero_ether_addr(match.mask->src)) in vsc9959_stream_identify()
1772 return -EOPNOTSUPP; in vsc9959_stream_identify()
1774 return -EOPNOTSUPP; in vsc9959_stream_identify()
1781 if (match.mask->vlan_priority) in vsc9959_stream_identify()
1782 stream->prio = match.key->vlan_priority; in vsc9959_stream_identify()
1784 stream->prio = -1; in vsc9959_stream_identify()
1786 if (!match.mask->vlan_id) in vsc9959_stream_identify()
1787 return -EOPNOTSUPP; in vsc9959_stream_identify()
1788 stream->vid = match.key->vlan_id; in vsc9959_stream_identify()
1790 return -EOPNOTSUPP; in vsc9959_stream_identify()
1793 stream->id = f->cookie; in vsc9959_stream_identify()
1798 static int vsc9959_mact_stream_set(struct ocelot *ocelot, in vsc9959_mact_stream_set() argument
1807 ether_addr_copy(mac, stream->dmac); in vsc9959_mact_stream_set()
1808 vid = stream->vid; in vsc9959_mact_stream_set()
1813 ret = ocelot_mact_lookup(ocelot, &dst_idx, mac, vid, &type); in vsc9959_mact_stream_set()
1817 return -EOPNOTSUPP; in vsc9959_mact_stream_set()
1820 if ((stream->sfid_valid || stream->ssid_valid) && in vsc9959_mact_stream_set()
1824 sfid = stream->sfid_valid ? stream->sfid : -1; in vsc9959_mact_stream_set()
1825 ssid = stream->ssid_valid ? stream->ssid : -1; in vsc9959_mact_stream_set()
1827 ret = ocelot_mact_learn_streamdata(ocelot, dst_idx, mac, vid, type, in vsc9959_mact_stream_set()
1840 if (ether_addr_equal(tmp->dmac, stream->dmac) && in vsc9959_stream_table_lookup()
1841 tmp->vid == stream->vid) in vsc9959_stream_table_lookup()
1847 static int vsc9959_stream_table_add(struct ocelot *ocelot, in vsc9959_stream_table_add() argument
1857 return -ENOMEM; in vsc9959_stream_table_add()
1859 if (!stream->dummy) { in vsc9959_stream_table_add()
1860 ret = vsc9959_mact_stream_set(ocelot, stream_entry, extack); in vsc9959_stream_table_add()
1867 list_add_tail(&stream_entry->list, stream_list); in vsc9959_stream_table_add()
1878 if (tmp->id == id) in vsc9959_stream_table_get()
1884 static void vsc9959_stream_table_del(struct ocelot *ocelot, in vsc9959_stream_table_del() argument
1887 if (!stream->dummy) in vsc9959_stream_table_del()
1888 vsc9959_mact_stream_set(ocelot, stream, NULL); in vsc9959_stream_table_del()
1890 list_del(&stream->list); in vsc9959_stream_table_del()
1894 static u32 vsc9959_sfi_access_status(struct ocelot *ocelot) in vsc9959_sfi_access_status() argument
1896 return ocelot_read(ocelot, ANA_TABLES_SFIDACCESS); in vsc9959_sfi_access_status()
1899 static int vsc9959_psfp_sfi_set(struct ocelot *ocelot, in vsc9959_psfp_sfi_set() argument
1904 if (sfi->index > VSC9959_PSFP_SFID_MAX) in vsc9959_psfp_sfi_set()
1905 return -EINVAL; in vsc9959_psfp_sfi_set()
1907 if (!sfi->enable) { in vsc9959_psfp_sfi_set()
1908 ocelot_write(ocelot, ANA_TABLES_SFIDTIDX_SFID_INDEX(sfi->index), in vsc9959_psfp_sfi_set()
1912 ocelot_write(ocelot, val, ANA_TABLES_SFIDACCESS); in vsc9959_psfp_sfi_set()
1914 return readx_poll_timeout(vsc9959_sfi_access_status, ocelot, val, in vsc9959_psfp_sfi_set()
1919 if (sfi->sgid > VSC9959_PSFP_GATE_ID_MAX || in vsc9959_psfp_sfi_set()
1920 sfi->fmid > VSC9959_PSFP_POLICER_MAX) in vsc9959_psfp_sfi_set()
1921 return -EINVAL; in vsc9959_psfp_sfi_set()
1923 ocelot_write(ocelot, in vsc9959_psfp_sfi_set()
1924 (sfi->sg_valid ? ANA_TABLES_SFIDTIDX_SGID_VALID : 0) | in vsc9959_psfp_sfi_set()
1925 ANA_TABLES_SFIDTIDX_SGID(sfi->sgid) | in vsc9959_psfp_sfi_set()
1926 (sfi->fm_valid ? ANA_TABLES_SFIDTIDX_POL_ENA : 0) | in vsc9959_psfp_sfi_set()
1927 ANA_TABLES_SFIDTIDX_POL_IDX(sfi->fmid) | in vsc9959_psfp_sfi_set()
1928 ANA_TABLES_SFIDTIDX_SFID_INDEX(sfi->index), in vsc9959_psfp_sfi_set()
1931 ocelot_write(ocelot, in vsc9959_psfp_sfi_set()
1932 (sfi->prio_valid ? ANA_TABLES_SFIDACCESS_IGR_PRIO_MATCH_ENA : 0) | in vsc9959_psfp_sfi_set()
1933 ANA_TABLES_SFIDACCESS_IGR_PRIO(sfi->prio) | in vsc9959_psfp_sfi_set()
1934 ANA_TABLES_SFIDACCESS_MAX_SDU_LEN(sfi->maxsdu) | in vsc9959_psfp_sfi_set()
1938 return readx_poll_timeout(vsc9959_sfi_access_status, ocelot, val, in vsc9959_psfp_sfi_set()
1943 static int vsc9959_psfp_sfidmask_set(struct ocelot *ocelot, u32 sfid, int ports) in vsc9959_psfp_sfidmask_set() argument
1947 ocelot_rmw(ocelot, in vsc9959_psfp_sfidmask_set()
1952 ocelot_write(ocelot, in vsc9959_psfp_sfidmask_set()
1957 ocelot_rmw(ocelot, in vsc9959_psfp_sfidmask_set()
1962 return readx_poll_timeout(vsc9959_sfi_access_status, ocelot, val, in vsc9959_psfp_sfidmask_set()
1967 static int vsc9959_psfp_sfi_list_add(struct ocelot *ocelot, in vsc9959_psfp_sfi_list_add() argument
1976 return -ENOMEM; in vsc9959_psfp_sfi_list_add()
1978 refcount_set(&sfi_entry->refcount, 1); in vsc9959_psfp_sfi_list_add()
1980 ret = vsc9959_psfp_sfi_set(ocelot, sfi_entry); in vsc9959_psfp_sfi_list_add()
1986 vsc9959_psfp_sfidmask_set(ocelot, sfi->index, sfi->portmask); in vsc9959_psfp_sfi_list_add()
1988 list_add(&sfi_entry->list, pos); in vsc9959_psfp_sfi_list_add()
1993 static int vsc9959_psfp_sfi_table_add(struct ocelot *ocelot, in vsc9959_psfp_sfi_table_add() argument
2001 psfp = &ocelot->psfp; in vsc9959_psfp_sfi_table_add()
2002 last = &psfp->sfi_list; in vsc9959_psfp_sfi_table_add()
2004 list_for_each_safe(pos, q, &psfp->sfi_list) { in vsc9959_psfp_sfi_table_add()
2006 if (sfi->sg_valid == tmp->sg_valid && in vsc9959_psfp_sfi_table_add()
2007 sfi->fm_valid == tmp->fm_valid && in vsc9959_psfp_sfi_table_add()
2008 sfi->portmask == tmp->portmask && in vsc9959_psfp_sfi_table_add()
2009 tmp->sgid == sfi->sgid && in vsc9959_psfp_sfi_table_add()
2010 tmp->fmid == sfi->fmid) { in vsc9959_psfp_sfi_table_add()
2011 sfi->index = tmp->index; in vsc9959_psfp_sfi_table_add()
2012 refcount_inc(&tmp->refcount); in vsc9959_psfp_sfi_table_add()
2016 if (tmp->index == insert) { in vsc9959_psfp_sfi_table_add()
2021 sfi->index = insert; in vsc9959_psfp_sfi_table_add()
2023 return vsc9959_psfp_sfi_list_add(ocelot, sfi, last); in vsc9959_psfp_sfi_table_add()
2026 static int vsc9959_psfp_sfi_table_add2(struct ocelot *ocelot, in vsc9959_psfp_sfi_table_add2() argument
2036 psfp = &ocelot->psfp; in vsc9959_psfp_sfi_table_add2()
2037 last = &psfp->sfi_list; in vsc9959_psfp_sfi_table_add2()
2039 list_for_each_safe(pos, q, &psfp->sfi_list) { in vsc9959_psfp_sfi_table_add2()
2042 if (tmp->index >= insert + 2) in vsc9959_psfp_sfi_table_add2()
2045 insert = tmp->index + 1; in vsc9959_psfp_sfi_table_add2()
2048 sfi->index = insert; in vsc9959_psfp_sfi_table_add2()
2050 ret = vsc9959_psfp_sfi_list_add(ocelot, sfi, last); in vsc9959_psfp_sfi_table_add2()
2054 sfi2->index = insert + 1; in vsc9959_psfp_sfi_table_add2()
2056 return vsc9959_psfp_sfi_list_add(ocelot, sfi2, last->next); in vsc9959_psfp_sfi_table_add2()
2065 if (tmp->index == index) in vsc9959_psfp_sfi_table_get()
2071 static void vsc9959_psfp_sfi_table_del(struct ocelot *ocelot, u32 index) in vsc9959_psfp_sfi_table_del() argument
2077 psfp = &ocelot->psfp; in vsc9959_psfp_sfi_table_del()
2079 list_for_each_entry_safe(tmp, n, &psfp->sfi_list, list) in vsc9959_psfp_sfi_table_del()
2080 if (tmp->index == index) { in vsc9959_psfp_sfi_table_del()
2081 z = refcount_dec_and_test(&tmp->refcount); in vsc9959_psfp_sfi_table_del()
2083 tmp->enable = 0; in vsc9959_psfp_sfi_table_del()
2084 vsc9959_psfp_sfi_set(ocelot, tmp); in vsc9959_psfp_sfi_table_del()
2085 list_del(&tmp->list); in vsc9959_psfp_sfi_table_del()
2095 sgi->index = entry->hw_index; in vsc9959_psfp_parse_gate()
2096 sgi->ipv_valid = (entry->gate.prio < 0) ? 0 : 1; in vsc9959_psfp_parse_gate()
2097 sgi->init_ipv = (sgi->ipv_valid) ? entry->gate.prio : 0; in vsc9959_psfp_parse_gate()
2098 sgi->basetime = entry->gate.basetime; in vsc9959_psfp_parse_gate()
2099 sgi->cycletime = entry->gate.cycletime; in vsc9959_psfp_parse_gate()
2100 sgi->num_entries = entry->gate.num_entries; in vsc9959_psfp_parse_gate()
2101 sgi->enable = 1; in vsc9959_psfp_parse_gate()
2103 memcpy(sgi->entries, entry->gate.entries, in vsc9959_psfp_parse_gate()
2104 entry->gate.num_entries * sizeof(struct action_gate_entry)); in vsc9959_psfp_parse_gate()
2107 static u32 vsc9959_sgi_cfg_status(struct ocelot *ocelot) in vsc9959_sgi_cfg_status() argument
2109 return ocelot_read(ocelot, ANA_SG_ACCESS_CTRL); in vsc9959_sgi_cfg_status()
2112 static int vsc9959_psfp_sgi_set(struct ocelot *ocelot, in vsc9959_psfp_sgi_set() argument
2121 if (sgi->index > VSC9959_PSFP_GATE_ID_MAX) in vsc9959_psfp_sgi_set()
2122 return -EINVAL; in vsc9959_psfp_sgi_set()
2124 ocelot_write(ocelot, ANA_SG_ACCESS_CTRL_SGID(sgi->index), in vsc9959_psfp_sgi_set()
2127 if (!sgi->enable) { in vsc9959_psfp_sgi_set()
2128 ocelot_rmw(ocelot, ANA_SG_CONFIG_REG_3_INIT_GATE_STATE, in vsc9959_psfp_sgi_set()
2136 if (sgi->cycletime < VSC9959_PSFP_GATE_CYCLETIME_MIN || in vsc9959_psfp_sgi_set()
2137 sgi->cycletime > NSEC_PER_SEC) in vsc9959_psfp_sgi_set()
2138 return -EINVAL; in vsc9959_psfp_sgi_set()
2140 if (sgi->num_entries > VSC9959_PSFP_GATE_LIST_NUM) in vsc9959_psfp_sgi_set()
2141 return -EINVAL; in vsc9959_psfp_sgi_set()
2143 vsc9959_new_base_time(ocelot, sgi->basetime, sgi->cycletime, &base_ts); in vsc9959_psfp_sgi_set()
2144 ocelot_write(ocelot, base_ts.tv_nsec, ANA_SG_CONFIG_REG_1); in vsc9959_psfp_sgi_set()
2146 ocelot_write(ocelot, val, ANA_SG_CONFIG_REG_2); in vsc9959_psfp_sgi_set()
2149 ocelot_write(ocelot, in vsc9959_psfp_sgi_set()
2150 (sgi->ipv_valid ? ANA_SG_CONFIG_REG_3_IPV_VALID : 0) | in vsc9959_psfp_sgi_set()
2151 ANA_SG_CONFIG_REG_3_INIT_IPV(sgi->init_ipv) | in vsc9959_psfp_sgi_set()
2153 ANA_SG_CONFIG_REG_3_LIST_LENGTH(sgi->num_entries) | in vsc9959_psfp_sgi_set()
2158 ocelot_write(ocelot, sgi->cycletime, ANA_SG_CONFIG_REG_4); in vsc9959_psfp_sgi_set()
2160 e = sgi->entries; in vsc9959_psfp_sgi_set()
2161 for (i = 0; i < sgi->num_entries; i++) { in vsc9959_psfp_sgi_set()
2164 ocelot_write_rix(ocelot, ANA_SG_GCL_GS_CONFIG_IPS(ips) | in vsc9959_psfp_sgi_set()
2170 ocelot_write_rix(ocelot, interval_sum, ANA_SG_GCL_TI_CONFIG, i); in vsc9959_psfp_sgi_set()
2173 ocelot_rmw(ocelot, ANA_SG_ACCESS_CTRL_CONFIG_CHANGE, in vsc9959_psfp_sgi_set()
2177 return readx_poll_timeout(vsc9959_sgi_cfg_status, ocelot, val, in vsc9959_psfp_sgi_set()
2182 static int vsc9959_psfp_sgi_table_add(struct ocelot *ocelot, in vsc9959_psfp_sgi_table_add() argument
2189 psfp = &ocelot->psfp; in vsc9959_psfp_sgi_table_add()
2191 list_for_each_entry(tmp, &psfp->sgi_list, list) in vsc9959_psfp_sgi_table_add()
2192 if (tmp->index == sgi->index) { in vsc9959_psfp_sgi_table_add()
2193 refcount_inc(&tmp->refcount); in vsc9959_psfp_sgi_table_add()
2199 return -ENOMEM; in vsc9959_psfp_sgi_table_add()
2201 ret = vsc9959_psfp_sgi_set(ocelot, sgi); in vsc9959_psfp_sgi_table_add()
2207 tmp->index = sgi->index; in vsc9959_psfp_sgi_table_add()
2208 refcount_set(&tmp->refcount, 1); in vsc9959_psfp_sgi_table_add()
2209 list_add_tail(&tmp->list, &psfp->sgi_list); in vsc9959_psfp_sgi_table_add()
2214 static void vsc9959_psfp_sgi_table_del(struct ocelot *ocelot, in vsc9959_psfp_sgi_table_del() argument
2222 psfp = &ocelot->psfp; in vsc9959_psfp_sgi_table_del()
2224 list_for_each_entry_safe(tmp, n, &psfp->sgi_list, list) in vsc9959_psfp_sgi_table_del()
2225 if (tmp->index == index) { in vsc9959_psfp_sgi_table_del()
2226 z = refcount_dec_and_test(&tmp->refcount); in vsc9959_psfp_sgi_table_del()
2230 vsc9959_psfp_sgi_set(ocelot, &sgi); in vsc9959_psfp_sgi_table_del()
2231 list_del(&tmp->list); in vsc9959_psfp_sgi_table_del()
2238 static int vsc9959_psfp_filter_add(struct ocelot *ocelot, int port, in vsc9959_psfp_filter_add() argument
2241 struct netlink_ext_ack *extack = f->common.extack; in vsc9959_psfp_filter_add()
2254 psfp = &ocelot->psfp; in vsc9959_psfp_filter_add()
2262 mutex_lock(&psfp->lock); in vsc9959_psfp_filter_add()
2264 flow_action_for_each(i, a, &f->rule->action) { in vsc9959_psfp_filter_add()
2265 switch (a->id) { in vsc9959_psfp_filter_add()
2267 size = struct_size(sgi, entries, a->gate.num_entries); in vsc9959_psfp_filter_add()
2270 ret = -ENOMEM; in vsc9959_psfp_filter_add()
2274 ret = vsc9959_psfp_sgi_table_add(ocelot, sgi); in vsc9959_psfp_filter_add()
2279 sfi.sg_valid = 1; in vsc9959_psfp_filter_add()
2280 sfi.sgid = sgi->index; in vsc9959_psfp_filter_add()
2284 index = a->hw_index + VSC9959_PSFP_POLICER_BASE; in vsc9959_psfp_filter_add()
2286 ret = -EINVAL; in vsc9959_psfp_filter_add()
2290 rate = a->police.rate_bytes_ps; in vsc9959_psfp_filter_add()
2291 burst = rate * PSCHED_NS2TICKS(a->police.burst); in vsc9959_psfp_filter_add()
2296 ret = ocelot_vcap_policer_add(ocelot, index, &pol); in vsc9959_psfp_filter_add()
2300 sfi.fm_valid = 1; in vsc9959_psfp_filter_add()
2302 sfi.maxsdu = a->police.mtu; in vsc9959_psfp_filter_add()
2305 mutex_unlock(&psfp->lock); in vsc9959_psfp_filter_add()
2306 return -EOPNOTSUPP; in vsc9959_psfp_filter_add()
2314 sfi.prio_valid = (stream.prio < 0 ? 0 : 1); in vsc9959_psfp_filter_add()
2316 sfi.enable = 1; in vsc9959_psfp_filter_add()
2319 stream_entry = vsc9959_stream_table_lookup(&psfp->stream_list, &stream); in vsc9959_psfp_filter_add()
2321 if (stream_entry->ports & BIT(port)) { in vsc9959_psfp_filter_add()
2324 ret = -EEXIST; in vsc9959_psfp_filter_add()
2328 if (stream_entry->ports != BIT(stream_entry->port)) { in vsc9959_psfp_filter_add()
2331 ret = -EEXIST; in vsc9959_psfp_filter_add()
2335 stream_entry->ports |= BIT(port); in vsc9959_psfp_filter_add()
2336 stream.ports = stream_entry->ports; in vsc9959_psfp_filter_add()
2338 sfi_entry = vsc9959_psfp_sfi_table_get(&psfp->sfi_list, in vsc9959_psfp_filter_add()
2339 stream_entry->sfid); in vsc9959_psfp_filter_add()
2342 vsc9959_psfp_sfi_table_del(ocelot, stream_entry->sfid); in vsc9959_psfp_filter_add()
2344 old_sfi.portmask = stream_entry->ports; in vsc9959_psfp_filter_add()
2347 if (stream_entry->port > port) { in vsc9959_psfp_filter_add()
2348 ret = vsc9959_psfp_sfi_table_add2(ocelot, &sfi, in vsc9959_psfp_filter_add()
2350 stream_entry->dummy = true; in vsc9959_psfp_filter_add()
2352 ret = vsc9959_psfp_sfi_table_add2(ocelot, &old_sfi, in vsc9959_psfp_filter_add()
2359 stream_entry->sfid = old_sfi.index; in vsc9959_psfp_filter_add()
2361 ret = vsc9959_psfp_sfi_table_add(ocelot, &sfi); in vsc9959_psfp_filter_add()
2367 stream.sfid_valid = 1; in vsc9959_psfp_filter_add()
2368 ret = vsc9959_stream_table_add(ocelot, &psfp->stream_list, in vsc9959_psfp_filter_add()
2371 vsc9959_psfp_sfi_table_del(ocelot, stream.sfid); in vsc9959_psfp_filter_add()
2375 mutex_unlock(&psfp->lock); in vsc9959_psfp_filter_add()
2381 vsc9959_psfp_sgi_table_del(ocelot, sfi.sgid); in vsc9959_psfp_filter_add()
2384 ocelot_vcap_policer_del(ocelot, sfi.fmid); in vsc9959_psfp_filter_add()
2386 mutex_unlock(&psfp->lock); in vsc9959_psfp_filter_add()
2391 static int vsc9959_psfp_filter_del(struct ocelot *ocelot, in vsc9959_psfp_filter_del() argument
2395 struct ocelot_psfp_list *psfp = &ocelot->psfp; in vsc9959_psfp_filter_del()
2398 mutex_lock(&psfp->lock); in vsc9959_psfp_filter_del()
2400 stream = vsc9959_stream_table_get(&psfp->stream_list, f->cookie); in vsc9959_psfp_filter_del()
2402 mutex_unlock(&psfp->lock); in vsc9959_psfp_filter_del()
2403 return -ENOMEM; in vsc9959_psfp_filter_del()
2406 sfi = vsc9959_psfp_sfi_table_get(&psfp->sfi_list, stream->sfid); in vsc9959_psfp_filter_del()
2408 mutex_unlock(&psfp->lock); in vsc9959_psfp_filter_del()
2409 return -ENOMEM; in vsc9959_psfp_filter_del()
2412 if (sfi->sg_valid) in vsc9959_psfp_filter_del()
2413 vsc9959_psfp_sgi_table_del(ocelot, sfi->sgid); in vsc9959_psfp_filter_del()
2415 if (sfi->fm_valid) in vsc9959_psfp_filter_del()
2416 ocelot_vcap_policer_del(ocelot, sfi->fmid); in vsc9959_psfp_filter_del()
2418 vsc9959_psfp_sfi_table_del(ocelot, stream->sfid); in vsc9959_psfp_filter_del()
2422 stream->sfid_valid = 0; in vsc9959_psfp_filter_del()
2423 vsc9959_stream_table_del(ocelot, stream); in vsc9959_psfp_filter_del()
2425 stream_entry = vsc9959_stream_table_lookup(&psfp->stream_list, &tmp); in vsc9959_psfp_filter_del()
2427 stream_entry->ports = BIT(stream_entry->port); in vsc9959_psfp_filter_del()
2428 if (stream_entry->dummy) { in vsc9959_psfp_filter_del()
2429 stream_entry->dummy = false; in vsc9959_psfp_filter_del()
2430 vsc9959_mact_stream_set(ocelot, stream_entry, NULL); in vsc9959_psfp_filter_del()
2432 vsc9959_psfp_sfidmask_set(ocelot, stream_entry->sfid, in vsc9959_psfp_filter_del()
2433 stream_entry->ports); in vsc9959_psfp_filter_del()
2436 mutex_unlock(&psfp->lock); in vsc9959_psfp_filter_del()
2441 static void vsc9959_update_sfid_stats(struct ocelot *ocelot, in vsc9959_update_sfid_stats() argument
2444 struct felix_stream_filter_counters *s = &sfi->stats; in vsc9959_update_sfid_stats()
2446 u32 sfid = sfi->index; in vsc9959_update_sfid_stats()
2448 lockdep_assert_held(&ocelot->stat_view_lock); in vsc9959_update_sfid_stats()
2450 ocelot_rmw(ocelot, SYS_STAT_CFG_STAT_VIEW(sfid), in vsc9959_update_sfid_stats()
2454 match = ocelot_read(ocelot, SYS_COUNT_SF_MATCHING_FRAMES); in vsc9959_update_sfid_stats()
2455 not_pass_gate = ocelot_read(ocelot, SYS_COUNT_SF_NOT_PASSING_FRAMES); in vsc9959_update_sfid_stats()
2456 not_pass_sdu = ocelot_read(ocelot, SYS_COUNT_SF_NOT_PASSING_SDU); in vsc9959_update_sfid_stats()
2457 red = ocelot_read(ocelot, SYS_COUNT_SF_RED_FRAMES); in vsc9959_update_sfid_stats()
2460 ocelot_write(ocelot, in vsc9959_update_sfid_stats()
2465 s->match += match; in vsc9959_update_sfid_stats()
2466 s->not_pass_gate += not_pass_gate; in vsc9959_update_sfid_stats()
2467 s->not_pass_sdu += not_pass_sdu; in vsc9959_update_sfid_stats()
2468 s->red += red; in vsc9959_update_sfid_stats()
2471 /* Caller must hold &ocelot->stat_view_lock */
2472 static void vsc9959_update_stats(struct ocelot *ocelot) in vsc9959_update_stats() argument
2474 struct ocelot_psfp_list *psfp = &ocelot->psfp; in vsc9959_update_stats()
2477 mutex_lock(&psfp->lock); in vsc9959_update_stats()
2479 list_for_each_entry(sfi, &psfp->sfi_list, list) in vsc9959_update_stats()
2480 vsc9959_update_sfid_stats(ocelot, sfi); in vsc9959_update_stats()
2482 mutex_unlock(&psfp->lock); in vsc9959_update_stats()
2485 static int vsc9959_psfp_stats_get(struct ocelot *ocelot, in vsc9959_psfp_stats_get() argument
2489 struct ocelot_psfp_list *psfp = &ocelot->psfp; in vsc9959_psfp_stats_get()
2494 stream = vsc9959_stream_table_get(&psfp->stream_list, f->cookie); in vsc9959_psfp_stats_get()
2496 return -ENOMEM; in vsc9959_psfp_stats_get()
2498 sfi = vsc9959_psfp_sfi_table_get(&psfp->sfi_list, stream->sfid); in vsc9959_psfp_stats_get()
2500 return -EINVAL; in vsc9959_psfp_stats_get()
2502 mutex_lock(&ocelot->stat_view_lock); in vsc9959_psfp_stats_get()
2504 vsc9959_update_sfid_stats(ocelot, sfi); in vsc9959_psfp_stats_get()
2506 s = &sfi->stats; in vsc9959_psfp_stats_get()
2507 stats->pkts = s->match; in vsc9959_psfp_stats_get()
2508 stats->drops = s->not_pass_gate + s->not_pass_sdu + s->red; in vsc9959_psfp_stats_get()
2512 mutex_unlock(&ocelot->stat_view_lock); in vsc9959_psfp_stats_get()
2517 static void vsc9959_psfp_init(struct ocelot *ocelot) in vsc9959_psfp_init() argument
2519 struct ocelot_psfp_list *psfp = &ocelot->psfp; in vsc9959_psfp_init()
2521 INIT_LIST_HEAD(&psfp->stream_list); in vsc9959_psfp_init()
2522 INIT_LIST_HEAD(&psfp->sfi_list); in vsc9959_psfp_init()
2523 INIT_LIST_HEAD(&psfp->sgi_list); in vsc9959_psfp_init()
2524 mutex_init(&psfp->lock); in vsc9959_psfp_init()
2527 /* When using cut-through forwarding and the egress port runs at a higher data
2530 * The Felix switch implementation of cut-through forwarding does not check in
2532 * list of ports that have cut-through forwarding enabled on egress to only be
2536 static void vsc9959_cut_through_fwd(struct ocelot *ocelot) in vsc9959_cut_through_fwd() argument
2538 struct felix *felix = ocelot_to_felix(ocelot); in vsc9959_cut_through_fwd()
2539 struct dsa_switch *ds = felix->ds; in vsc9959_cut_through_fwd()
2542 lockdep_assert_held(&ocelot->fwd_domain_lock); in vsc9959_cut_through_fwd()
2544 for (port = 0; port < ocelot->num_phys_ports; port++) { in vsc9959_cut_through_fwd()
2545 struct ocelot_port *ocelot_port = ocelot->ports[port]; in vsc9959_cut_through_fwd()
2546 struct ocelot_mm_state *mm = &ocelot->mm[port]; in vsc9959_cut_through_fwd()
2547 int min_speed = ocelot_port->speed; in vsc9959_cut_through_fwd()
2551 /* Disable cut-through on ports that are down */ in vsc9959_cut_through_fwd()
2552 if (ocelot_port->speed <= 0) in vsc9959_cut_through_fwd()
2556 /* Ocelot switches forward from the NPI port towards in vsc9959_cut_through_fwd()
2562 mask = ocelot_get_bridge_fwd_mask(ocelot, port); in vsc9959_cut_through_fwd()
2564 if (ocelot->npi >= 0) in vsc9959_cut_through_fwd()
2565 mask |= BIT(ocelot->npi); in vsc9959_cut_through_fwd()
2567 mask |= ocelot_port_assigned_dsa_8021q_cpu_mask(ocelot, in vsc9959_cut_through_fwd()
2574 for_each_set_bit(other_port, &mask, ocelot->num_phys_ports) { in vsc9959_cut_through_fwd()
2577 other_ocelot_port = ocelot->ports[other_port]; in vsc9959_cut_through_fwd()
2578 if (other_ocelot_port->speed <= 0) in vsc9959_cut_through_fwd()
2581 if (min_speed > other_ocelot_port->speed) in vsc9959_cut_through_fwd()
2582 min_speed = other_ocelot_port->speed; in vsc9959_cut_through_fwd()
2585 /* Enable cut-through forwarding for all traffic classes that in vsc9959_cut_through_fwd()
2587 * bypassed in cut-through mode. Also exclude preemptible in vsc9959_cut_through_fwd()
2589 * reason, if sent as cut-through. in vsc9959_cut_through_fwd()
2591 if (ocelot_port->speed == min_speed) { in vsc9959_cut_through_fwd()
2592 val = GENMASK(7, 0) & ~mm->active_preemptible_tcs; in vsc9959_cut_through_fwd()
2595 if (vsc9959_port_qmaxsdu_get(ocelot, port, tc)) in vsc9959_cut_through_fwd()
2600 tmp = ocelot_read_rix(ocelot, ANA_CUT_THRU_CFG, port); in vsc9959_cut_through_fwd()
2604 dev_dbg(ocelot->dev, in vsc9959_cut_through_fwd()
2605 "port %d fwd mask 0x%lx speed %d min_speed %d, %s cut-through forwarding on TC mask 0x%x\n", in vsc9959_cut_through_fwd()
2606 port, mask, ocelot_port->speed, min_speed, in vsc9959_cut_through_fwd()
2609 ocelot_write_rix(ocelot, val, ANA_CUT_THRU_CFG, port); in vsc9959_cut_through_fwd()
2660 struct ocelot *ocelot = (struct ocelot *)data; in felix_irq_handler() local
2662 ocelot_get_txtstamp(ocelot); in felix_irq_handler()
2663 ocelot_mm_irq(ocelot); in felix_irq_handler()
2672 struct ocelot *ocelot; in felix_pci_probe() local
2676 if (pdev->dev.of_node && !of_device_is_available(pdev->dev.of_node)) { in felix_pci_probe()
2677 dev_info(&pdev->dev, "device is disabled, skipping\n"); in felix_pci_probe()
2678 return -ENODEV; in felix_pci_probe()
2683 dev_err(&pdev->dev, "device enable failed\n"); in felix_pci_probe()
2689 err = -ENOMEM; in felix_pci_probe()
2690 dev_err(&pdev->dev, "Failed to allocate driver memory\n"); in felix_pci_probe()
2695 ocelot = &felix->ocelot; in felix_pci_probe()
2696 ocelot->dev = &pdev->dev; in felix_pci_probe()
2697 ocelot->num_flooding_pgids = OCELOT_NUM_TC; in felix_pci_probe()
2698 felix->info = &felix_info_vsc9959; in felix_pci_probe()
2699 felix->switch_base = pci_resource_start(pdev, VSC9959_SWITCH_PCI_BAR); in felix_pci_probe()
2703 err = devm_request_threaded_irq(&pdev->dev, pdev->irq, NULL, in felix_pci_probe()
2705 "felix-intb", ocelot); in felix_pci_probe()
2707 dev_err(&pdev->dev, "Failed to request irq\n"); in felix_pci_probe()
2711 ocelot->ptp = 1; in felix_pci_probe()
2712 ocelot->mm_supported = true; in felix_pci_probe()
2716 err = -ENOMEM; in felix_pci_probe()
2717 dev_err(&pdev->dev, "Failed to allocate DSA switch\n"); in felix_pci_probe()
2721 ds->dev = &pdev->dev; in felix_pci_probe()
2722 ds->num_ports = felix->info->num_ports; in felix_pci_probe()
2723 ds->num_tx_queues = felix->info->num_tx_queues; in felix_pci_probe()
2724 ds->ops = &felix_switch_ops; in felix_pci_probe()
2725 ds->priv = ocelot; in felix_pci_probe()
2726 felix->ds = ds; in felix_pci_probe()
2727 felix->tag_proto = DSA_TAG_PROTO_OCELOT; in felix_pci_probe()
2731 dev_err_probe(&pdev->dev, err, "Failed to register DSA switch\n"); in felix_pci_probe()
2755 dsa_unregister_switch(felix->ds); in felix_pci_remove()
2757 kfree(felix->ds); in felix_pci_remove()
2770 dsa_switch_shutdown(felix->ds); in felix_pci_shutdown()