Lines Matching +full:cpsw +full:- +full:switch

1 // SPDX-License-Identifier: GPL-2.0
3 * Texas Instruments Ethernet Switch Driver
25 #include "cpsw.h"
34 int (*cpsw_slave_index)(struct cpsw_common *cpsw, struct cpsw_priv *priv);
36 void cpsw_intr_enable(struct cpsw_common *cpsw) in cpsw_intr_enable() argument
38 writel_relaxed(0xFF, &cpsw->wr_regs->tx_en); in cpsw_intr_enable()
39 writel_relaxed(0xFF, &cpsw->wr_regs->rx_en); in cpsw_intr_enable()
41 cpdma_ctlr_int_ctrl(cpsw->dma, true); in cpsw_intr_enable()
44 void cpsw_intr_disable(struct cpsw_common *cpsw) in cpsw_intr_disable() argument
46 writel_relaxed(0, &cpsw->wr_regs->tx_en); in cpsw_intr_disable()
47 writel_relaxed(0, &cpsw->wr_regs->rx_en); in cpsw_intr_disable()
49 cpdma_ctlr_int_ctrl(cpsw->dma, false); in cpsw_intr_disable()
64 ndev = xmeta->ndev; in cpsw_tx_handler()
65 ch = xmeta->ch; in cpsw_tx_handler()
69 ndev = skb->dev; in cpsw_tx_handler()
71 cpts_tx_timestamp(ndev_to_cpsw(ndev)->cpts, skb); in cpsw_tx_handler()
82 ndev->stats.tx_packets++; in cpsw_tx_handler()
83 ndev->stats.tx_bytes += len; in cpsw_tx_handler()
88 struct cpsw_common *cpsw = dev_id; in cpsw_tx_interrupt() local
90 writel(0, &cpsw->wr_regs->tx_en); in cpsw_tx_interrupt()
91 cpdma_ctlr_eoi(cpsw->dma, CPDMA_EOI_TX); in cpsw_tx_interrupt()
93 if (cpsw->quirk_irq) { in cpsw_tx_interrupt()
94 disable_irq_nosync(cpsw->irqs_table[1]); in cpsw_tx_interrupt()
95 cpsw->tx_irq_disabled = true; in cpsw_tx_interrupt()
98 napi_schedule(&cpsw->napi_tx); in cpsw_tx_interrupt()
104 struct cpsw_common *cpsw = dev_id; in cpsw_rx_interrupt() local
106 writel(0, &cpsw->wr_regs->rx_en); in cpsw_rx_interrupt()
107 cpdma_ctlr_eoi(cpsw->dma, CPDMA_EOI_RX); in cpsw_rx_interrupt()
109 if (cpsw->quirk_irq) { in cpsw_rx_interrupt()
110 disable_irq_nosync(cpsw->irqs_table[0]); in cpsw_rx_interrupt()
111 cpsw->rx_irq_disabled = true; in cpsw_rx_interrupt()
114 napi_schedule(&cpsw->napi_rx); in cpsw_rx_interrupt()
120 struct cpsw_common *cpsw = dev_id; in cpsw_misc_interrupt() local
122 writel(0, &cpsw->wr_regs->misc_en); in cpsw_misc_interrupt()
123 cpdma_ctlr_eoi(cpsw->dma, CPDMA_EOI_MISC); in cpsw_misc_interrupt()
124 cpts_misc_interrupt(cpsw->cpts); in cpsw_misc_interrupt()
125 writel(0x10, &cpsw->wr_regs->misc_en); in cpsw_misc_interrupt()
132 struct cpsw_common *cpsw = napi_to_cpsw(napi_tx); in cpsw_tx_mq_poll() local
138 ch_map = cpdma_ctrl_txchs_state(cpsw->dma); in cpsw_tx_mq_poll()
143 txv = &cpsw->txv[ch]; in cpsw_tx_mq_poll()
144 if (unlikely(txv->budget > budget - num_tx)) in cpsw_tx_mq_poll()
145 cur_budget = budget - num_tx; in cpsw_tx_mq_poll()
147 cur_budget = txv->budget; in cpsw_tx_mq_poll()
149 num_tx += cpdma_chan_process(txv->ch, cur_budget); in cpsw_tx_mq_poll()
156 writel(0xff, &cpsw->wr_regs->tx_en); in cpsw_tx_mq_poll()
164 struct cpsw_common *cpsw = napi_to_cpsw(napi_tx); in cpsw_tx_poll() local
167 num_tx = cpdma_chan_process(cpsw->txv[0].ch, budget); in cpsw_tx_poll()
170 writel(0xff, &cpsw->wr_regs->tx_en); in cpsw_tx_poll()
171 if (cpsw->tx_irq_disabled) { in cpsw_tx_poll()
172 cpsw->tx_irq_disabled = false; in cpsw_tx_poll()
173 enable_irq(cpsw->irqs_table[1]); in cpsw_tx_poll()
182 struct cpsw_common *cpsw = napi_to_cpsw(napi_rx); in cpsw_rx_mq_poll() local
188 ch_map = cpdma_ctrl_rxchs_state(cpsw->dma); in cpsw_rx_mq_poll()
193 rxv = &cpsw->rxv[ch]; in cpsw_rx_mq_poll()
194 if (unlikely(rxv->budget > budget - num_rx)) in cpsw_rx_mq_poll()
195 cur_budget = budget - num_rx; in cpsw_rx_mq_poll()
197 cur_budget = rxv->budget; in cpsw_rx_mq_poll()
199 num_rx += cpdma_chan_process(rxv->ch, cur_budget); in cpsw_rx_mq_poll()
206 writel(0xff, &cpsw->wr_regs->rx_en); in cpsw_rx_mq_poll()
214 struct cpsw_common *cpsw = napi_to_cpsw(napi_rx); in cpsw_rx_poll() local
217 num_rx = cpdma_chan_process(cpsw->rxv[0].ch, budget); in cpsw_rx_poll()
220 writel(0xff, &cpsw->wr_regs->rx_en); in cpsw_rx_poll()
221 if (cpsw->rx_irq_disabled) { in cpsw_rx_poll()
222 cpsw->rx_irq_disabled = false; in cpsw_rx_poll()
223 enable_irq(cpsw->irqs_table[0]); in cpsw_rx_poll()
232 struct cpsw_priv *priv = netdev_priv(skb->dev); in cpsw_rx_vlan_encap()
233 u32 rx_vlan_encap_hdr = *((u32 *)skb->data); in cpsw_rx_vlan_encap()
234 struct cpsw_common *cpsw = priv->cpsw; in cpsw_rx_vlan_encap() local
243 /* Ignore unknown & Priority-tagged packets*/ in cpsw_rx_vlan_encap()
256 if (!cpsw_ale_get_vlan_p0_untag(cpsw->ale, vid)) { in cpsw_rx_vlan_encap()
265 /* strip vlan tag for VLAN-tagged packet */ in cpsw_rx_vlan_encap()
267 memmove(skb->data + VLAN_HLEN, skb->data, 2 * ETH_ALEN); in cpsw_rx_vlan_encap()
274 slave_write(slave, mac_hi(priv->mac_addr), SA_HI); in cpsw_set_slave_mac()
275 slave_write(slave, mac_lo(priv->mac_addr), SA_LO); in cpsw_set_slave_mac()
287 WARN(readl_relaxed(reg) & 1, "failed to soft-reset %s\n", module); in soft_reset()
293 struct cpsw_common *cpsw = priv->cpsw; in cpsw_ndo_tx_timeout() local
297 ndev->stats.tx_errors++; in cpsw_ndo_tx_timeout()
298 cpsw_intr_disable(cpsw); in cpsw_ndo_tx_timeout()
299 for (ch = 0; ch < cpsw->tx_ch_num; ch++) { in cpsw_ndo_tx_timeout()
300 cpdma_chan_stop(cpsw->txv[ch].ch); in cpsw_ndo_tx_timeout()
301 cpdma_chan_start(cpsw->txv[ch].ch); in cpsw_ndo_tx_timeout()
304 cpsw_intr_enable(cpsw); in cpsw_ndo_tx_timeout()
309 static int cpsw_get_common_speed(struct cpsw_common *cpsw) in cpsw_get_common_speed() argument
313 for (i = 0, speed = 0; i < cpsw->data.slaves; i++) in cpsw_get_common_speed()
314 if (cpsw->slaves[i].phy && cpsw->slaves[i].phy->link) in cpsw_get_common_speed()
315 speed += cpsw->slaves[i].phy->speed; in cpsw_get_common_speed()
320 int cpsw_need_resplit(struct cpsw_common *cpsw) in cpsw_need_resplit() argument
325 /* re-split resources only in case speed was changed */ in cpsw_need_resplit()
326 speed = cpsw_get_common_speed(cpsw); in cpsw_need_resplit()
327 if (speed == cpsw->speed || !speed) in cpsw_need_resplit()
330 cpsw->speed = speed; in cpsw_need_resplit()
332 for (i = 0, rlim_ch_num = 0; i < cpsw->tx_ch_num; i++) { in cpsw_need_resplit()
333 ch_rate = cpdma_chan_get_rate(cpsw->txv[i].ch); in cpsw_need_resplit()
341 if (!rlim_ch_num || rlim_ch_num == cpsw->tx_ch_num) in cpsw_need_resplit()
347 void cpsw_split_res(struct cpsw_common *cpsw) in cpsw_split_res() argument
350 struct cpsw_vector *txv = cpsw->txv; in cpsw_split_res()
356 for (i = 0; i < cpsw->tx_ch_num; i++) { in cpsw_split_res()
365 if (cpsw->tx_ch_num == rlim_ch_num) { in cpsw_split_res()
368 ch_budget = NAPI_POLL_WEIGHT / cpsw->tx_ch_num; in cpsw_split_res()
372 max_rate = cpsw->speed * 1000; in cpsw_split_res()
384 ch_budget = (NAPI_POLL_WEIGHT - ch_budget) / in cpsw_split_res()
385 (cpsw->tx_ch_num - rlim_ch_num); in cpsw_split_res()
386 bigest_rate = (max_rate - consumed_rate) / in cpsw_split_res()
387 (cpsw->tx_ch_num - rlim_ch_num); in cpsw_split_res()
392 for (i = 0; i < cpsw->tx_ch_num; i++) { in cpsw_split_res()
406 cpdma_chan_set_weight(cpsw->txv[i].ch, ch_weight); in cpsw_split_res()
411 cpdma_chan_set_weight(cpsw->txv[i].ch, 0); in cpsw_split_res()
414 budget -= txv[i].budget; in cpsw_split_res()
422 ch_budget = budget / cpsw->rx_ch_num; in cpsw_split_res()
423 for (i = 0; i < cpsw->rx_ch_num; i++) { in cpsw_split_res()
424 cpsw->rxv[i].budget = ch_budget; in cpsw_split_res()
425 budget -= ch_budget; in cpsw_split_res()
429 cpsw->rxv[0].budget += budget; in cpsw_split_res()
432 int cpsw_init_common(struct cpsw_common *cpsw, void __iomem *ss_regs, in cpsw_init_common() argument
440 struct device *dev = cpsw->dev; in cpsw_init_common()
445 data = &cpsw->data; in cpsw_init_common()
446 cpsw->rx_ch_num = 1; in cpsw_init_common()
447 cpsw->tx_ch_num = 1; in cpsw_init_common()
449 cpsw->version = readl(&cpsw->regs->id_ver); in cpsw_init_common()
454 switch (cpsw->version) { in cpsw_init_common()
456 cpsw->host_port_regs = ss_regs + CPSW1_HOST_PORT_OFFSET; in cpsw_init_common()
458 cpsw->hw_stats = ss_regs + CPSW1_HW_STATS; in cpsw_init_common()
470 cpsw->host_port_regs = ss_regs + CPSW2_HOST_PORT_OFFSET; in cpsw_init_common()
472 cpsw->hw_stats = ss_regs + CPSW2_HW_STATS; in cpsw_init_common()
482 dev_err(dev, "unknown version 0x%08x\n", cpsw->version); in cpsw_init_common()
483 return -ENODEV; in cpsw_init_common()
486 for (i = 0; i < cpsw->data.slaves; i++) { in cpsw_init_common()
487 struct cpsw_slave *slave = &cpsw->slaves[i]; in cpsw_init_common()
488 void __iomem *regs = cpsw->regs; in cpsw_init_common()
490 slave->slave_num = i; in cpsw_init_common()
491 slave->data = &cpsw->data.slave_data[i]; in cpsw_init_common()
492 slave->regs = regs + slave_offset; in cpsw_init_common()
493 slave->port_vlan = slave->data->dual_emac_res_vlan; in cpsw_init_common()
494 slave->mac_sl = cpsw_sl_get("cpsw", dev, regs + sliver_offset); in cpsw_init_common()
495 if (IS_ERR(slave->mac_sl)) in cpsw_init_common()
496 return PTR_ERR(slave->mac_sl); in cpsw_init_common()
505 ale_params.dev_id = "cpsw"; in cpsw_init_common()
506 ale_params.bus_freq = cpsw->bus_freq_mhz * 1000000; in cpsw_init_common()
508 cpsw->ale = cpsw_ale_create(&ale_params); in cpsw_init_common()
509 if (IS_ERR(cpsw->ale)) { in cpsw_init_common()
511 return PTR_ERR(cpsw->ale); in cpsw_init_common()
521 dma_params.num_chan = data->channels; in cpsw_init_common()
524 dma_params.desc_mem_size = data->bd_ram_size; in cpsw_init_common()
528 dma_params.bus_freq_mhz = cpsw->bus_freq_mhz; in cpsw_init_common()
531 cpsw->dma = cpdma_ctlr_create(&dma_params); in cpsw_init_common()
532 if (!cpsw->dma) { in cpsw_init_common()
534 return -ENOMEM; in cpsw_init_common()
537 cpts_node = of_get_child_by_name(cpsw->dev->of_node, "cpts"); in cpsw_init_common()
539 cpts_node = cpsw->dev->of_node; in cpsw_init_common()
541 cpsw->cpts = cpts_create(cpsw->dev, cpts_regs, cpts_node, in cpsw_init_common()
543 if (IS_ERR(cpsw->cpts)) { in cpsw_init_common()
544 ret = PTR_ERR(cpsw->cpts); in cpsw_init_common()
545 cpdma_ctlr_destroy(cpsw->dma); in cpsw_init_common()
556 struct cpsw_common *cpsw = priv->cpsw; in cpsw_hwtstamp_v1() local
557 struct cpsw_slave *slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; in cpsw_hwtstamp_v1()
560 if (!priv->tx_ts_enabled && !priv->rx_ts_enabled) { in cpsw_hwtstamp_v1()
568 if (priv->tx_ts_enabled) in cpsw_hwtstamp_v1()
571 if (priv->rx_ts_enabled) in cpsw_hwtstamp_v1()
580 struct cpsw_common *cpsw = priv->cpsw; in cpsw_hwtstamp_v2() local
584 slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; in cpsw_hwtstamp_v2()
587 switch (cpsw->version) { in cpsw_hwtstamp_v2()
591 if (priv->tx_ts_enabled) in cpsw_hwtstamp_v2()
594 if (priv->rx_ts_enabled) in cpsw_hwtstamp_v2()
601 if (priv->tx_ts_enabled) in cpsw_hwtstamp_v2()
604 if (priv->rx_ts_enabled) in cpsw_hwtstamp_v2()
613 writel_relaxed(ETH_P_1588, &cpsw->regs->ts_ltype); in cpsw_hwtstamp_v2()
614 writel_relaxed(ETH_P_8021Q, &cpsw->regs->vlan_ltype); in cpsw_hwtstamp_v2()
620 struct cpsw_common *cpsw = priv->cpsw; in cpsw_hwtstamp_set() local
623 if (cpsw->version != CPSW_VERSION_1 && in cpsw_hwtstamp_set()
624 cpsw->version != CPSW_VERSION_2 && in cpsw_hwtstamp_set()
625 cpsw->version != CPSW_VERSION_3) in cpsw_hwtstamp_set()
626 return -EOPNOTSUPP; in cpsw_hwtstamp_set()
628 if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) in cpsw_hwtstamp_set()
629 return -EFAULT; in cpsw_hwtstamp_set()
632 return -ERANGE; in cpsw_hwtstamp_set()
634 switch (cfg.rx_filter) { in cpsw_hwtstamp_set()
636 priv->rx_ts_enabled = 0; in cpsw_hwtstamp_set()
643 return -ERANGE; in cpsw_hwtstamp_set()
653 priv->rx_ts_enabled = HWTSTAMP_FILTER_PTP_V2_EVENT; in cpsw_hwtstamp_set()
657 return -ERANGE; in cpsw_hwtstamp_set()
660 priv->tx_ts_enabled = cfg.tx_type == HWTSTAMP_TX_ON; in cpsw_hwtstamp_set()
662 switch (cpsw->version) { in cpsw_hwtstamp_set()
674 return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; in cpsw_hwtstamp_set()
679 struct cpsw_common *cpsw = ndev_to_cpsw(dev); in cpsw_hwtstamp_get() local
683 if (cpsw->version != CPSW_VERSION_1 && in cpsw_hwtstamp_get()
684 cpsw->version != CPSW_VERSION_2 && in cpsw_hwtstamp_get()
685 cpsw->version != CPSW_VERSION_3) in cpsw_hwtstamp_get()
686 return -EOPNOTSUPP; in cpsw_hwtstamp_get()
689 cfg.tx_type = priv->tx_ts_enabled ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; in cpsw_hwtstamp_get()
690 cfg.rx_filter = priv->rx_ts_enabled; in cpsw_hwtstamp_get()
692 return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; in cpsw_hwtstamp_get()
697 return -EOPNOTSUPP; in cpsw_hwtstamp_get()
702 return -EOPNOTSUPP; in cpsw_hwtstamp_set()
709 struct cpsw_common *cpsw = priv->cpsw; in cpsw_ndo_ioctl() local
710 int slave_no = cpsw_slave_index(cpsw, priv); in cpsw_ndo_ioctl()
714 return -EINVAL; in cpsw_ndo_ioctl()
716 phy = cpsw->slaves[slave_no].phy; in cpsw_ndo_ioctl()
719 switch (cmd) { in cpsw_ndo_ioctl()
730 return -EOPNOTSUPP; in cpsw_ndo_ioctl()
736 struct cpsw_common *cpsw = priv->cpsw; in cpsw_ndo_set_tx_maxrate() local
742 ch_rate = netdev_get_tx_queue(ndev, queue)->tx_maxrate; in cpsw_ndo_set_tx_maxrate()
747 min_rate = cpdma_chan_get_min_rate(cpsw->dma); in cpsw_ndo_set_tx_maxrate()
749 dev_err(priv->dev, "The channel rate cannot be less than %dMbps", in cpsw_ndo_set_tx_maxrate()
751 return -EINVAL; in cpsw_ndo_set_tx_maxrate()
754 if (rate > cpsw->speed) { in cpsw_ndo_set_tx_maxrate()
755 dev_err(priv->dev, "The channel rate cannot be more than 2Gbps"); in cpsw_ndo_set_tx_maxrate()
756 return -EINVAL; in cpsw_ndo_set_tx_maxrate()
759 ret = pm_runtime_resume_and_get(cpsw->dev); in cpsw_ndo_set_tx_maxrate()
763 ret = cpdma_chan_set_rate(cpsw->txv[queue].ch, ch_rate); in cpsw_ndo_set_tx_maxrate()
764 pm_runtime_put(cpsw->dev); in cpsw_ndo_set_tx_maxrate()
770 for (i = 0; i < cpsw->data.slaves; i++) { in cpsw_ndo_set_tx_maxrate()
771 slave = &cpsw->slaves[i]; in cpsw_ndo_set_tx_maxrate()
772 if (!slave->ndev) in cpsw_ndo_set_tx_maxrate()
775 netdev_get_tx_queue(slave->ndev, queue)->tx_maxrate = rate; in cpsw_ndo_set_tx_maxrate()
778 cpsw_split_res(cpsw); in cpsw_ndo_set_tx_maxrate()
784 if (tc == num_tc - 1) in cpsw_tc_to_fifo()
787 return CPSW_FIFO_SHAPERS_NUM - tc; in cpsw_tc_to_fifo()
792 struct cpsw_common *cpsw = priv->cpsw; in cpsw_shp_is_off() local
796 val = readl_relaxed(&cpsw->regs->ptype); in cpsw_shp_is_off()
798 slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; in cpsw_shp_is_off()
799 shift = CPSW_FIFO_SHAPE_EN_SHIFT + 3 * slave->slave_num; in cpsw_shp_is_off()
808 struct cpsw_common *cpsw = priv->cpsw; in cpsw_fifo_shp_on() local
812 val = readl_relaxed(&cpsw->regs->ptype); in cpsw_fifo_shp_on()
814 slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; in cpsw_fifo_shp_on()
815 shift = CPSW_FIFO_SHAPE_EN_SHIFT + 3 * slave->slave_num; in cpsw_fifo_shp_on()
816 mask = (1 << --fifo) << shift; in cpsw_fifo_shp_on()
819 writel_relaxed(val, &cpsw->regs->ptype); in cpsw_fifo_shp_on()
824 struct cpsw_common *cpsw = priv->cpsw; in cpsw_set_fifo_bw() local
829 if (bw > priv->shp_cfg_speed * 1000) in cpsw_set_fifo_bw()
835 slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; in cpsw_set_fifo_bw()
837 for (i = CPSW_FIFO_SHAPERS_NUM; i > 0; i--) { in cpsw_set_fifo_bw()
839 if (i >= fifo || !priv->fifo_bw[i]) in cpsw_set_fifo_bw()
842 dev_warn(priv->dev, "Prev FIFO%d is shaped", i); in cpsw_set_fifo_bw()
846 if (!priv->fifo_bw[i] && i > fifo) { in cpsw_set_fifo_bw()
847 dev_err(priv->dev, "Upper FIFO%d is not shaped", i); in cpsw_set_fifo_bw()
848 return -EINVAL; in cpsw_set_fifo_bw()
851 shift = (i - 1) * 8; in cpsw_set_fifo_bw()
854 val = DIV_ROUND_UP(bw, priv->shp_cfg_speed * 10); in cpsw_set_fifo_bw()
863 if (priv->fifo_bw[i]) in cpsw_set_fifo_bw()
871 priv->fifo_bw[fifo] = bw; in cpsw_set_fifo_bw()
873 dev_warn(priv->dev, "set FIFO%d bw = %d\n", fifo, in cpsw_set_fifo_bw()
874 DIV_ROUND_CLOSEST(val * priv->shp_cfg_speed, 100)); in cpsw_set_fifo_bw()
878 dev_err(priv->dev, "Bandwidth doesn't fit in tc configuration"); in cpsw_set_fifo_bw()
879 return -EINVAL; in cpsw_set_fifo_bw()
884 struct cpsw_common *cpsw = priv->cpsw; in cpsw_set_fifo_rlimit() local
893 slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; in cpsw_set_fifo_rlimit()
894 tx_in_ctl_rg = cpsw->version == CPSW_VERSION_1 ? in cpsw_set_fifo_rlimit()
912 priv->shp_cfg_speed = 0; in cpsw_set_fifo_rlimit()
928 * class A - prio 3
929 * class B - prio 2
936 struct cpsw_common *cpsw = priv->cpsw; in cpsw_set_cbs() local
942 tc = netdev_txq_to_tc(priv->ndev, qopt->queue); in cpsw_set_cbs()
948 fifo = cpsw_tc_to_fifo(tc, ndev->num_tc); in cpsw_set_cbs()
950 dev_err(priv->dev, "Last tc%d can't be rate limited", tc); in cpsw_set_cbs()
951 return -EINVAL; in cpsw_set_cbs()
955 if (!qopt->enable && !priv->fifo_bw[fifo]) in cpsw_set_cbs()
959 slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; in cpsw_set_cbs()
960 if (slave->phy && slave->phy->link) { in cpsw_set_cbs()
961 if (priv->shp_cfg_speed && in cpsw_set_cbs()
962 priv->shp_cfg_speed != slave->phy->speed) in cpsw_set_cbs()
963 prev_speed = priv->shp_cfg_speed; in cpsw_set_cbs()
965 priv->shp_cfg_speed = slave->phy->speed; in cpsw_set_cbs()
968 if (!priv->shp_cfg_speed) { in cpsw_set_cbs()
969 dev_err(priv->dev, "Link speed is not known"); in cpsw_set_cbs()
970 return -1; in cpsw_set_cbs()
973 ret = pm_runtime_resume_and_get(cpsw->dev); in cpsw_set_cbs()
977 bw = qopt->enable ? qopt->idleslope : 0; in cpsw_set_cbs()
980 priv->shp_cfg_speed = prev_speed; in cpsw_set_cbs()
985 dev_warn(priv->dev, in cpsw_set_cbs()
988 pm_runtime_put_sync(cpsw->dev); in cpsw_set_cbs()
996 struct cpsw_common *cpsw = priv->cpsw; in cpsw_set_mqprio() local
1002 num_tc = mqprio->qopt.num_tc; in cpsw_set_mqprio()
1004 return -EINVAL; in cpsw_set_mqprio()
1006 if (mqprio->mode != TC_MQPRIO_MODE_DCB) in cpsw_set_mqprio()
1007 return -EINVAL; in cpsw_set_mqprio()
1009 ret = pm_runtime_resume_and_get(cpsw->dev); in cpsw_set_mqprio()
1015 tc = mqprio->qopt.prio_tc_map[i]; in cpsw_set_mqprio()
1022 count = mqprio->qopt.count[i]; in cpsw_set_mqprio()
1023 offset = mqprio->qopt.offset[i]; in cpsw_set_mqprio()
1028 if (!mqprio->qopt.hw) { in cpsw_set_mqprio()
1034 priv->mqprio_hw = mqprio->qopt.hw; in cpsw_set_mqprio()
1036 offset = cpsw->version == CPSW_VERSION_1 ? in cpsw_set_mqprio()
1039 slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; in cpsw_set_mqprio()
1042 pm_runtime_put_sync(cpsw->dev); in cpsw_set_mqprio()
1052 switch (type) { in cpsw_ndo_setup_tc()
1063 return -EOPNOTSUPP; in cpsw_ndo_setup_tc()
1071 for (fifo = CPSW_FIFO_SHAPERS_NUM; fifo > 0; fifo--) { in cpsw_cbs_resume()
1072 bw = priv->fifo_bw[fifo]; in cpsw_cbs_resume()
1082 struct cpsw_common *cpsw = priv->cpsw; in cpsw_mqprio_resume() local
1087 if (!priv->mqprio_hw) in cpsw_mqprio_resume()
1091 tc = netdev_get_prio_tc_map(priv->ndev, i); in cpsw_mqprio_resume()
1092 fifo = CPSW_FIFO_SHAPERS_NUM - tc; in cpsw_mqprio_resume()
1096 tx_prio_rg = cpsw->version == CPSW_VERSION_1 ? in cpsw_mqprio_resume()
1104 struct cpsw_common *cpsw = priv->cpsw; in cpsw_fill_rx_channels() local
1112 for (ch = 0; ch < cpsw->rx_ch_num; ch++) { in cpsw_fill_rx_channels()
1113 pool = cpsw->page_pool[ch]; in cpsw_fill_rx_channels()
1114 ch_buf_num = cpdma_chan_get_rx_buf_num(cpsw->rxv[ch].ch); in cpsw_fill_rx_channels()
1119 return -ENOMEM; in cpsw_fill_rx_channels()
1123 xmeta->ndev = priv->ndev; in cpsw_fill_rx_channels()
1124 xmeta->ch = ch; in cpsw_fill_rx_channels()
1127 ret = cpdma_chan_idle_submit_mapped(cpsw->rxv[ch].ch, in cpsw_fill_rx_channels()
1129 cpsw->rx_packet_max, in cpsw_fill_rx_channels()
1147 static struct page_pool *cpsw_create_page_pool(struct cpsw_common *cpsw, in cpsw_create_page_pool() argument
1158 pp_params.dev = cpsw->dev; in cpsw_create_page_pool()
1162 dev_err(cpsw->dev, "cannot create rx page pool\n"); in cpsw_create_page_pool()
1167 static int cpsw_create_rx_pool(struct cpsw_common *cpsw, int ch) in cpsw_create_rx_pool() argument
1172 pool_size = cpdma_chan_get_rx_buf_num(cpsw->rxv[ch].ch); in cpsw_create_rx_pool()
1173 pool = cpsw_create_page_pool(cpsw, pool_size); in cpsw_create_rx_pool()
1177 cpsw->page_pool[ch] = pool; in cpsw_create_rx_pool()
1184 struct cpsw_common *cpsw = priv->cpsw; in cpsw_ndev_create_xdp_rxq() local
1189 pool = cpsw->page_pool[ch]; in cpsw_ndev_create_xdp_rxq()
1190 rxq = &priv->xdp_rxq[ch]; in cpsw_ndev_create_xdp_rxq()
1192 ret = xdp_rxq_info_reg(rxq, priv->ndev, ch, 0); in cpsw_ndev_create_xdp_rxq()
1205 struct xdp_rxq_info *rxq = &priv->xdp_rxq[ch]; in cpsw_ndev_destroy_xdp_rxq()
1213 void cpsw_destroy_xdp_rxqs(struct cpsw_common *cpsw) in cpsw_destroy_xdp_rxqs() argument
1218 for (ch = 0; ch < cpsw->rx_ch_num; ch++) { in cpsw_destroy_xdp_rxqs()
1219 for (i = 0; i < cpsw->data.slaves; i++) { in cpsw_destroy_xdp_rxqs()
1220 ndev = cpsw->slaves[i].ndev; in cpsw_destroy_xdp_rxqs()
1227 page_pool_destroy(cpsw->page_pool[ch]); in cpsw_destroy_xdp_rxqs()
1228 cpsw->page_pool[ch] = NULL; in cpsw_destroy_xdp_rxqs()
1232 int cpsw_create_xdp_rxqs(struct cpsw_common *cpsw) in cpsw_create_xdp_rxqs() argument
1237 for (ch = 0; ch < cpsw->rx_ch_num; ch++) { in cpsw_create_xdp_rxqs()
1238 ret = cpsw_create_rx_pool(cpsw, ch); in cpsw_create_xdp_rxqs()
1245 for (i = 0; i < cpsw->data.slaves; i++) { in cpsw_create_xdp_rxqs()
1246 ndev = cpsw->slaves[i].ndev; in cpsw_create_xdp_rxqs()
1259 cpsw_destroy_xdp_rxqs(cpsw); in cpsw_create_xdp_rxqs()
1266 struct bpf_prog *prog = bpf->prog; in cpsw_xdp_prog_setup()
1268 if (!priv->xdpi.prog && !prog) in cpsw_xdp_prog_setup()
1271 WRITE_ONCE(priv->xdp_prog, prog); in cpsw_xdp_prog_setup()
1273 xdp_attachment_setup(&priv->xdpi, bpf); in cpsw_xdp_prog_setup()
1282 switch (bpf->command) { in cpsw_ndo_bpf()
1287 return -EINVAL; in cpsw_ndo_bpf()
1294 struct cpsw_common *cpsw = priv->cpsw; in cpsw_xdp_tx_frame() local
1301 xmeta->ndev = priv->ndev; in cpsw_xdp_tx_frame()
1302 xmeta->ch = 0; in cpsw_xdp_tx_frame()
1303 txch = cpsw->txv[0].ch; in cpsw_xdp_tx_frame()
1307 dma += xdpf->headroom + sizeof(struct xdp_frame); in cpsw_xdp_tx_frame()
1309 dma, xdpf->len, port); in cpsw_xdp_tx_frame()
1311 if (sizeof(*xmeta) > xdpf->headroom) in cpsw_xdp_tx_frame()
1312 return -EINVAL; in cpsw_xdp_tx_frame()
1315 xdpf->data, xdpf->len, port); in cpsw_xdp_tx_frame()
1319 priv->ndev->stats.tx_dropped++; in cpsw_xdp_tx_frame()
1327 struct cpsw_common *cpsw = priv->cpsw; in cpsw_run_xdp() local
1328 struct net_device *ndev = priv->ndev; in cpsw_run_xdp()
1334 prog = READ_ONCE(priv->xdp_prog); in cpsw_run_xdp()
1340 *len = xdp->data_end - xdp->data; in cpsw_run_xdp()
1342 switch (act) { in cpsw_run_xdp()
1372 ndev->stats.rx_bytes += *len; in cpsw_run_xdp()
1373 ndev->stats.rx_packets++; in cpsw_run_xdp()
1377 ndev->stats.rx_bytes += *len; in cpsw_run_xdp()
1378 ndev->stats.rx_packets++; in cpsw_run_xdp()
1382 page_pool_recycle_direct(cpsw->page_pool[ch], page); in cpsw_run_xdp()
1392 struct flow_dissector *dissector = rule->match.dissector; in cpsw_qos_clsflower_add_policer()
1398 if (dissector->used_keys & in cpsw_qos_clsflower_add_policer()
1404 return -EOPNOTSUPP; in cpsw_qos_clsflower_add_policer()
1408 return -EOPNOTSUPP; in cpsw_qos_clsflower_add_policer()
1412 return -EOPNOTSUPP; in cpsw_qos_clsflower_add_policer()
1417 if (!is_zero_ether_addr(match.mask->src)) { in cpsw_qos_clsflower_add_policer()
1420 return -EOPNOTSUPP; in cpsw_qos_clsflower_add_policer()
1423 port_id = cpsw_slave_index(priv->cpsw, priv) + 1; in cpsw_qos_clsflower_add_policer()
1425 if (is_broadcast_ether_addr(match.key->dst) && in cpsw_qos_clsflower_add_policer()
1426 is_broadcast_ether_addr(match.mask->dst)) { in cpsw_qos_clsflower_add_policer()
1427 ret = cpsw_ale_rx_ratelimit_bc(priv->cpsw->ale, port_id, rate_pkt_ps); in cpsw_qos_clsflower_add_policer()
1431 priv->ale_bc_ratelimit.cookie = cls->cookie; in cpsw_qos_clsflower_add_policer()
1432 priv->ale_bc_ratelimit.rate_packet_ps = rate_pkt_ps; in cpsw_qos_clsflower_add_policer()
1433 } else if (ether_addr_equal_unaligned(match.key->dst, mc_mac) && in cpsw_qos_clsflower_add_policer()
1434 ether_addr_equal_unaligned(match.mask->dst, mc_mac)) { in cpsw_qos_clsflower_add_policer()
1435 ret = cpsw_ale_rx_ratelimit_mc(priv->cpsw->ale, port_id, rate_pkt_ps); in cpsw_qos_clsflower_add_policer()
1439 priv->ale_mc_ratelimit.cookie = cls->cookie; in cpsw_qos_clsflower_add_policer()
1440 priv->ale_mc_ratelimit.rate_packet_ps = rate_pkt_ps; in cpsw_qos_clsflower_add_policer()
1443 return -EOPNOTSUPP; in cpsw_qos_clsflower_add_policer()
1453 if (act->police.exceed.act_id != FLOW_ACTION_DROP) { in cpsw_qos_clsflower_policer_validate()
1456 return -EOPNOTSUPP; in cpsw_qos_clsflower_policer_validate()
1459 if (act->police.notexceed.act_id != FLOW_ACTION_PIPE && in cpsw_qos_clsflower_policer_validate()
1460 act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) { in cpsw_qos_clsflower_policer_validate()
1463 return -EOPNOTSUPP; in cpsw_qos_clsflower_policer_validate()
1466 if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT && in cpsw_qos_clsflower_policer_validate()
1470 return -EOPNOTSUPP; in cpsw_qos_clsflower_policer_validate()
1473 if (act->police.rate_bytes_ps || act->police.peakrate_bytes_ps || in cpsw_qos_clsflower_policer_validate()
1474 act->police.avrate || act->police.overhead) { in cpsw_qos_clsflower_policer_validate()
1477 return -EOPNOTSUPP; in cpsw_qos_clsflower_policer_validate()
1486 struct netlink_ext_ack *extack = cls->common.extack; in cpsw_qos_configure_clsflower()
1490 flow_action_for_each(i, act, &rule->action) { in cpsw_qos_configure_clsflower()
1491 switch (act->id) { in cpsw_qos_configure_clsflower()
1493 ret = cpsw_qos_clsflower_policer_validate(&rule->action, act, extack); in cpsw_qos_configure_clsflower()
1498 act->police.rate_pkt_ps); in cpsw_qos_configure_clsflower()
1501 return -EOPNOTSUPP; in cpsw_qos_configure_clsflower()
1504 return -EOPNOTSUPP; in cpsw_qos_configure_clsflower()
1509 u32 port_id = cpsw_slave_index(priv->cpsw, priv) + 1; in cpsw_qos_delete_clsflower()
1511 if (cls->cookie == priv->ale_bc_ratelimit.cookie) { in cpsw_qos_delete_clsflower()
1512 priv->ale_bc_ratelimit.cookie = 0; in cpsw_qos_delete_clsflower()
1513 priv->ale_bc_ratelimit.rate_packet_ps = 0; in cpsw_qos_delete_clsflower()
1514 cpsw_ale_rx_ratelimit_bc(priv->cpsw->ale, port_id, 0); in cpsw_qos_delete_clsflower()
1517 if (cls->cookie == priv->ale_mc_ratelimit.cookie) { in cpsw_qos_delete_clsflower()
1518 priv->ale_mc_ratelimit.cookie = 0; in cpsw_qos_delete_clsflower()
1519 priv->ale_mc_ratelimit.rate_packet_ps = 0; in cpsw_qos_delete_clsflower()
1520 cpsw_ale_rx_ratelimit_mc(priv->cpsw->ale, port_id, 0); in cpsw_qos_delete_clsflower()
1528 switch (cls_flower->command) { in cpsw_qos_setup_tc_clsflower()
1534 return -EOPNOTSUPP; in cpsw_qos_setup_tc_clsflower()
1543 if (!tc_cls_can_offload_and_chain0(priv->ndev, type_data)) in cpsw_qos_setup_tc_block_cb()
1544 return -EOPNOTSUPP; in cpsw_qos_setup_tc_block_cb()
1546 ret = pm_runtime_get_sync(priv->dev); in cpsw_qos_setup_tc_block_cb()
1548 pm_runtime_put_noidle(priv->dev); in cpsw_qos_setup_tc_block_cb()
1552 switch (type) { in cpsw_qos_setup_tc_block_cb()
1557 ret = -EOPNOTSUPP; in cpsw_qos_setup_tc_block_cb()
1560 pm_runtime_put(priv->dev); in cpsw_qos_setup_tc_block_cb()
1577 u32 port_id = cpsw_slave_index(priv->cpsw, priv) + 1; in cpsw_qos_clsflower_resume()
1579 if (priv->ale_bc_ratelimit.cookie) in cpsw_qos_clsflower_resume()
1580 cpsw_ale_rx_ratelimit_bc(priv->cpsw->ale, port_id, in cpsw_qos_clsflower_resume()
1581 priv->ale_bc_ratelimit.rate_packet_ps); in cpsw_qos_clsflower_resume()
1583 if (priv->ale_mc_ratelimit.cookie) in cpsw_qos_clsflower_resume()
1584 cpsw_ale_rx_ratelimit_mc(priv->cpsw->ale, port_id, in cpsw_qos_clsflower_resume()
1585 priv->ale_mc_ratelimit.rate_packet_ps); in cpsw_qos_clsflower_resume()