| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0+ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Driver for the National Semiconductor DP83640 PHYTER |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2010 OMICRON electronics GmbH |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 7 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 8 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 9 | | - * (at your option) any later version. |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 14 | | - * GNU General Public License for more details. |
|---|
| 15 | | - * |
|---|
| 16 | | - * You should have received a copy of the GNU General Public License |
|---|
| 17 | | - * along with this program; if not, write to the Free Software |
|---|
| 18 | | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|---|
| 19 | 6 | */ |
|---|
| 20 | 7 | |
|---|
| 21 | 8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 111 | 98 | struct list_head list; |
|---|
| 112 | 99 | struct dp83640_clock *clock; |
|---|
| 113 | 100 | struct phy_device *phydev; |
|---|
| 101 | + struct mii_timestamper mii_ts; |
|---|
| 114 | 102 | struct delayed_work ts_work; |
|---|
| 115 | 103 | int hwts_tx_en; |
|---|
| 116 | 104 | int hwts_rx_en; |
|---|
| .. | .. |
|---|
| 482 | 470 | |
|---|
| 483 | 471 | switch (rq->type) { |
|---|
| 484 | 472 | case PTP_CLK_REQ_EXTTS: |
|---|
| 473 | + /* Reject requests with unsupported flags */ |
|---|
| 474 | + if (rq->extts.flags & ~(PTP_ENABLE_FEATURE | |
|---|
| 475 | + PTP_RISING_EDGE | |
|---|
| 476 | + PTP_FALLING_EDGE | |
|---|
| 477 | + PTP_STRICT_FLAGS)) |
|---|
| 478 | + return -EOPNOTSUPP; |
|---|
| 479 | + |
|---|
| 480 | + /* Reject requests to enable time stamping on both edges. */ |
|---|
| 481 | + if ((rq->extts.flags & PTP_STRICT_FLAGS) && |
|---|
| 482 | + (rq->extts.flags & PTP_ENABLE_FEATURE) && |
|---|
| 483 | + (rq->extts.flags & PTP_EXTTS_EDGES) == PTP_EXTTS_EDGES) |
|---|
| 484 | + return -EOPNOTSUPP; |
|---|
| 485 | + |
|---|
| 485 | 486 | index = rq->extts.index; |
|---|
| 486 | 487 | if (index >= N_EXT_TS) |
|---|
| 487 | 488 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 504 | 505 | return 0; |
|---|
| 505 | 506 | |
|---|
| 506 | 507 | case PTP_CLK_REQ_PEROUT: |
|---|
| 508 | + /* Reject requests with unsupported flags */ |
|---|
| 509 | + if (rq->perout.flags) |
|---|
| 510 | + return -EOPNOTSUPP; |
|---|
| 507 | 511 | if (rq->perout.index >= N_PER_OUT) |
|---|
| 508 | 512 | return -EINVAL; |
|---|
| 509 | 513 | return periodic_output(clock, rq, on, rq->perout.index); |
|---|
| .. | .. |
|---|
| 553 | 557 | mutex_unlock(&clock->extreg_lock); |
|---|
| 554 | 558 | |
|---|
| 555 | 559 | if (!phydev->attached_dev) { |
|---|
| 556 | | - pr_warn("expected to find an attached netdevice\n"); |
|---|
| 560 | + phydev_warn(phydev, |
|---|
| 561 | + "expected to find an attached netdevice\n"); |
|---|
| 557 | 562 | return; |
|---|
| 558 | 563 | } |
|---|
| 559 | 564 | |
|---|
| 560 | 565 | if (on) { |
|---|
| 561 | 566 | if (dev_mc_add(phydev->attached_dev, status_frame_dst)) |
|---|
| 562 | | - pr_warn("failed to add mc address\n"); |
|---|
| 567 | + phydev_warn(phydev, "failed to add mc address\n"); |
|---|
| 563 | 568 | } else { |
|---|
| 564 | 569 | if (dev_mc_del(phydev->attached_dev, status_frame_dst)) |
|---|
| 565 | | - pr_warn("failed to delete mc address\n"); |
|---|
| 570 | + phydev_warn(phydev, "failed to delete mc address\n"); |
|---|
| 566 | 571 | } |
|---|
| 567 | 572 | } |
|---|
| 568 | 573 | |
|---|
| .. | .. |
|---|
| 623 | 628 | u16 cal_gpio, cfg0, evnt, ptp_trig, trigger, val; |
|---|
| 624 | 629 | |
|---|
| 625 | 630 | trigger = CAL_TRIGGER; |
|---|
| 626 | | - cal_gpio = 1 + ptp_find_pin(clock->ptp_clock, PTP_PF_PHYSYNC, 0); |
|---|
| 631 | + cal_gpio = 1 + ptp_find_pin_unlocked(clock->ptp_clock, PTP_PF_PHYSYNC, 0); |
|---|
| 627 | 632 | if (cal_gpio < 1) { |
|---|
| 628 | 633 | pr_err("PHY calibration pin not available - PHY is not calibrated."); |
|---|
| 629 | 634 | return; |
|---|
| .. | .. |
|---|
| 686 | 691 | * read out and correct offsets |
|---|
| 687 | 692 | */ |
|---|
| 688 | 693 | val = ext_read(master, PAGE4, PTP_STS); |
|---|
| 689 | | - pr_info("master PTP_STS 0x%04hx\n", val); |
|---|
| 694 | + phydev_info(master, "master PTP_STS 0x%04hx\n", val); |
|---|
| 690 | 695 | val = ext_read(master, PAGE4, PTP_ESTS); |
|---|
| 691 | | - pr_info("master PTP_ESTS 0x%04hx\n", val); |
|---|
| 696 | + phydev_info(master, "master PTP_ESTS 0x%04hx\n", val); |
|---|
| 692 | 697 | event_ts.ns_lo = ext_read(master, PAGE4, PTP_EDATA); |
|---|
| 693 | 698 | event_ts.ns_hi = ext_read(master, PAGE4, PTP_EDATA); |
|---|
| 694 | 699 | event_ts.sec_lo = ext_read(master, PAGE4, PTP_EDATA); |
|---|
| .. | .. |
|---|
| 698 | 703 | list_for_each(this, &clock->phylist) { |
|---|
| 699 | 704 | tmp = list_entry(this, struct dp83640_private, list); |
|---|
| 700 | 705 | val = ext_read(tmp->phydev, PAGE4, PTP_STS); |
|---|
| 701 | | - pr_info("slave PTP_STS 0x%04hx\n", val); |
|---|
| 706 | + phydev_info(tmp->phydev, "slave PTP_STS 0x%04hx\n", val); |
|---|
| 702 | 707 | val = ext_read(tmp->phydev, PAGE4, PTP_ESTS); |
|---|
| 703 | | - pr_info("slave PTP_ESTS 0x%04hx\n", val); |
|---|
| 708 | + phydev_info(tmp->phydev, "slave PTP_ESTS 0x%04hx\n", val); |
|---|
| 704 | 709 | event_ts.ns_lo = ext_read(tmp->phydev, PAGE4, PTP_EDATA); |
|---|
| 705 | 710 | event_ts.ns_hi = ext_read(tmp->phydev, PAGE4, PTP_EDATA); |
|---|
| 706 | 711 | event_ts.sec_lo = ext_read(tmp->phydev, PAGE4, PTP_EDATA); |
|---|
| 707 | 712 | event_ts.sec_hi = ext_read(tmp->phydev, PAGE4, PTP_EDATA); |
|---|
| 708 | 713 | diff = now - (s64) phy2txts(&event_ts); |
|---|
| 709 | | - pr_info("slave offset %lld nanoseconds\n", diff); |
|---|
| 714 | + phydev_info(tmp->phydev, "slave offset %lld nanoseconds\n", |
|---|
| 715 | + diff); |
|---|
| 710 | 716 | diff += ADJTIME_FIX; |
|---|
| 711 | 717 | ts = ns_to_timespec64(diff); |
|---|
| 712 | 718 | tdr_write(0, tmp->phydev, &ts, PTP_STEP_CLK); |
|---|
| .. | .. |
|---|
| 760 | 766 | switch (words) { |
|---|
| 761 | 767 | case 3: |
|---|
| 762 | 768 | dp83640->edata.sec_hi = phy_txts->sec_hi; |
|---|
| 763 | | - /* fall through */ |
|---|
| 769 | + fallthrough; |
|---|
| 764 | 770 | case 2: |
|---|
| 765 | 771 | dp83640->edata.sec_lo = phy_txts->sec_lo; |
|---|
| 766 | | - /* fall through */ |
|---|
| 772 | + fallthrough; |
|---|
| 767 | 773 | case 1: |
|---|
| 768 | 774 | dp83640->edata.ns_hi = phy_txts->ns_hi; |
|---|
| 769 | | - /* fall through */ |
|---|
| 775 | + fallthrough; |
|---|
| 770 | 776 | case 0: |
|---|
| 771 | 777 | dp83640->edata.ns_lo = phy_txts->ns_lo; |
|---|
| 772 | 778 | } |
|---|
| .. | .. |
|---|
| 792 | 798 | return parsed; |
|---|
| 793 | 799 | } |
|---|
| 794 | 800 | |
|---|
| 795 | | -#define DP83640_PACKET_HASH_OFFSET 20 |
|---|
| 796 | 801 | #define DP83640_PACKET_HASH_LEN 10 |
|---|
| 797 | 802 | |
|---|
| 798 | 803 | static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts) |
|---|
| 799 | 804 | { |
|---|
| 800 | | - u16 *seqid, hash; |
|---|
| 801 | | - unsigned int offset = 0; |
|---|
| 802 | | - u8 *msgtype, *data = skb_mac_header(skb); |
|---|
| 805 | + struct ptp_header *hdr; |
|---|
| 806 | + u8 msgtype; |
|---|
| 807 | + u16 seqid; |
|---|
| 808 | + u16 hash; |
|---|
| 803 | 809 | |
|---|
| 804 | 810 | /* check sequenceID, messageType, 12 bit hash of offset 20-29 */ |
|---|
| 805 | 811 | |
|---|
| 806 | | - if (type & PTP_CLASS_VLAN) |
|---|
| 807 | | - offset += VLAN_HLEN; |
|---|
| 808 | | - |
|---|
| 809 | | - switch (type & PTP_CLASS_PMASK) { |
|---|
| 810 | | - case PTP_CLASS_IPV4: |
|---|
| 811 | | - offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN; |
|---|
| 812 | | - break; |
|---|
| 813 | | - case PTP_CLASS_IPV6: |
|---|
| 814 | | - offset += ETH_HLEN + IP6_HLEN + UDP_HLEN; |
|---|
| 815 | | - break; |
|---|
| 816 | | - case PTP_CLASS_L2: |
|---|
| 817 | | - offset += ETH_HLEN; |
|---|
| 818 | | - break; |
|---|
| 819 | | - default: |
|---|
| 820 | | - return 0; |
|---|
| 821 | | - } |
|---|
| 822 | | - |
|---|
| 823 | | - if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid)) |
|---|
| 812 | + hdr = ptp_parse_header(skb, type); |
|---|
| 813 | + if (!hdr) |
|---|
| 824 | 814 | return 0; |
|---|
| 825 | 815 | |
|---|
| 826 | | - if (unlikely(type & PTP_CLASS_V1)) |
|---|
| 827 | | - msgtype = data + offset + OFF_PTP_CONTROL; |
|---|
| 828 | | - else |
|---|
| 829 | | - msgtype = data + offset; |
|---|
| 830 | | - if (rxts->msgtype != (*msgtype & 0xf)) |
|---|
| 816 | + msgtype = ptp_get_msgtype(hdr, type); |
|---|
| 817 | + |
|---|
| 818 | + if (rxts->msgtype != (msgtype & 0xf)) |
|---|
| 831 | 819 | return 0; |
|---|
| 832 | 820 | |
|---|
| 833 | | - seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID); |
|---|
| 834 | | - if (rxts->seqid != ntohs(*seqid)) |
|---|
| 821 | + seqid = be16_to_cpu(hdr->sequence_id); |
|---|
| 822 | + if (rxts->seqid != seqid) |
|---|
| 835 | 823 | return 0; |
|---|
| 836 | 824 | |
|---|
| 837 | 825 | hash = ether_crc(DP83640_PACKET_HASH_LEN, |
|---|
| 838 | | - data + offset + DP83640_PACKET_HASH_OFFSET) >> 20; |
|---|
| 826 | + (unsigned char *)&hdr->source_port_identity) >> 20; |
|---|
| 839 | 827 | if (rxts->hash != hash) |
|---|
| 840 | 828 | return 0; |
|---|
| 841 | 829 | |
|---|
| .. | .. |
|---|
| 975 | 963 | |
|---|
| 976 | 964 | static int is_sync(struct sk_buff *skb, int type) |
|---|
| 977 | 965 | { |
|---|
| 978 | | - u8 *data = skb->data, *msgtype; |
|---|
| 979 | | - unsigned int offset = 0; |
|---|
| 966 | + struct ptp_header *hdr; |
|---|
| 967 | + u8 msgtype; |
|---|
| 980 | 968 | |
|---|
| 981 | | - if (type & PTP_CLASS_VLAN) |
|---|
| 982 | | - offset += VLAN_HLEN; |
|---|
| 983 | | - |
|---|
| 984 | | - switch (type & PTP_CLASS_PMASK) { |
|---|
| 985 | | - case PTP_CLASS_IPV4: |
|---|
| 986 | | - offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN; |
|---|
| 987 | | - break; |
|---|
| 988 | | - case PTP_CLASS_IPV6: |
|---|
| 989 | | - offset += ETH_HLEN + IP6_HLEN + UDP_HLEN; |
|---|
| 990 | | - break; |
|---|
| 991 | | - case PTP_CLASS_L2: |
|---|
| 992 | | - offset += ETH_HLEN; |
|---|
| 993 | | - break; |
|---|
| 994 | | - default: |
|---|
| 995 | | - return 0; |
|---|
| 996 | | - } |
|---|
| 997 | | - |
|---|
| 998 | | - if (type & PTP_CLASS_V1) |
|---|
| 999 | | - offset += OFF_PTP_CONTROL; |
|---|
| 1000 | | - |
|---|
| 1001 | | - if (skb->len < offset + 1) |
|---|
| 969 | + hdr = ptp_parse_header(skb, type); |
|---|
| 970 | + if (!hdr) |
|---|
| 1002 | 971 | return 0; |
|---|
| 1003 | 972 | |
|---|
| 1004 | | - msgtype = data + offset; |
|---|
| 973 | + msgtype = ptp_get_msgtype(hdr, type); |
|---|
| 1005 | 974 | |
|---|
| 1006 | | - return (*msgtype & 0xf) == 0; |
|---|
| 975 | + return (msgtype & 0xf) == 0; |
|---|
| 1007 | 976 | } |
|---|
| 1008 | 977 | |
|---|
| 1009 | 978 | static void dp83640_free_clocks(void) |
|---|
| .. | .. |
|---|
| 1126 | 1095 | mutex_unlock(&clock->clock_lock); |
|---|
| 1127 | 1096 | } |
|---|
| 1128 | 1097 | |
|---|
| 1129 | | -static int dp83640_probe(struct phy_device *phydev) |
|---|
| 1130 | | -{ |
|---|
| 1131 | | - struct dp83640_clock *clock; |
|---|
| 1132 | | - struct dp83640_private *dp83640; |
|---|
| 1133 | | - int err = -ENOMEM, i; |
|---|
| 1134 | | - |
|---|
| 1135 | | - if (phydev->mdio.addr == BROADCAST_ADDR) |
|---|
| 1136 | | - return 0; |
|---|
| 1137 | | - |
|---|
| 1138 | | - clock = dp83640_clock_get_bus(phydev->mdio.bus); |
|---|
| 1139 | | - if (!clock) |
|---|
| 1140 | | - goto no_clock; |
|---|
| 1141 | | - |
|---|
| 1142 | | - dp83640 = kzalloc(sizeof(struct dp83640_private), GFP_KERNEL); |
|---|
| 1143 | | - if (!dp83640) |
|---|
| 1144 | | - goto no_memory; |
|---|
| 1145 | | - |
|---|
| 1146 | | - dp83640->phydev = phydev; |
|---|
| 1147 | | - INIT_DELAYED_WORK(&dp83640->ts_work, rx_timestamp_work); |
|---|
| 1148 | | - |
|---|
| 1149 | | - INIT_LIST_HEAD(&dp83640->rxts); |
|---|
| 1150 | | - INIT_LIST_HEAD(&dp83640->rxpool); |
|---|
| 1151 | | - for (i = 0; i < MAX_RXTS; i++) |
|---|
| 1152 | | - list_add(&dp83640->rx_pool_data[i].list, &dp83640->rxpool); |
|---|
| 1153 | | - |
|---|
| 1154 | | - phydev->priv = dp83640; |
|---|
| 1155 | | - |
|---|
| 1156 | | - spin_lock_init(&dp83640->rx_lock); |
|---|
| 1157 | | - skb_queue_head_init(&dp83640->rx_queue); |
|---|
| 1158 | | - skb_queue_head_init(&dp83640->tx_queue); |
|---|
| 1159 | | - |
|---|
| 1160 | | - dp83640->clock = clock; |
|---|
| 1161 | | - |
|---|
| 1162 | | - if (choose_this_phy(clock, phydev)) { |
|---|
| 1163 | | - clock->chosen = dp83640; |
|---|
| 1164 | | - clock->ptp_clock = ptp_clock_register(&clock->caps, |
|---|
| 1165 | | - &phydev->mdio.dev); |
|---|
| 1166 | | - if (IS_ERR(clock->ptp_clock)) { |
|---|
| 1167 | | - err = PTR_ERR(clock->ptp_clock); |
|---|
| 1168 | | - goto no_register; |
|---|
| 1169 | | - } |
|---|
| 1170 | | - } else |
|---|
| 1171 | | - list_add_tail(&dp83640->list, &clock->phylist); |
|---|
| 1172 | | - |
|---|
| 1173 | | - dp83640_clock_put(clock); |
|---|
| 1174 | | - return 0; |
|---|
| 1175 | | - |
|---|
| 1176 | | -no_register: |
|---|
| 1177 | | - clock->chosen = NULL; |
|---|
| 1178 | | - kfree(dp83640); |
|---|
| 1179 | | -no_memory: |
|---|
| 1180 | | - dp83640_clock_put(clock); |
|---|
| 1181 | | -no_clock: |
|---|
| 1182 | | - return err; |
|---|
| 1183 | | -} |
|---|
| 1184 | | - |
|---|
| 1185 | | -static void dp83640_remove(struct phy_device *phydev) |
|---|
| 1186 | | -{ |
|---|
| 1187 | | - struct dp83640_clock *clock; |
|---|
| 1188 | | - struct list_head *this, *next; |
|---|
| 1189 | | - struct dp83640_private *tmp, *dp83640 = phydev->priv; |
|---|
| 1190 | | - |
|---|
| 1191 | | - if (phydev->mdio.addr == BROADCAST_ADDR) |
|---|
| 1192 | | - return; |
|---|
| 1193 | | - |
|---|
| 1194 | | - enable_status_frames(phydev, false); |
|---|
| 1195 | | - cancel_delayed_work_sync(&dp83640->ts_work); |
|---|
| 1196 | | - |
|---|
| 1197 | | - skb_queue_purge(&dp83640->rx_queue); |
|---|
| 1198 | | - skb_queue_purge(&dp83640->tx_queue); |
|---|
| 1199 | | - |
|---|
| 1200 | | - clock = dp83640_clock_get(dp83640->clock); |
|---|
| 1201 | | - |
|---|
| 1202 | | - if (dp83640 == clock->chosen) { |
|---|
| 1203 | | - ptp_clock_unregister(clock->ptp_clock); |
|---|
| 1204 | | - clock->chosen = NULL; |
|---|
| 1205 | | - } else { |
|---|
| 1206 | | - list_for_each_safe(this, next, &clock->phylist) { |
|---|
| 1207 | | - tmp = list_entry(this, struct dp83640_private, list); |
|---|
| 1208 | | - if (tmp == dp83640) { |
|---|
| 1209 | | - list_del_init(&tmp->list); |
|---|
| 1210 | | - break; |
|---|
| 1211 | | - } |
|---|
| 1212 | | - } |
|---|
| 1213 | | - } |
|---|
| 1214 | | - |
|---|
| 1215 | | - dp83640_clock_put(clock); |
|---|
| 1216 | | - kfree(dp83640); |
|---|
| 1217 | | -} |
|---|
| 1218 | | - |
|---|
| 1219 | 1098 | static int dp83640_soft_reset(struct phy_device *phydev) |
|---|
| 1220 | 1099 | { |
|---|
| 1221 | 1100 | int ret; |
|---|
| .. | .. |
|---|
| 1314 | 1193 | } |
|---|
| 1315 | 1194 | } |
|---|
| 1316 | 1195 | |
|---|
| 1317 | | -static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr) |
|---|
| 1196 | +static int dp83640_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr) |
|---|
| 1318 | 1197 | { |
|---|
| 1319 | | - struct dp83640_private *dp83640 = phydev->priv; |
|---|
| 1198 | + struct dp83640_private *dp83640 = |
|---|
| 1199 | + container_of(mii_ts, struct dp83640_private, mii_ts); |
|---|
| 1320 | 1200 | struct hwtstamp_config cfg; |
|---|
| 1321 | 1201 | u16 txcfg0, rxcfg0; |
|---|
| 1322 | 1202 | |
|---|
| .. | .. |
|---|
| 1396 | 1276 | |
|---|
| 1397 | 1277 | mutex_lock(&dp83640->clock->extreg_lock); |
|---|
| 1398 | 1278 | |
|---|
| 1399 | | - ext_write(0, phydev, PAGE5, PTP_TXCFG0, txcfg0); |
|---|
| 1400 | | - ext_write(0, phydev, PAGE5, PTP_RXCFG0, rxcfg0); |
|---|
| 1279 | + ext_write(0, dp83640->phydev, PAGE5, PTP_TXCFG0, txcfg0); |
|---|
| 1280 | + ext_write(0, dp83640->phydev, PAGE5, PTP_RXCFG0, rxcfg0); |
|---|
| 1401 | 1281 | |
|---|
| 1402 | 1282 | mutex_unlock(&dp83640->clock->extreg_lock); |
|---|
| 1403 | 1283 | |
|---|
| .. | .. |
|---|
| 1427 | 1307 | schedule_delayed_work(&dp83640->ts_work, SKB_TIMESTAMP_TIMEOUT); |
|---|
| 1428 | 1308 | } |
|---|
| 1429 | 1309 | |
|---|
| 1430 | | -static bool dp83640_rxtstamp(struct phy_device *phydev, |
|---|
| 1310 | +static bool dp83640_rxtstamp(struct mii_timestamper *mii_ts, |
|---|
| 1431 | 1311 | struct sk_buff *skb, int type) |
|---|
| 1432 | 1312 | { |
|---|
| 1433 | | - struct dp83640_private *dp83640 = phydev->priv; |
|---|
| 1313 | + struct dp83640_private *dp83640 = |
|---|
| 1314 | + container_of(mii_ts, struct dp83640_private, mii_ts); |
|---|
| 1434 | 1315 | struct dp83640_skb_info *skb_info = (struct dp83640_skb_info *)skb->cb; |
|---|
| 1435 | 1316 | struct list_head *this, *next; |
|---|
| 1436 | 1317 | struct rxts *rxts; |
|---|
| .. | .. |
|---|
| 1476 | 1357 | return true; |
|---|
| 1477 | 1358 | } |
|---|
| 1478 | 1359 | |
|---|
| 1479 | | -static void dp83640_txtstamp(struct phy_device *phydev, |
|---|
| 1360 | +static void dp83640_txtstamp(struct mii_timestamper *mii_ts, |
|---|
| 1480 | 1361 | struct sk_buff *skb, int type) |
|---|
| 1481 | 1362 | { |
|---|
| 1482 | 1363 | struct dp83640_skb_info *skb_info = (struct dp83640_skb_info *)skb->cb; |
|---|
| 1483 | | - struct dp83640_private *dp83640 = phydev->priv; |
|---|
| 1364 | + struct dp83640_private *dp83640 = |
|---|
| 1365 | + container_of(mii_ts, struct dp83640_private, mii_ts); |
|---|
| 1484 | 1366 | |
|---|
| 1485 | 1367 | switch (dp83640->hwts_tx_en) { |
|---|
| 1486 | 1368 | |
|---|
| .. | .. |
|---|
| 1489 | 1371 | kfree_skb(skb); |
|---|
| 1490 | 1372 | return; |
|---|
| 1491 | 1373 | } |
|---|
| 1492 | | - /* fall through */ |
|---|
| 1374 | + fallthrough; |
|---|
| 1493 | 1375 | case HWTSTAMP_TX_ON: |
|---|
| 1494 | 1376 | skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; |
|---|
| 1495 | 1377 | skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT; |
|---|
| .. | .. |
|---|
| 1503 | 1385 | } |
|---|
| 1504 | 1386 | } |
|---|
| 1505 | 1387 | |
|---|
| 1506 | | -static int dp83640_ts_info(struct phy_device *dev, struct ethtool_ts_info *info) |
|---|
| 1388 | +static int dp83640_ts_info(struct mii_timestamper *mii_ts, |
|---|
| 1389 | + struct ethtool_ts_info *info) |
|---|
| 1507 | 1390 | { |
|---|
| 1508 | | - struct dp83640_private *dp83640 = dev->priv; |
|---|
| 1391 | + struct dp83640_private *dp83640 = |
|---|
| 1392 | + container_of(mii_ts, struct dp83640_private, mii_ts); |
|---|
| 1509 | 1393 | |
|---|
| 1510 | 1394 | info->so_timestamping = |
|---|
| 1511 | 1395 | SOF_TIMESTAMPING_TX_HARDWARE | |
|---|
| .. | .. |
|---|
| 1525 | 1409 | return 0; |
|---|
| 1526 | 1410 | } |
|---|
| 1527 | 1411 | |
|---|
| 1412 | +static int dp83640_probe(struct phy_device *phydev) |
|---|
| 1413 | +{ |
|---|
| 1414 | + struct dp83640_clock *clock; |
|---|
| 1415 | + struct dp83640_private *dp83640; |
|---|
| 1416 | + int err = -ENOMEM, i; |
|---|
| 1417 | + |
|---|
| 1418 | + if (phydev->mdio.addr == BROADCAST_ADDR) |
|---|
| 1419 | + return 0; |
|---|
| 1420 | + |
|---|
| 1421 | + clock = dp83640_clock_get_bus(phydev->mdio.bus); |
|---|
| 1422 | + if (!clock) |
|---|
| 1423 | + goto no_clock; |
|---|
| 1424 | + |
|---|
| 1425 | + dp83640 = kzalloc(sizeof(struct dp83640_private), GFP_KERNEL); |
|---|
| 1426 | + if (!dp83640) |
|---|
| 1427 | + goto no_memory; |
|---|
| 1428 | + |
|---|
| 1429 | + dp83640->phydev = phydev; |
|---|
| 1430 | + dp83640->mii_ts.rxtstamp = dp83640_rxtstamp; |
|---|
| 1431 | + dp83640->mii_ts.txtstamp = dp83640_txtstamp; |
|---|
| 1432 | + dp83640->mii_ts.hwtstamp = dp83640_hwtstamp; |
|---|
| 1433 | + dp83640->mii_ts.ts_info = dp83640_ts_info; |
|---|
| 1434 | + |
|---|
| 1435 | + INIT_DELAYED_WORK(&dp83640->ts_work, rx_timestamp_work); |
|---|
| 1436 | + INIT_LIST_HEAD(&dp83640->rxts); |
|---|
| 1437 | + INIT_LIST_HEAD(&dp83640->rxpool); |
|---|
| 1438 | + for (i = 0; i < MAX_RXTS; i++) |
|---|
| 1439 | + list_add(&dp83640->rx_pool_data[i].list, &dp83640->rxpool); |
|---|
| 1440 | + |
|---|
| 1441 | + phydev->mii_ts = &dp83640->mii_ts; |
|---|
| 1442 | + phydev->priv = dp83640; |
|---|
| 1443 | + |
|---|
| 1444 | + spin_lock_init(&dp83640->rx_lock); |
|---|
| 1445 | + skb_queue_head_init(&dp83640->rx_queue); |
|---|
| 1446 | + skb_queue_head_init(&dp83640->tx_queue); |
|---|
| 1447 | + |
|---|
| 1448 | + dp83640->clock = clock; |
|---|
| 1449 | + |
|---|
| 1450 | + if (choose_this_phy(clock, phydev)) { |
|---|
| 1451 | + clock->chosen = dp83640; |
|---|
| 1452 | + clock->ptp_clock = ptp_clock_register(&clock->caps, |
|---|
| 1453 | + &phydev->mdio.dev); |
|---|
| 1454 | + if (IS_ERR(clock->ptp_clock)) { |
|---|
| 1455 | + err = PTR_ERR(clock->ptp_clock); |
|---|
| 1456 | + goto no_register; |
|---|
| 1457 | + } |
|---|
| 1458 | + } else |
|---|
| 1459 | + list_add_tail(&dp83640->list, &clock->phylist); |
|---|
| 1460 | + |
|---|
| 1461 | + dp83640_clock_put(clock); |
|---|
| 1462 | + return 0; |
|---|
| 1463 | + |
|---|
| 1464 | +no_register: |
|---|
| 1465 | + clock->chosen = NULL; |
|---|
| 1466 | + kfree(dp83640); |
|---|
| 1467 | +no_memory: |
|---|
| 1468 | + dp83640_clock_put(clock); |
|---|
| 1469 | +no_clock: |
|---|
| 1470 | + return err; |
|---|
| 1471 | +} |
|---|
| 1472 | + |
|---|
| 1473 | +static void dp83640_remove(struct phy_device *phydev) |
|---|
| 1474 | +{ |
|---|
| 1475 | + struct dp83640_clock *clock; |
|---|
| 1476 | + struct list_head *this, *next; |
|---|
| 1477 | + struct dp83640_private *tmp, *dp83640 = phydev->priv; |
|---|
| 1478 | + |
|---|
| 1479 | + if (phydev->mdio.addr == BROADCAST_ADDR) |
|---|
| 1480 | + return; |
|---|
| 1481 | + |
|---|
| 1482 | + phydev->mii_ts = NULL; |
|---|
| 1483 | + |
|---|
| 1484 | + enable_status_frames(phydev, false); |
|---|
| 1485 | + cancel_delayed_work_sync(&dp83640->ts_work); |
|---|
| 1486 | + |
|---|
| 1487 | + skb_queue_purge(&dp83640->rx_queue); |
|---|
| 1488 | + skb_queue_purge(&dp83640->tx_queue); |
|---|
| 1489 | + |
|---|
| 1490 | + clock = dp83640_clock_get(dp83640->clock); |
|---|
| 1491 | + |
|---|
| 1492 | + if (dp83640 == clock->chosen) { |
|---|
| 1493 | + ptp_clock_unregister(clock->ptp_clock); |
|---|
| 1494 | + clock->chosen = NULL; |
|---|
| 1495 | + } else { |
|---|
| 1496 | + list_for_each_safe(this, next, &clock->phylist) { |
|---|
| 1497 | + tmp = list_entry(this, struct dp83640_private, list); |
|---|
| 1498 | + if (tmp == dp83640) { |
|---|
| 1499 | + list_del_init(&tmp->list); |
|---|
| 1500 | + break; |
|---|
| 1501 | + } |
|---|
| 1502 | + } |
|---|
| 1503 | + } |
|---|
| 1504 | + |
|---|
| 1505 | + dp83640_clock_put(clock); |
|---|
| 1506 | + kfree(dp83640); |
|---|
| 1507 | +} |
|---|
| 1508 | + |
|---|
| 1528 | 1509 | static struct phy_driver dp83640_driver = { |
|---|
| 1529 | 1510 | .phy_id = DP83640_PHY_ID, |
|---|
| 1530 | 1511 | .phy_id_mask = 0xfffffff0, |
|---|
| 1531 | 1512 | .name = "NatSemi DP83640", |
|---|
| 1532 | | - .features = PHY_BASIC_FEATURES, |
|---|
| 1533 | | - .flags = PHY_HAS_INTERRUPT, |
|---|
| 1513 | + /* PHY_BASIC_FEATURES */ |
|---|
| 1534 | 1514 | .probe = dp83640_probe, |
|---|
| 1535 | 1515 | .remove = dp83640_remove, |
|---|
| 1536 | 1516 | .soft_reset = dp83640_soft_reset, |
|---|
| 1537 | 1517 | .config_init = dp83640_config_init, |
|---|
| 1538 | 1518 | .ack_interrupt = dp83640_ack_interrupt, |
|---|
| 1539 | 1519 | .config_intr = dp83640_config_intr, |
|---|
| 1540 | | - .ts_info = dp83640_ts_info, |
|---|
| 1541 | | - .hwtstamp = dp83640_hwtstamp, |
|---|
| 1542 | | - .rxtstamp = dp83640_rxtstamp, |
|---|
| 1543 | | - .txtstamp = dp83640_txtstamp, |
|---|
| 1544 | 1520 | }; |
|---|
| 1545 | 1521 | |
|---|
| 1546 | 1522 | static int __init dp83640_init(void) |
|---|