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

net: phy: ti: 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: Dan Murphy <dmurphy@ti.com>
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Ioana Ciornei and committed by
Jakub Kicinski
1d1ae3c6 a4d77421

+191
+27
drivers/net/phy/dp83640.c
··· 50 50 #define MII_DP83640_MISR_LINK_INT_EN 0x20 51 51 #define MII_DP83640_MISR_ED_INT_EN 0x40 52 52 #define MII_DP83640_MISR_LQ_INT_EN 0x80 53 + #define MII_DP83640_MISR_ANC_INT 0x400 54 + #define MII_DP83640_MISR_DUP_INT 0x800 55 + #define MII_DP83640_MISR_SPD_INT 0x1000 56 + #define MII_DP83640_MISR_LINK_INT 0x2000 57 + #define MII_DP83640_MISR_INT_MASK (MII_DP83640_MISR_ANC_INT |\ 58 + MII_DP83640_MISR_DUP_INT |\ 59 + MII_DP83640_MISR_SPD_INT |\ 60 + MII_DP83640_MISR_LINK_INT) 53 61 54 62 /* phyter seems to miss the mark by 16 ns */ 55 63 #define ADJTIME_FIX 16 ··· 1201 1193 } 1202 1194 } 1203 1195 1196 + static irqreturn_t dp83640_handle_interrupt(struct phy_device *phydev) 1197 + { 1198 + int irq_status; 1199 + 1200 + irq_status = phy_read(phydev, MII_DP83640_MISR); 1201 + if (irq_status < 0) { 1202 + phy_error(phydev); 1203 + return IRQ_NONE; 1204 + } 1205 + 1206 + if (!(irq_status & MII_DP83640_MISR_INT_MASK)) 1207 + return IRQ_NONE; 1208 + 1209 + phy_trigger_machine(phydev); 1210 + 1211 + return IRQ_HANDLED; 1212 + } 1213 + 1204 1214 static int dp83640_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr) 1205 1215 { 1206 1216 struct dp83640_private *dp83640 = ··· 1543 1517 .config_init = dp83640_config_init, 1544 1518 .ack_interrupt = dp83640_ack_interrupt, 1545 1519 .config_intr = dp83640_config_intr, 1520 + .handle_interrupt = dp83640_handle_interrupt, 1546 1521 }; 1547 1522 1548 1523 static int __init dp83640_init(void)
+37
drivers/net/phy/dp83822.c
··· 303 303 return phy_write(phydev, MII_DP83822_PHYSCR, physcr_status); 304 304 } 305 305 306 + static irqreturn_t dp83822_handle_interrupt(struct phy_device *phydev) 307 + { 308 + int irq_status; 309 + 310 + /* The MISR1 and MISR2 registers are holding the interrupt status in 311 + * the upper half (15:8), while the lower half (7:0) is used for 312 + * controlling the interrupt enable state of those individual interrupt 313 + * sources. To determine the possible interrupt sources, just read the 314 + * MISR* register and use it directly to know which interrupts have 315 + * been enabled previously or not. 316 + */ 317 + irq_status = phy_read(phydev, MII_DP83822_MISR1); 318 + if (irq_status < 0) { 319 + phy_error(phydev); 320 + return IRQ_NONE; 321 + } 322 + if (irq_status & ((irq_status & GENMASK(7, 0)) << 8)) 323 + goto trigger_machine; 324 + 325 + irq_status = phy_read(phydev, MII_DP83822_MISR2); 326 + if (irq_status < 0) { 327 + phy_error(phydev); 328 + return IRQ_NONE; 329 + } 330 + if (irq_status & ((irq_status & GENMASK(7, 0)) << 8)) 331 + goto trigger_machine; 332 + 333 + return IRQ_NONE; 334 + 335 + trigger_machine: 336 + phy_trigger_machine(phydev); 337 + 338 + return IRQ_HANDLED; 339 + } 340 + 306 341 static int dp8382x_disable_wol(struct phy_device *phydev) 307 342 { 308 343 int value = DP83822_WOL_EN | DP83822_WOL_MAGIC_EN | ··· 611 576 .set_wol = dp83822_set_wol, \ 612 577 .ack_interrupt = dp83822_ack_interrupt, \ 613 578 .config_intr = dp83822_config_intr, \ 579 + .handle_interrupt = dp83822_handle_interrupt, \ 614 580 .suspend = dp83822_suspend, \ 615 581 .resume = dp83822_resume, \ 616 582 } ··· 627 591 .set_wol = dp83822_set_wol, \ 628 592 .ack_interrupt = dp83822_ack_interrupt, \ 629 593 .config_intr = dp83822_config_intr, \ 594 + .handle_interrupt = dp83822_handle_interrupt, \ 630 595 .suspend = dp83822_suspend, \ 631 596 .resume = dp83822_resume, \ 632 597 }
+33
drivers/net/phy/dp83848.c
··· 37 37 DP83848_MISR_SPD_INT_EN | \ 38 38 DP83848_MISR_LINK_INT_EN) 39 39 40 + #define DP83848_MISR_RHF_INT BIT(8) 41 + #define DP83848_MISR_FHF_INT BIT(9) 42 + #define DP83848_MISR_ANC_INT BIT(10) 43 + #define DP83848_MISR_DUP_INT BIT(11) 44 + #define DP83848_MISR_SPD_INT BIT(12) 45 + #define DP83848_MISR_LINK_INT BIT(13) 46 + #define DP83848_MISR_ED_INT BIT(14) 47 + 48 + #define DP83848_INT_MASK \ 49 + (DP83848_MISR_ANC_INT | \ 50 + DP83848_MISR_DUP_INT | \ 51 + DP83848_MISR_SPD_INT | \ 52 + DP83848_MISR_LINK_INT) 53 + 40 54 static int dp83848_ack_interrupt(struct phy_device *phydev) 41 55 { 42 56 int err = phy_read(phydev, DP83848_MISR); ··· 78 64 } 79 65 80 66 return phy_write(phydev, DP83848_MICR, control); 67 + } 68 + 69 + static irqreturn_t dp83848_handle_interrupt(struct phy_device *phydev) 70 + { 71 + int irq_status; 72 + 73 + irq_status = phy_read(phydev, DP83848_MISR); 74 + if (irq_status < 0) { 75 + phy_error(phydev); 76 + return IRQ_NONE; 77 + } 78 + 79 + if (!(irq_status & DP83848_INT_MASK)) 80 + return IRQ_NONE; 81 + 82 + phy_trigger_machine(phydev); 83 + 84 + return IRQ_HANDLED; 81 85 } 82 86 83 87 static int dp83848_config_init(struct phy_device *phydev) ··· 136 104 /* IRQ related */ \ 137 105 .ack_interrupt = dp83848_ack_interrupt, \ 138 106 .config_intr = dp83848_config_intr, \ 107 + .handle_interrupt = dp83848_handle_interrupt, \ 139 108 } 140 109 141 110 static struct phy_driver dp83848_driver[] = {
+25
drivers/net/phy/dp83867.c
··· 310 310 return phy_write(phydev, MII_DP83867_MICR, micr_status); 311 311 } 312 312 313 + static irqreturn_t dp83867_handle_interrupt(struct phy_device *phydev) 314 + { 315 + int irq_status, irq_enabled; 316 + 317 + irq_status = phy_read(phydev, MII_DP83867_ISR); 318 + if (irq_status < 0) { 319 + phy_error(phydev); 320 + return IRQ_NONE; 321 + } 322 + 323 + irq_enabled = phy_read(phydev, MII_DP83867_MICR); 324 + if (irq_enabled < 0) { 325 + phy_error(phydev); 326 + return IRQ_NONE; 327 + } 328 + 329 + if (!(irq_status & irq_enabled)) 330 + return IRQ_NONE; 331 + 332 + phy_trigger_machine(phydev); 333 + 334 + return IRQ_HANDLED; 335 + } 336 + 313 337 static int dp83867_read_status(struct phy_device *phydev) 314 338 { 315 339 int status = phy_read(phydev, MII_DP83867_PHYSTS); ··· 851 827 /* IRQ related */ 852 828 .ack_interrupt = dp83867_ack_interrupt, 853 829 .config_intr = dp83867_config_intr, 830 + .handle_interrupt = dp83867_handle_interrupt, 854 831 855 832 .suspend = genphy_suspend, 856 833 .resume = genphy_resume,
+25
drivers/net/phy/dp83869.c
··· 207 207 return phy_write(phydev, MII_DP83869_MICR, micr_status); 208 208 } 209 209 210 + static irqreturn_t dp83869_handle_interrupt(struct phy_device *phydev) 211 + { 212 + int irq_status, irq_enabled; 213 + 214 + irq_status = phy_read(phydev, MII_DP83869_ISR); 215 + if (irq_status < 0) { 216 + phy_error(phydev); 217 + return IRQ_NONE; 218 + } 219 + 220 + irq_enabled = phy_read(phydev, MII_DP83869_MICR); 221 + if (irq_enabled < 0) { 222 + phy_error(phydev); 223 + return IRQ_NONE; 224 + } 225 + 226 + if (!(irq_status & irq_enabled)) 227 + return IRQ_NONE; 228 + 229 + phy_trigger_machine(phydev); 230 + 231 + return IRQ_HANDLED; 232 + } 233 + 210 234 static int dp83869_set_wol(struct phy_device *phydev, 211 235 struct ethtool_wolinfo *wol) 212 236 { ··· 876 852 /* IRQ related */ 877 853 .ack_interrupt = dp83869_ack_interrupt, 878 854 .config_intr = dp83869_config_intr, 855 + .handle_interrupt = dp83869_handle_interrupt, 879 856 .read_status = dp83869_read_status, 880 857 881 858 .get_tunable = dp83869_get_tunable,
+44
drivers/net/phy/dp83tc811.c
··· 254 254 return err; 255 255 } 256 256 257 + static irqreturn_t dp83811_handle_interrupt(struct phy_device *phydev) 258 + { 259 + int irq_status; 260 + 261 + /* The INT_STAT registers 1, 2 and 3 are holding the interrupt status 262 + * in the upper half (15:8), while the lower half (7:0) is used for 263 + * controlling the interrupt enable state of those individual interrupt 264 + * sources. To determine the possible interrupt sources, just read the 265 + * INT_STAT* register and use it directly to know which interrupts have 266 + * been enabled previously or not. 267 + */ 268 + irq_status = phy_read(phydev, MII_DP83811_INT_STAT1); 269 + if (irq_status < 0) { 270 + phy_error(phydev); 271 + return IRQ_NONE; 272 + } 273 + if (irq_status & ((irq_status & GENMASK(7, 0)) << 8)) 274 + goto trigger_machine; 275 + 276 + irq_status = phy_read(phydev, MII_DP83811_INT_STAT2); 277 + if (irq_status < 0) { 278 + phy_error(phydev); 279 + return IRQ_NONE; 280 + } 281 + if (irq_status & ((irq_status & GENMASK(7, 0)) << 8)) 282 + goto trigger_machine; 283 + 284 + irq_status = phy_read(phydev, MII_DP83811_INT_STAT3); 285 + if (irq_status < 0) { 286 + phy_error(phydev); 287 + return IRQ_NONE; 288 + } 289 + if (irq_status & ((irq_status & GENMASK(7, 0)) << 8)) 290 + goto trigger_machine; 291 + 292 + return IRQ_NONE; 293 + 294 + trigger_machine: 295 + phy_trigger_machine(phydev); 296 + 297 + return IRQ_HANDLED; 298 + } 299 + 257 300 static int dp83811_config_aneg(struct phy_device *phydev) 258 301 { 259 302 int value, err; ··· 388 345 .set_wol = dp83811_set_wol, 389 346 .ack_interrupt = dp83811_ack_interrupt, 390 347 .config_intr = dp83811_config_intr, 348 + .handle_interrupt = dp83811_handle_interrupt, 391 349 .suspend = dp83811_suspend, 392 350 .resume = dp83811_resume, 393 351 },