Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: phy: broadcom: implement generic .handle_interrupt() callback

In an attempt to actually support shared IRQs in phylib, we now move the
responsibility of triggering the phylib state machine or just returning
IRQ_NONE, based on the IRQ status register, to the PHY driver. Having
3 different IRQ handling callbacks (.handle_interrupt(),
.did_interrupt() and .ack_interrupt() ) is confusing so let the PHY
driver implement directly an IRQ handler like any other device driver.
Make this driver follow the new convention.

Cc: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Tested-by: Michael Walle <michael@walle.cc>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Ioana Ciornei and committed by
Jakub Kicinski
4567d5c3 e11ef96d

+114 -15
+1
drivers/net/phy/bcm-cygnus.c
··· 258 258 .config_init = bcm_cygnus_config_init, 259 259 .ack_interrupt = bcm_phy_ack_intr, 260 260 .config_intr = bcm_phy_config_intr, 261 + .handle_interrupt = bcm_phy_handle_interrupt, 261 262 .suspend = genphy_suspend, 262 263 .resume = bcm_cygnus_resume, 263 264 }, {
+31
drivers/net/phy/bcm-phy-lib.c
··· 196 196 } 197 197 EXPORT_SYMBOL_GPL(bcm_phy_config_intr); 198 198 199 + irqreturn_t bcm_phy_handle_interrupt(struct phy_device *phydev) 200 + { 201 + int irq_status, irq_mask; 202 + 203 + irq_status = phy_read(phydev, MII_BCM54XX_ISR); 204 + if (irq_status < 0) { 205 + phy_error(phydev); 206 + return IRQ_NONE; 207 + } 208 + 209 + /* If a bit from the Interrupt Mask register is set, the corresponding 210 + * bit from the Interrupt Status register is masked. So read the IMR 211 + * and then flip the bits to get the list of possible interrupt 212 + * sources. 213 + */ 214 + irq_mask = phy_read(phydev, MII_BCM54XX_IMR); 215 + if (irq_mask < 0) { 216 + phy_error(phydev); 217 + return IRQ_NONE; 218 + } 219 + irq_mask = ~irq_mask; 220 + 221 + if (!(irq_status & irq_mask)) 222 + return IRQ_NONE; 223 + 224 + phy_trigger_machine(phydev); 225 + 226 + return IRQ_HANDLED; 227 + } 228 + EXPORT_SYMBOL_GPL(bcm_phy_handle_interrupt); 229 + 199 230 int bcm_phy_read_shadow(struct phy_device *phydev, u16 shadow) 200 231 { 201 232 phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow));
+1
drivers/net/phy/bcm-phy-lib.h
··· 63 63 64 64 int bcm_phy_ack_intr(struct phy_device *phydev); 65 65 int bcm_phy_config_intr(struct phy_device *phydev); 66 + irqreturn_t bcm_phy_handle_interrupt(struct phy_device *phydev); 66 67 67 68 int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down); 68 69
+21 -5
drivers/net/phy/bcm54140.c
··· 637 637 BCM54140_RDB_C_PWR_ISOLATE, 0); 638 638 } 639 639 640 - static int bcm54140_did_interrupt(struct phy_device *phydev) 640 + static irqreturn_t bcm54140_handle_interrupt(struct phy_device *phydev) 641 641 { 642 - int ret; 642 + int irq_status, irq_mask; 643 643 644 - ret = bcm_phy_read_rdb(phydev, BCM54140_RDB_ISR); 644 + irq_status = bcm_phy_read_rdb(phydev, BCM54140_RDB_ISR); 645 + if (irq_status < 0) { 646 + phy_error(phydev); 647 + return IRQ_NONE; 648 + } 645 649 646 - return (ret < 0) ? 0 : ret; 650 + irq_mask = bcm_phy_read_rdb(phydev, BCM54140_RDB_IMR); 651 + if (irq_mask < 0) { 652 + phy_error(phydev); 653 + return IRQ_NONE; 654 + } 655 + irq_mask = ~irq_mask; 656 + 657 + if (!(irq_status & irq_mask)) 658 + return IRQ_NONE; 659 + 660 + phy_trigger_machine(phydev); 661 + 662 + return IRQ_HANDLED; 647 663 } 648 664 649 665 static int bcm54140_ack_intr(struct phy_device *phydev) ··· 850 834 .flags = PHY_POLL_CABLE_TEST, 851 835 .features = PHY_GBIT_FEATURES, 852 836 .config_init = bcm54140_config_init, 853 - .did_interrupt = bcm54140_did_interrupt, 854 837 .ack_interrupt = bcm54140_ack_intr, 838 + .handle_interrupt = bcm54140_handle_interrupt, 855 839 .config_intr = bcm54140_config_intr, 856 840 .probe = bcm54140_probe, 857 841 .suspend = genphy_suspend,
+2
drivers/net/phy/bcm63xx.c
··· 69 69 .config_init = bcm63xx_config_init, 70 70 .ack_interrupt = bcm_phy_ack_intr, 71 71 .config_intr = bcm63xx_config_intr, 72 + .handle_interrupt = bcm_phy_handle_interrupt, 72 73 }, { 73 74 /* same phy as above, with just a different OUI */ 74 75 .phy_id = 0x002bdc00, ··· 80 79 .config_init = bcm63xx_config_init, 81 80 .ack_interrupt = bcm_phy_ack_intr, 82 81 .config_intr = bcm63xx_config_intr, 82 + .handle_interrupt = bcm_phy_handle_interrupt, 83 83 } }; 84 84 85 85 module_phy_driver(bcm63xx_driver);
+22 -10
drivers/net/phy/bcm87xx.c
··· 153 153 return err; 154 154 } 155 155 156 - static int bcm87xx_did_interrupt(struct phy_device *phydev) 156 + static irqreturn_t bcm87xx_handle_interrupt(struct phy_device *phydev) 157 + { 158 + int irq_status; 159 + 160 + irq_status = phy_read(phydev, BCM87XX_LASI_STATUS); 161 + if (irq_status < 0) { 162 + phy_error(phydev); 163 + return IRQ_NONE; 164 + } 165 + 166 + if (irq_status == 0) 167 + return IRQ_NONE; 168 + 169 + phy_trigger_machine(phydev); 170 + 171 + return IRQ_HANDLED; 172 + } 173 + 174 + static int bcm87xx_ack_interrupt(struct phy_device *phydev) 157 175 { 158 176 int reg; 159 177 178 + /* Reading the LASI status clears it. */ 160 179 reg = phy_read(phydev, BCM87XX_LASI_STATUS); 161 180 162 181 if (reg < 0) { ··· 185 166 return 0; 186 167 } 187 168 return (reg & 1) != 0; 188 - } 189 - 190 - static int bcm87xx_ack_interrupt(struct phy_device *phydev) 191 - { 192 - /* Reading the LASI status clears it. */ 193 - bcm87xx_did_interrupt(phydev); 194 - return 0; 195 169 } 196 170 197 171 static int bcm8706_match_phy_device(struct phy_device *phydev) ··· 208 196 .read_status = bcm87xx_read_status, 209 197 .ack_interrupt = bcm87xx_ack_interrupt, 210 198 .config_intr = bcm87xx_config_intr, 211 - .did_interrupt = bcm87xx_did_interrupt, 199 + .handle_interrupt = bcm87xx_handle_interrupt, 212 200 .match_phy_device = bcm8706_match_phy_device, 213 201 }, { 214 202 .phy_id = PHY_ID_BCM8727, ··· 220 208 .read_status = bcm87xx_read_status, 221 209 .ack_interrupt = bcm87xx_ack_interrupt, 222 210 .config_intr = bcm87xx_config_intr, 223 - .did_interrupt = bcm87xx_did_interrupt, 211 + .handle_interrupt = bcm87xx_handle_interrupt, 224 212 .match_phy_device = bcm8727_match_phy_device, 225 213 } }; 226 214
+36
drivers/net/phy/broadcom.c
··· 643 643 return err; 644 644 } 645 645 646 + static irqreturn_t brcm_fet_handle_interrupt(struct phy_device *phydev) 647 + { 648 + int irq_status; 649 + 650 + irq_status = phy_read(phydev, MII_BRCM_FET_INTREG); 651 + if (irq_status < 0) { 652 + phy_error(phydev); 653 + return IRQ_NONE; 654 + } 655 + 656 + if (irq_status == 0) 657 + return IRQ_NONE; 658 + 659 + phy_trigger_machine(phydev); 660 + 661 + return IRQ_HANDLED; 662 + } 663 + 646 664 struct bcm53xx_phy_priv { 647 665 u64 *stats; 648 666 }; ··· 701 683 .config_init = bcm54xx_config_init, 702 684 .ack_interrupt = bcm_phy_ack_intr, 703 685 .config_intr = bcm_phy_config_intr, 686 + .handle_interrupt = bcm_phy_handle_interrupt, 704 687 }, { 705 688 .phy_id = PHY_ID_BCM5421, 706 689 .phy_id_mask = 0xfffffff0, ··· 710 691 .config_init = bcm54xx_config_init, 711 692 .ack_interrupt = bcm_phy_ack_intr, 712 693 .config_intr = bcm_phy_config_intr, 694 + .handle_interrupt = bcm_phy_handle_interrupt, 713 695 }, { 714 696 .phy_id = PHY_ID_BCM54210E, 715 697 .phy_id_mask = 0xfffffff0, ··· 719 699 .config_init = bcm54xx_config_init, 720 700 .ack_interrupt = bcm_phy_ack_intr, 721 701 .config_intr = bcm_phy_config_intr, 702 + .handle_interrupt = bcm_phy_handle_interrupt, 722 703 }, { 723 704 .phy_id = PHY_ID_BCM5461, 724 705 .phy_id_mask = 0xfffffff0, ··· 728 707 .config_init = bcm54xx_config_init, 729 708 .ack_interrupt = bcm_phy_ack_intr, 730 709 .config_intr = bcm_phy_config_intr, 710 + .handle_interrupt = bcm_phy_handle_interrupt, 731 711 }, { 732 712 .phy_id = PHY_ID_BCM54612E, 733 713 .phy_id_mask = 0xfffffff0, ··· 737 715 .config_init = bcm54xx_config_init, 738 716 .ack_interrupt = bcm_phy_ack_intr, 739 717 .config_intr = bcm_phy_config_intr, 718 + .handle_interrupt = bcm_phy_handle_interrupt, 740 719 }, { 741 720 .phy_id = PHY_ID_BCM54616S, 742 721 .phy_id_mask = 0xfffffff0, ··· 747 724 .config_aneg = bcm54616s_config_aneg, 748 725 .ack_interrupt = bcm_phy_ack_intr, 749 726 .config_intr = bcm_phy_config_intr, 727 + .handle_interrupt = bcm_phy_handle_interrupt, 750 728 .read_status = bcm54616s_read_status, 751 729 .probe = bcm54616s_probe, 752 730 }, { ··· 758 734 .config_init = bcm54xx_config_init, 759 735 .ack_interrupt = bcm_phy_ack_intr, 760 736 .config_intr = bcm_phy_config_intr, 737 + .handle_interrupt = bcm_phy_handle_interrupt, 761 738 .suspend = genphy_suspend, 762 739 .resume = genphy_resume, 763 740 }, { ··· 770 745 .config_aneg = bcm5481_config_aneg, 771 746 .ack_interrupt = bcm_phy_ack_intr, 772 747 .config_intr = bcm_phy_config_intr, 748 + .handle_interrupt = bcm_phy_handle_interrupt, 773 749 }, { 774 750 .phy_id = PHY_ID_BCM54810, 775 751 .phy_id_mask = 0xfffffff0, ··· 780 754 .config_aneg = bcm5481_config_aneg, 781 755 .ack_interrupt = bcm_phy_ack_intr, 782 756 .config_intr = bcm_phy_config_intr, 757 + .handle_interrupt = bcm_phy_handle_interrupt, 783 758 .suspend = genphy_suspend, 784 759 .resume = bcm54xx_resume, 785 760 }, { ··· 792 765 .config_aneg = bcm5481_config_aneg, 793 766 .ack_interrupt = bcm_phy_ack_intr, 794 767 .config_intr = bcm_phy_config_intr, 768 + .handle_interrupt = bcm_phy_handle_interrupt, 795 769 .suspend = genphy_suspend, 796 770 .resume = bcm54xx_resume, 797 771 }, { ··· 804 776 .read_status = bcm5482_read_status, 805 777 .ack_interrupt = bcm_phy_ack_intr, 806 778 .config_intr = bcm_phy_config_intr, 779 + .handle_interrupt = bcm_phy_handle_interrupt, 807 780 }, { 808 781 .phy_id = PHY_ID_BCM50610, 809 782 .phy_id_mask = 0xfffffff0, ··· 813 784 .config_init = bcm54xx_config_init, 814 785 .ack_interrupt = bcm_phy_ack_intr, 815 786 .config_intr = bcm_phy_config_intr, 787 + .handle_interrupt = bcm_phy_handle_interrupt, 816 788 }, { 817 789 .phy_id = PHY_ID_BCM50610M, 818 790 .phy_id_mask = 0xfffffff0, ··· 822 792 .config_init = bcm54xx_config_init, 823 793 .ack_interrupt = bcm_phy_ack_intr, 824 794 .config_intr = bcm_phy_config_intr, 795 + .handle_interrupt = bcm_phy_handle_interrupt, 825 796 }, { 826 797 .phy_id = PHY_ID_BCM57780, 827 798 .phy_id_mask = 0xfffffff0, ··· 831 800 .config_init = bcm54xx_config_init, 832 801 .ack_interrupt = bcm_phy_ack_intr, 833 802 .config_intr = bcm_phy_config_intr, 803 + .handle_interrupt = bcm_phy_handle_interrupt, 834 804 }, { 835 805 .phy_id = PHY_ID_BCMAC131, 836 806 .phy_id_mask = 0xfffffff0, ··· 840 808 .config_init = brcm_fet_config_init, 841 809 .ack_interrupt = brcm_fet_ack_interrupt, 842 810 .config_intr = brcm_fet_config_intr, 811 + .handle_interrupt = brcm_fet_handle_interrupt, 843 812 }, { 844 813 .phy_id = PHY_ID_BCM5241, 845 814 .phy_id_mask = 0xfffffff0, ··· 849 816 .config_init = brcm_fet_config_init, 850 817 .ack_interrupt = brcm_fet_ack_interrupt, 851 818 .config_intr = brcm_fet_config_intr, 819 + .handle_interrupt = brcm_fet_handle_interrupt, 852 820 }, { 853 821 .phy_id = PHY_ID_BCM5395, 854 822 .phy_id_mask = 0xfffffff0, ··· 873 839 .config_init = bcm54xx_config_init, 874 840 .ack_interrupt = bcm_phy_ack_intr, 875 841 .config_intr = bcm_phy_config_intr, 842 + .handle_interrupt = bcm_phy_handle_interrupt, 876 843 }, { 877 844 .phy_id = PHY_ID_BCM89610, 878 845 .phy_id_mask = 0xfffffff0, ··· 882 847 .config_init = bcm54xx_config_init, 883 848 .ack_interrupt = bcm_phy_ack_intr, 884 849 .config_intr = bcm_phy_config_intr, 850 + .handle_interrupt = bcm_phy_handle_interrupt, 885 851 } }; 886 852 887 853 module_phy_driver(broadcom_drivers);