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, ×tamp); 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 --- |