| .. | .. | 
|---|
|  | 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) | 
|---|