Lines Matching +full:burst +full:- +full:wrap

1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
3 * Copyright 2018-2019 NXP
15 #include <linux/pcs-lynx.h>
663 /* Layer-3 Information */
669 /* Layer-4 Information */
900 /* soft-reset the switch core */ in vsc9959_reset()
906 dev_err(ocelot->dev, "timeout: switch core reset\n"); in vsc9959_reset()
916 dev_err(ocelot->dev, "timeout: switch sram init\n"); in vsc9959_reset()
928 * Bit 7-0: Value to be multiplied with unit
958 struct pci_dev *pdev = to_pci_dev(ocelot->dev); 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()
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()
1109 * open gates that wrap around. We are just interested in the 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()
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()
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()
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()
1326 max_sdu -= 20; in vsc9959_tas_guard_bands_update()
1331 dev_info(ocelot->dev, in vsc9959_tas_guard_bands_update()
1345 ocelot->ops->cut_through_fwd(ocelot); in vsc9959_tas_guard_bands_update()
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()
1379 if (ocelot_port->taprio) in vsc9959_sched_speed_set()
1382 mutex_unlock(&ocelot->fwd_domain_lock); in vsc9959_sched_speed_set()
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()
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()
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()
1437 taprio_offload_free(ocelot_port->taprio); in vsc9959_qos_port_tas_set()
1438 ocelot_port->taprio = NULL; 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()
1479 /* Hardware errata - Admin config could not be overwritten if in vsc9959_qos_port_tas_set()
1486 ret = -EBUSY; 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()
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()
1525 ocelot_port->taprio = taprio_offload_get(taprio); 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()
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()
1562 /* Disable time-aware shaper */ 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()
1582 /* Re-enable time-aware shaper */ 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()
1594 int port_ix = port * 8 + cbs_qopt->queue; in vsc9959_qos_port_cbs_set()
1595 u32 rate, burst; in vsc9959_qos_port_cbs_set() local
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()
1612 rate = DIV_ROUND_UP(cbs_qopt->idleslope, 100); in vsc9959_qos_port_cbs_set()
1615 /* Burst unit is 4kB */ in vsc9959_qos_port_cbs_set()
1616 burst = DIV_ROUND_UP(cbs_qopt->hicredit, 4096); in vsc9959_qos_port_cbs_set()
1617 /* Avoid using zero burst size */ in vsc9959_qos_port_cbs_set()
1618 burst = clamp_t(u32, burst, 1, GENMASK(5, 0)); in vsc9959_qos_port_cbs_set()
1621 QSYS_CIR_CFG_CIR_BURST(burst), 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()
1663 mutex_lock(&ocelot->fwd_domain_lock); 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()
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()
1766 if (flow_rule_match_has_control_flags(rule, f->common.extack)) in vsc9959_stream_identify()
1767 return -EOPNOTSUPP; in vsc9959_stream_identify()
1773 ether_addr_copy(stream->dmac, match.key->dst); in vsc9959_stream_identify()
1774 if (!is_zero_ether_addr(match.mask->src)) in vsc9959_stream_identify()
1775 return -EOPNOTSUPP; in vsc9959_stream_identify()
1777 return -EOPNOTSUPP; in vsc9959_stream_identify()
1784 if (match.mask->vlan_priority) in vsc9959_stream_identify()
1785 stream->prio = match.key->vlan_priority; in vsc9959_stream_identify()
1787 stream->prio = -1; in vsc9959_stream_identify()
1789 if (!match.mask->vlan_id) in vsc9959_stream_identify()
1790 return -EOPNOTSUPP; in vsc9959_stream_identify()
1791 stream->vid = match.key->vlan_id; in vsc9959_stream_identify()
1793 return -EOPNOTSUPP; in vsc9959_stream_identify()
1796 stream->id = f->cookie; in vsc9959_stream_identify()
1810 ether_addr_copy(mac, stream->dmac); in vsc9959_mact_stream_set()
1811 vid = stream->vid; in vsc9959_mact_stream_set()
1820 return -EOPNOTSUPP; in vsc9959_mact_stream_set()
1823 if ((stream->sfid_valid || stream->ssid_valid) && in vsc9959_mact_stream_set()
1827 sfid = stream->sfid_valid ? stream->sfid : -1; in vsc9959_mact_stream_set()
1828 ssid = stream->ssid_valid ? stream->ssid : -1; in vsc9959_mact_stream_set()
1843 if (ether_addr_equal(tmp->dmac, stream->dmac) && in vsc9959_stream_table_lookup()
1844 tmp->vid == stream->vid) in vsc9959_stream_table_lookup()
1860 return -ENOMEM; in vsc9959_stream_table_add()
1862 if (!stream->dummy) { in vsc9959_stream_table_add()
1870 list_add_tail(&stream_entry->list, stream_list); in vsc9959_stream_table_add()
1881 if (tmp->id == id) in vsc9959_stream_table_get()
1890 if (!stream->dummy) in vsc9959_stream_table_del()
1893 list_del(&stream->list); in vsc9959_stream_table_del()
1907 if (sfi->index > VSC9959_PSFP_SFID_MAX) in vsc9959_psfp_sfi_set()
1908 return -EINVAL; in vsc9959_psfp_sfi_set()
1910 if (!sfi->enable) { in vsc9959_psfp_sfi_set()
1911 ocelot_write(ocelot, ANA_TABLES_SFIDTIDX_SFID_INDEX(sfi->index), in vsc9959_psfp_sfi_set()
1922 if (sfi->sgid > VSC9959_PSFP_GATE_ID_MAX || in vsc9959_psfp_sfi_set()
1923 sfi->fmid > VSC9959_PSFP_POLICER_MAX) in vsc9959_psfp_sfi_set()
1924 return -EINVAL; in vsc9959_psfp_sfi_set()
1927 (sfi->sg_valid ? ANA_TABLES_SFIDTIDX_SGID_VALID : 0) | in vsc9959_psfp_sfi_set()
1928 ANA_TABLES_SFIDTIDX_SGID(sfi->sgid) | in vsc9959_psfp_sfi_set()
1929 (sfi->fm_valid ? ANA_TABLES_SFIDTIDX_POL_ENA : 0) | in vsc9959_psfp_sfi_set()
1930 ANA_TABLES_SFIDTIDX_POL_IDX(sfi->fmid) | in vsc9959_psfp_sfi_set()
1931 ANA_TABLES_SFIDTIDX_SFID_INDEX(sfi->index), in vsc9959_psfp_sfi_set()
1935 (sfi->prio_valid ? ANA_TABLES_SFIDACCESS_IGR_PRIO_MATCH_ENA : 0) | in vsc9959_psfp_sfi_set()
1936 ANA_TABLES_SFIDACCESS_IGR_PRIO(sfi->prio) | in vsc9959_psfp_sfi_set()
1937 ANA_TABLES_SFIDACCESS_MAX_SDU_LEN(sfi->maxsdu) | in vsc9959_psfp_sfi_set()
1979 return -ENOMEM; in vsc9959_psfp_sfi_list_add()
1981 refcount_set(&sfi_entry->refcount, 1); in vsc9959_psfp_sfi_list_add()
1989 vsc9959_psfp_sfidmask_set(ocelot, sfi->index, sfi->portmask); in vsc9959_psfp_sfi_list_add()
1991 list_add(&sfi_entry->list, pos); in vsc9959_psfp_sfi_list_add()
2004 psfp = &ocelot->psfp; in vsc9959_psfp_sfi_table_add()
2005 last = &psfp->sfi_list; in vsc9959_psfp_sfi_table_add()
2007 list_for_each_safe(pos, q, &psfp->sfi_list) { in vsc9959_psfp_sfi_table_add()
2009 if (sfi->sg_valid == tmp->sg_valid && in vsc9959_psfp_sfi_table_add()
2010 sfi->fm_valid == tmp->fm_valid && in vsc9959_psfp_sfi_table_add()
2011 sfi->portmask == tmp->portmask && in vsc9959_psfp_sfi_table_add()
2012 tmp->sgid == sfi->sgid && in vsc9959_psfp_sfi_table_add()
2013 tmp->fmid == sfi->fmid) { in vsc9959_psfp_sfi_table_add()
2014 sfi->index = tmp->index; in vsc9959_psfp_sfi_table_add()
2015 refcount_inc(&tmp->refcount); in vsc9959_psfp_sfi_table_add()
2019 if (tmp->index == insert) { in vsc9959_psfp_sfi_table_add()
2024 sfi->index = insert; in vsc9959_psfp_sfi_table_add()
2039 psfp = &ocelot->psfp; in vsc9959_psfp_sfi_table_add2()
2040 last = &psfp->sfi_list; in vsc9959_psfp_sfi_table_add2()
2042 list_for_each_safe(pos, q, &psfp->sfi_list) { in vsc9959_psfp_sfi_table_add2()
2045 if (tmp->index >= insert + 2) in vsc9959_psfp_sfi_table_add2()
2048 insert = tmp->index + 1; in vsc9959_psfp_sfi_table_add2()
2051 sfi->index = insert; in vsc9959_psfp_sfi_table_add2()
2057 sfi2->index = insert + 1; in vsc9959_psfp_sfi_table_add2()
2059 return vsc9959_psfp_sfi_list_add(ocelot, sfi2, last->next); in vsc9959_psfp_sfi_table_add2()
2068 if (tmp->index == index) in vsc9959_psfp_sfi_table_get()
2080 psfp = &ocelot->psfp; in vsc9959_psfp_sfi_table_del()
2082 list_for_each_entry_safe(tmp, n, &psfp->sfi_list, list) in vsc9959_psfp_sfi_table_del()
2083 if (tmp->index == index) { in vsc9959_psfp_sfi_table_del()
2084 z = refcount_dec_and_test(&tmp->refcount); in vsc9959_psfp_sfi_table_del()
2086 tmp->enable = 0; in vsc9959_psfp_sfi_table_del()
2088 list_del(&tmp->list); in vsc9959_psfp_sfi_table_del()
2098 sgi->index = entry->hw_index; in vsc9959_psfp_parse_gate()
2099 sgi->ipv_valid = (entry->gate.prio < 0) ? 0 : 1; in vsc9959_psfp_parse_gate()
2100 sgi->init_ipv = (sgi->ipv_valid) ? entry->gate.prio : 0; in vsc9959_psfp_parse_gate()
2101 sgi->basetime = entry->gate.basetime; in vsc9959_psfp_parse_gate()
2102 sgi->cycletime = entry->gate.cycletime; in vsc9959_psfp_parse_gate()
2103 sgi->num_entries = entry->gate.num_entries; in vsc9959_psfp_parse_gate()
2104 sgi->enable = 1; in vsc9959_psfp_parse_gate()
2106 memcpy(sgi->entries, entry->gate.entries, in vsc9959_psfp_parse_gate()
2107 entry->gate.num_entries * sizeof(struct action_gate_entry)); in vsc9959_psfp_parse_gate()
2124 if (sgi->index > VSC9959_PSFP_GATE_ID_MAX) in vsc9959_psfp_sgi_set()
2125 return -EINVAL; in vsc9959_psfp_sgi_set()
2127 ocelot_write(ocelot, ANA_SG_ACCESS_CTRL_SGID(sgi->index), in vsc9959_psfp_sgi_set()
2130 if (!sgi->enable) { in vsc9959_psfp_sgi_set()
2139 if (sgi->cycletime < VSC9959_PSFP_GATE_CYCLETIME_MIN || in vsc9959_psfp_sgi_set()
2140 sgi->cycletime > NSEC_PER_SEC) in vsc9959_psfp_sgi_set()
2141 return -EINVAL; in vsc9959_psfp_sgi_set()
2143 if (sgi->num_entries > VSC9959_PSFP_GATE_LIST_NUM) in vsc9959_psfp_sgi_set()
2144 return -EINVAL; in vsc9959_psfp_sgi_set()
2146 vsc9959_new_base_time(ocelot, sgi->basetime, sgi->cycletime, &base_ts); in vsc9959_psfp_sgi_set()
2153 (sgi->ipv_valid ? ANA_SG_CONFIG_REG_3_IPV_VALID : 0) | in vsc9959_psfp_sgi_set()
2154 ANA_SG_CONFIG_REG_3_INIT_IPV(sgi->init_ipv) | in vsc9959_psfp_sgi_set()
2156 ANA_SG_CONFIG_REG_3_LIST_LENGTH(sgi->num_entries) | in vsc9959_psfp_sgi_set()
2161 ocelot_write(ocelot, sgi->cycletime, ANA_SG_CONFIG_REG_4); in vsc9959_psfp_sgi_set()
2163 e = sgi->entries; in vsc9959_psfp_sgi_set()
2164 for (i = 0; i < sgi->num_entries; i++) { in vsc9959_psfp_sgi_set()
2192 psfp = &ocelot->psfp; in vsc9959_psfp_sgi_table_add()
2194 list_for_each_entry(tmp, &psfp->sgi_list, list) in vsc9959_psfp_sgi_table_add()
2195 if (tmp->index == sgi->index) { in vsc9959_psfp_sgi_table_add()
2196 refcount_inc(&tmp->refcount); in vsc9959_psfp_sgi_table_add()
2202 return -ENOMEM; in vsc9959_psfp_sgi_table_add()
2210 tmp->index = sgi->index; in vsc9959_psfp_sgi_table_add()
2211 refcount_set(&tmp->refcount, 1); in vsc9959_psfp_sgi_table_add()
2212 list_add_tail(&tmp->list, &psfp->sgi_list); in vsc9959_psfp_sgi_table_add()
2225 psfp = &ocelot->psfp; in vsc9959_psfp_sgi_table_del()
2227 list_for_each_entry_safe(tmp, n, &psfp->sgi_list, list) in vsc9959_psfp_sgi_table_del()
2228 if (tmp->index == index) { in vsc9959_psfp_sgi_table_del()
2229 z = refcount_dec_and_test(&tmp->refcount); in vsc9959_psfp_sgi_table_del()
2234 list_del(&tmp->list); in vsc9959_psfp_sgi_table_del()
2244 struct netlink_ext_ack *extack = f->common.extack; in vsc9959_psfp_filter_add()
2254 u64 rate, burst; in vsc9959_psfp_filter_add() local
2257 psfp = &ocelot->psfp; in vsc9959_psfp_filter_add()
2265 mutex_lock(&psfp->lock); in vsc9959_psfp_filter_add()
2267 flow_action_for_each(i, a, &f->rule->action) { in vsc9959_psfp_filter_add()
2268 switch (a->id) { in vsc9959_psfp_filter_add()
2270 size = struct_size(sgi, entries, a->gate.num_entries); in vsc9959_psfp_filter_add()
2273 ret = -ENOMEM; in vsc9959_psfp_filter_add()
2283 sfi.sgid = sgi->index; in vsc9959_psfp_filter_add()
2287 index = a->hw_index + VSC9959_PSFP_POLICER_BASE; in vsc9959_psfp_filter_add()
2289 ret = -EINVAL; in vsc9959_psfp_filter_add()
2293 rate = a->police.rate_bytes_ps; in vsc9959_psfp_filter_add()
2294 burst = rate * PSCHED_NS2TICKS(a->police.burst); in vsc9959_psfp_filter_add()
2296 .burst = div_u64(burst, PSCHED_TICKS_PER_SEC), in vsc9959_psfp_filter_add()
2305 sfi.maxsdu = a->police.mtu; in vsc9959_psfp_filter_add()
2308 mutex_unlock(&psfp->lock); in vsc9959_psfp_filter_add()
2309 return -EOPNOTSUPP; in vsc9959_psfp_filter_add()
2322 stream_entry = vsc9959_stream_table_lookup(&psfp->stream_list, &stream); in vsc9959_psfp_filter_add()
2324 if (stream_entry->ports & BIT(port)) { in vsc9959_psfp_filter_add()
2327 ret = -EEXIST; in vsc9959_psfp_filter_add()
2331 if (stream_entry->ports != BIT(stream_entry->port)) { in vsc9959_psfp_filter_add()
2334 ret = -EEXIST; in vsc9959_psfp_filter_add()
2338 stream_entry->ports |= BIT(port); in vsc9959_psfp_filter_add()
2339 stream.ports = stream_entry->ports; in vsc9959_psfp_filter_add()
2341 sfi_entry = vsc9959_psfp_sfi_table_get(&psfp->sfi_list, in vsc9959_psfp_filter_add()
2342 stream_entry->sfid); in vsc9959_psfp_filter_add()
2345 vsc9959_psfp_sfi_table_del(ocelot, stream_entry->sfid); in vsc9959_psfp_filter_add()
2347 old_sfi.portmask = stream_entry->ports; in vsc9959_psfp_filter_add()
2350 if (stream_entry->port > port) { in vsc9959_psfp_filter_add()
2353 stream_entry->dummy = true; in vsc9959_psfp_filter_add()
2362 stream_entry->sfid = old_sfi.index; in vsc9959_psfp_filter_add()
2371 ret = vsc9959_stream_table_add(ocelot, &psfp->stream_list, in vsc9959_psfp_filter_add()
2378 mutex_unlock(&psfp->lock); in vsc9959_psfp_filter_add()
2389 mutex_unlock(&psfp->lock); in vsc9959_psfp_filter_add()
2398 struct ocelot_psfp_list *psfp = &ocelot->psfp; in vsc9959_psfp_filter_del()
2401 mutex_lock(&psfp->lock); in vsc9959_psfp_filter_del()
2403 stream = vsc9959_stream_table_get(&psfp->stream_list, f->cookie); in vsc9959_psfp_filter_del()
2405 mutex_unlock(&psfp->lock); in vsc9959_psfp_filter_del()
2406 return -ENOMEM; in vsc9959_psfp_filter_del()
2409 sfi = vsc9959_psfp_sfi_table_get(&psfp->sfi_list, stream->sfid); in vsc9959_psfp_filter_del()
2411 mutex_unlock(&psfp->lock); in vsc9959_psfp_filter_del()
2412 return -ENOMEM; in vsc9959_psfp_filter_del()
2415 if (sfi->sg_valid) in vsc9959_psfp_filter_del()
2416 vsc9959_psfp_sgi_table_del(ocelot, sfi->sgid); in vsc9959_psfp_filter_del()
2418 if (sfi->fm_valid) in vsc9959_psfp_filter_del()
2419 ocelot_vcap_policer_del(ocelot, sfi->fmid); in vsc9959_psfp_filter_del()
2421 vsc9959_psfp_sfi_table_del(ocelot, stream->sfid); in vsc9959_psfp_filter_del()
2425 stream->sfid_valid = 0; in vsc9959_psfp_filter_del()
2428 stream_entry = vsc9959_stream_table_lookup(&psfp->stream_list, &tmp); in vsc9959_psfp_filter_del()
2430 stream_entry->ports = BIT(stream_entry->port); in vsc9959_psfp_filter_del()
2431 if (stream_entry->dummy) { in vsc9959_psfp_filter_del()
2432 stream_entry->dummy = false; in vsc9959_psfp_filter_del()
2435 vsc9959_psfp_sfidmask_set(ocelot, stream_entry->sfid, in vsc9959_psfp_filter_del()
2436 stream_entry->ports); in vsc9959_psfp_filter_del()
2439 mutex_unlock(&psfp->lock); in vsc9959_psfp_filter_del()
2447 struct felix_stream_filter_counters *s = &sfi->stats; in vsc9959_update_sfid_stats()
2449 u32 sfid = sfi->index; in vsc9959_update_sfid_stats()
2451 lockdep_assert_held(&ocelot->stat_view_lock); in vsc9959_update_sfid_stats()
2468 s->match += match; in vsc9959_update_sfid_stats()
2469 s->not_pass_gate += not_pass_gate; in vsc9959_update_sfid_stats()
2470 s->not_pass_sdu += not_pass_sdu; in vsc9959_update_sfid_stats()
2471 s->red += red; in vsc9959_update_sfid_stats()
2474 /* Caller must hold &ocelot->stat_view_lock */
2477 struct ocelot_psfp_list *psfp = &ocelot->psfp; in vsc9959_update_stats()
2480 mutex_lock(&psfp->lock); in vsc9959_update_stats()
2482 list_for_each_entry(sfi, &psfp->sfi_list, list) in vsc9959_update_stats()
2485 mutex_unlock(&psfp->lock); in vsc9959_update_stats()
2492 struct ocelot_psfp_list *psfp = &ocelot->psfp; in vsc9959_psfp_stats_get()
2497 stream = vsc9959_stream_table_get(&psfp->stream_list, f->cookie); in vsc9959_psfp_stats_get()
2499 return -ENOMEM; in vsc9959_psfp_stats_get()
2501 sfi = vsc9959_psfp_sfi_table_get(&psfp->sfi_list, stream->sfid); in vsc9959_psfp_stats_get()
2503 return -EINVAL; in vsc9959_psfp_stats_get()
2505 mutex_lock(&ocelot->stat_view_lock); in vsc9959_psfp_stats_get()
2509 s = &sfi->stats; in vsc9959_psfp_stats_get()
2510 stats->pkts = s->match; in vsc9959_psfp_stats_get()
2511 stats->drops = s->not_pass_gate + s->not_pass_sdu + s->red; in vsc9959_psfp_stats_get()
2515 mutex_unlock(&ocelot->stat_view_lock); in vsc9959_psfp_stats_get()
2522 struct ocelot_psfp_list *psfp = &ocelot->psfp; in vsc9959_psfp_init()
2524 INIT_LIST_HEAD(&psfp->stream_list); in vsc9959_psfp_init()
2525 INIT_LIST_HEAD(&psfp->sfi_list); in vsc9959_psfp_init()
2526 INIT_LIST_HEAD(&psfp->sgi_list); in vsc9959_psfp_init()
2527 mutex_init(&psfp->lock); in vsc9959_psfp_init()
2530 /* When using cut-through forwarding and the egress port runs at a higher data
2533 * The Felix switch implementation of cut-through forwarding does not check in
2535 * list of ports that have cut-through forwarding enabled on egress to only be
2542 struct dsa_switch *ds = felix->ds; in vsc9959_cut_through_fwd()
2545 lockdep_assert_held(&ocelot->fwd_domain_lock); in vsc9959_cut_through_fwd()
2547 for (port = 0; port < ocelot->num_phys_ports; port++) { in vsc9959_cut_through_fwd()
2548 struct ocelot_port *ocelot_port = ocelot->ports[port]; in vsc9959_cut_through_fwd()
2549 struct ocelot_mm_state *mm = &ocelot->mm[port]; in vsc9959_cut_through_fwd()
2550 int min_speed = ocelot_port->speed; in vsc9959_cut_through_fwd()
2554 /* Disable cut-through on ports that are down */ in vsc9959_cut_through_fwd()
2555 if (ocelot_port->speed <= 0) in vsc9959_cut_through_fwd()
2567 if (ocelot->npi >= 0) in vsc9959_cut_through_fwd()
2568 mask |= BIT(ocelot->npi); in vsc9959_cut_through_fwd()
2577 for_each_set_bit(other_port, &mask, ocelot->num_phys_ports) { in vsc9959_cut_through_fwd()
2580 other_ocelot_port = ocelot->ports[other_port]; in vsc9959_cut_through_fwd()
2581 if (other_ocelot_port->speed <= 0) in vsc9959_cut_through_fwd()
2584 if (min_speed > other_ocelot_port->speed) in vsc9959_cut_through_fwd()
2585 min_speed = other_ocelot_port->speed; in vsc9959_cut_through_fwd()
2588 /* Enable cut-through forwarding for all traffic classes that in vsc9959_cut_through_fwd()
2590 * bypassed in cut-through mode. Also exclude preemptible in vsc9959_cut_through_fwd()
2592 * reason, if sent as cut-through. in vsc9959_cut_through_fwd()
2594 if (ocelot_port->speed == min_speed) { in vsc9959_cut_through_fwd()
2595 val = GENMASK(7, 0) & ~mm->active_preemptible_tcs; in vsc9959_cut_through_fwd()
2607 dev_dbg(ocelot->dev, in vsc9959_cut_through_fwd()
2608 "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()
2609 port, mask, ocelot_port->speed, min_speed, in vsc9959_cut_through_fwd()
2631 struct pci_dev *pdev = to_pci_dev(ocelot->dev); in vsc9959_request_irq()
2633 return devm_request_threaded_irq(ocelot->dev, pdev->irq, NULL, in vsc9959_request_irq()
2635 "felix-intb", ocelot); in vsc9959_request_irq()
2683 struct device *dev = &pdev->dev; in felix_pci_probe()
2717 dsa_unregister_switch(felix->ds); in felix_pci_remove()
2729 dsa_switch_shutdown(felix->ds); in felix_pci_shutdown()