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

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

624 skb_complete_tx_timestamp(skb_match, &shhwtstamps);
625
626 /* Next ts */
627 ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
628 }
629}
630EXPORT_SYMBOL(ocelot_get_txtstamp);
631
1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
2/*
3 * Microsemi Ocelot Switch driver
4 *
5 * Copyright (c) 2017 Microsemi Corporation
6 */
7#include <linux/dsa/ocelot.h>
8#include <linux/if_bridge.h>

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

624 skb_complete_tx_timestamp(skb_match, &shhwtstamps);
625
626 /* Next ts */
627 ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
628 }
629}
630EXPORT_SYMBOL(ocelot_get_txtstamp);
631
632static int ocelot_rx_frame_word(struct ocelot *ocelot, u8 grp, bool ifh,
633 u32 *rval)
634{
635 u32 bytes_valid, val;
636
637 val = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
638 if (val == XTR_NOT_READY) {
639 if (ifh)
640 return -EIO;
641
642 do {
643 val = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
644 } while (val == XTR_NOT_READY);
645 }
646
647 switch (val) {
648 case XTR_ABORT:
649 return -EIO;
650 case XTR_EOF_0:
651 case XTR_EOF_1:
652 case XTR_EOF_2:
653 case XTR_EOF_3:
654 case XTR_PRUNED:
655 bytes_valid = XTR_VALID_BYTES(val);
656 val = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
657 if (val == XTR_ESCAPE)
658 *rval = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
659 else
660 *rval = val;
661
662 return bytes_valid;
663 case XTR_ESCAPE:
664 *rval = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
665
666 return 4;
667 default:
668 *rval = val;
669
670 return 4;
671 }
672}
673
674static int ocelot_xtr_poll_xfh(struct ocelot *ocelot, int grp, u32 *xfh)
675{
676 int i, err = 0;
677
678 for (i = 0; i < OCELOT_TAG_LEN / 4; i++) {
679 err = ocelot_rx_frame_word(ocelot, grp, true, &xfh[i]);
680 if (err != 4)
681 return (err < 0) ? err : -EIO;
682 }
683
684 return 0;
685}
686
687int ocelot_xtr_poll_frame(struct ocelot *ocelot, int grp, struct sk_buff **nskb)
688{
689 struct skb_shared_hwtstamps *shhwtstamps;
690 u64 tod_in_ns, full_ts_in_ns;
691 u64 timestamp, src_port, len;
692 u32 xfh[OCELOT_TAG_LEN / 4];
693 struct net_device *dev;
694 struct timespec64 ts;
695 struct sk_buff *skb;
696 int sz, buf_len;
697 u32 val, *buf;
698 int err;
699
700 err = ocelot_xtr_poll_xfh(ocelot, grp, xfh);
701 if (err)
702 return err;
703
704 ocelot_xfh_get_src_port(xfh, &src_port);
705 ocelot_xfh_get_len(xfh, &len);
706 ocelot_xfh_get_rew_val(xfh, &timestamp);
707
708 if (WARN_ON(src_port >= ocelot->num_phys_ports))
709 return -EINVAL;
710
711 dev = ocelot->ops->port_to_netdev(ocelot, src_port);
712 if (!dev)
713 return -EINVAL;
714
715 skb = netdev_alloc_skb(dev, len);
716 if (unlikely(!skb)) {
717 netdev_err(dev, "Unable to allocate sk_buff\n");
718 return -ENOMEM;
719 }
720
721 buf_len = len - ETH_FCS_LEN;
722 buf = (u32 *)skb_put(skb, buf_len);
723
724 len = 0;
725 do {
726 sz = ocelot_rx_frame_word(ocelot, grp, false, &val);
727 if (sz < 0) {
728 err = sz;
729 goto out_free_skb;
730 }
731 *buf++ = val;
732 len += sz;
733 } while (len < buf_len);
734
735 /* Read the FCS */
736 sz = ocelot_rx_frame_word(ocelot, grp, false, &val);
737 if (sz < 0) {
738 err = sz;
739 goto out_free_skb;
740 }
741
742 /* Update the statistics if part of the FCS was read before */
743 len -= ETH_FCS_LEN - sz;
744
745 if (unlikely(dev->features & NETIF_F_RXFCS)) {
746 buf = (u32 *)skb_put(skb, ETH_FCS_LEN);
747 *buf = val;
748 }
749
750 if (ocelot->ptp) {
751 ocelot_ptp_gettime64(&ocelot->ptp_info, &ts);
752
753 tod_in_ns = ktime_set(ts.tv_sec, ts.tv_nsec);
754 if ((tod_in_ns & 0xffffffff) < timestamp)
755 full_ts_in_ns = (((tod_in_ns >> 32) - 1) << 32) |
756 timestamp;
757 else
758 full_ts_in_ns = (tod_in_ns & GENMASK_ULL(63, 32)) |
759 timestamp;
760
761 shhwtstamps = skb_hwtstamps(skb);
762 memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
763 shhwtstamps->hwtstamp = full_ts_in_ns;
764 }
765
766 /* Everything we see on an interface that is in the HW bridge
767 * has already been forwarded.
768 */
769 if (ocelot->bridge_mask & BIT(src_port))
770 skb->offload_fwd_mark = 1;
771
772 skb->protocol = eth_type_trans(skb, dev);
773 *nskb = skb;
774
775 return 0;
776
777out_free_skb:
778 kfree_skb(skb);
779 return err;
780}
781EXPORT_SYMBOL(ocelot_xtr_poll_frame);
782
632bool ocelot_can_inject(struct ocelot *ocelot, int grp)
633{
634 u32 val = ocelot_read(ocelot, QS_INJ_STATUS);
635
636 if (!(val & QS_INJ_STATUS_FIFO_RDY(BIT(grp))))
637 return false;
638 if (val & QS_INJ_STATUS_WMARK_REACHED(BIT(grp)))
639 return false;

--- 1305 unchanged lines hidden ---
783bool ocelot_can_inject(struct ocelot *ocelot, int grp)
784{
785 u32 val = ocelot_read(ocelot, QS_INJ_STATUS);
786
787 if (!(val & QS_INJ_STATUS_FIFO_RDY(BIT(grp))))
788 return false;
789 if (val & QS_INJ_STATUS_WMARK_REACHED(BIT(grp)))
790 return false;

--- 1305 unchanged lines hidden ---