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

Merge branch 'net-phy-add-support-for-shared-interrupts-part-3'

Ioana Ciornei says:

====================
net: phy: add support for shared interrupts (part 3)

This patch set aims to actually add support for shared interrupts in
phylib and not only for multi-PHY devices. While we are at it,
streamline the interrupt handling in phylib.

For a bit of context, at the moment, there are multiple phy_driver ops
that deal with this subject:

- .config_intr() - Enable/disable the interrupt line.

- .ack_interrupt() - Should quiesce any interrupts that may have been
fired. It's also used by phylib in conjunction with .config_intr() to
clear any pending interrupts after the line was disabled, and before
it is going to be enabled.

- .did_interrupt() - Intended for multi-PHY devices with a shared IRQ
line and used by phylib to discern which PHY from the package was the
one that actually fired the interrupt.

- .handle_interrupt() - Completely overrides the default interrupt
handling logic from phylib. The PHY driver is responsible for checking
if any interrupt was fired by the respective PHY and choose
accordingly if it's the one that should trigger the link state machine.

From my point of view, the interrupt handling in phylib has become
somewhat confusing with all these callbacks that actually read the same
PHY register - the interrupt status. A more streamlined approach would
be to just move the responsibility to write an interrupt handler to the
driver (as any other device driver does) and make .handle_interrupt()
the only way to deal with interrupts.

Another advantage with this approach would be that phylib would gain
support for shared IRQs between different PHY (not just multi-PHY
devices), something which at the moment would require extending every
PHY driver anyway in order to implement their .did_interrupt() callback
and duplicate the same logic as in .ack_interrupt(). The disadvantage
of making .did_interrupt() mandatory would be that we are slightly
changing the semantics of the phylib API and that would increase
confusion instead of reducing it.

What I am proposing is the following:

- As a first step, make the .ack_interrupt() callback optional so that
we do not break any PHY driver amid the transition.

- Every PHY driver gains a .handle_interrupt() implementation that, for
the most part, would look like below:

irq_status = phy_read(phydev, INTR_STATUS);
if (irq_status < 0) {
phy_error(phydev);
return IRQ_NONE;
}

if (!(irq_status & irq_mask))
return IRQ_NONE;

phy_trigger_machine(phydev);

return IRQ_HANDLED;

- Remove each PHY driver's implementation of the .ack_interrupt() by
actually taking care of quiescing any pending interrupts before
enabling/after disabling the interrupt line.

- Finally, after all drivers have been ported, remove the
.ack_interrupt() and .did_interrupt() callbacks from phy_driver.

This patch set is part 3 (and final) of the entire change set and it
addresses the remaining PHY drivers that have not been migrated
previosly. Also, it finally removed the .did_interrupt() and
.ack_interrupt() callbacks since they are of no use anymore.

I do not have access to most of these PHY's, therefore I Cc-ed the
latest contributors to the individual PHY drivers in order to have
access, hopefully, to more regression testing.
====================

Link: https://lore.kernel.org/r/20201123153817.1616814-1-ciorneiioana@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+508 -192
+36 -2
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 ··· 1159 1151 int err; 1160 1152 1161 1153 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 1154 + err = dp83640_ack_interrupt(phydev); 1155 + if (err) 1156 + return err; 1157 + 1162 1158 misr = phy_read(phydev, MII_DP83640_MISR); 1163 1159 if (misr < 0) 1164 1160 return misr; ··· 1201 1189 MII_DP83640_MISR_DUP_INT_EN | 1202 1190 MII_DP83640_MISR_SPD_INT_EN | 1203 1191 MII_DP83640_MISR_LINK_INT_EN); 1204 - return phy_write(phydev, MII_DP83640_MISR, misr); 1192 + err = phy_write(phydev, MII_DP83640_MISR, misr); 1193 + if (err) 1194 + return err; 1195 + 1196 + return dp83640_ack_interrupt(phydev); 1205 1197 } 1198 + } 1199 + 1200 + static irqreturn_t dp83640_handle_interrupt(struct phy_device *phydev) 1201 + { 1202 + int irq_status; 1203 + 1204 + irq_status = phy_read(phydev, MII_DP83640_MISR); 1205 + if (irq_status < 0) { 1206 + phy_error(phydev); 1207 + return IRQ_NONE; 1208 + } 1209 + 1210 + if (!(irq_status & MII_DP83640_MISR_INT_MASK)) 1211 + return IRQ_NONE; 1212 + 1213 + phy_trigger_machine(phydev); 1214 + 1215 + return IRQ_HANDLED; 1206 1216 } 1207 1217 1208 1218 static int dp83640_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr) ··· 1549 1515 .remove = dp83640_remove, 1550 1516 .soft_reset = dp83640_soft_reset, 1551 1517 .config_init = dp83640_config_init, 1552 - .ack_interrupt = dp83640_ack_interrupt, 1553 1518 .config_intr = dp83640_config_intr, 1519 + .handle_interrupt = dp83640_handle_interrupt, 1554 1520 }; 1555 1521 1556 1522 static int __init dp83640_init(void)
+37 -17
drivers/net/phy/dp83822.c
··· 119 119 u16 fx_sd_enable; 120 120 }; 121 121 122 - static int dp83822_ack_interrupt(struct phy_device *phydev) 123 - { 124 - int err; 125 - 126 - err = phy_read(phydev, MII_DP83822_MISR1); 127 - if (err < 0) 128 - return err; 129 - 130 - err = phy_read(phydev, MII_DP83822_MISR2); 131 - if (err < 0) 132 - return err; 133 - 134 - return 0; 135 - } 136 - 137 122 static int dp83822_set_wol(struct phy_device *phydev, 138 123 struct ethtool_wolinfo *wol) 139 124 { ··· 286 301 } 287 302 288 303 return phy_write(phydev, MII_DP83822_PHYSCR, physcr_status); 304 + } 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; 289 339 } 290 340 291 341 static int dp8382x_disable_wol(struct phy_device *phydev) ··· 594 574 .read_status = dp83822_read_status, \ 595 575 .get_wol = dp83822_get_wol, \ 596 576 .set_wol = dp83822_set_wol, \ 597 - .ack_interrupt = dp83822_ack_interrupt, \ 598 577 .config_intr = dp83822_config_intr, \ 578 + .handle_interrupt = dp83822_handle_interrupt, \ 599 579 .suspend = dp83822_suspend, \ 600 580 .resume = dp83822_resume, \ 601 581 } ··· 609 589 .config_init = dp8382x_config_init, \ 610 590 .get_wol = dp83822_get_wol, \ 611 591 .set_wol = dp83822_set_wol, \ 612 - .ack_interrupt = dp83822_ack_interrupt, \ 613 592 .config_intr = dp83822_config_intr, \ 593 + .handle_interrupt = dp83822_handle_interrupt, \ 614 594 .suspend = dp83822_suspend, \ 615 595 .resume = dp83822_resume, \ 616 596 }
+45 -2
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); ··· 67 53 return control; 68 54 69 55 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 56 + ret = dp83848_ack_interrupt(phydev); 57 + if (ret) 58 + return ret; 59 + 70 60 control |= DP83848_MICR_INT_OE; 71 61 control |= DP83848_MICR_INTEN; 72 62 73 63 ret = phy_write(phydev, DP83848_MISR, DP83848_INT_EN_MASK); 74 64 if (ret < 0) 75 65 return ret; 66 + 67 + ret = phy_write(phydev, DP83848_MICR, control); 76 68 } else { 77 69 control &= ~DP83848_MICR_INTEN; 70 + ret = phy_write(phydev, DP83848_MICR, control); 71 + if (ret) 72 + return ret; 73 + 74 + ret = dp83848_ack_interrupt(phydev); 78 75 } 79 76 80 - return phy_write(phydev, DP83848_MICR, control); 77 + return ret; 78 + } 79 + 80 + static irqreturn_t dp83848_handle_interrupt(struct phy_device *phydev) 81 + { 82 + int irq_status; 83 + 84 + irq_status = phy_read(phydev, DP83848_MISR); 85 + if (irq_status < 0) { 86 + phy_error(phydev); 87 + return IRQ_NONE; 88 + } 89 + 90 + if (!(irq_status & DP83848_INT_MASK)) 91 + return IRQ_NONE; 92 + 93 + phy_trigger_machine(phydev); 94 + 95 + return IRQ_HANDLED; 81 96 } 82 97 83 98 static int dp83848_config_init(struct phy_device *phydev) ··· 145 102 .resume = genphy_resume, \ 146 103 \ 147 104 /* IRQ related */ \ 148 - .ack_interrupt = dp83848_ack_interrupt, \ 149 105 .config_intr = dp83848_config_intr, \ 106 + .handle_interrupt = dp83848_handle_interrupt, \ 150 107 } 151 108 152 109 static struct phy_driver dp83848_driver[] = {
+39 -5
drivers/net/phy/dp83867.c
··· 288 288 289 289 static int dp83867_config_intr(struct phy_device *phydev) 290 290 { 291 - int micr_status; 291 + int micr_status, err; 292 292 293 293 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 294 + err = dp83867_ack_interrupt(phydev); 295 + if (err) 296 + return err; 297 + 294 298 micr_status = phy_read(phydev, MII_DP83867_MICR); 295 299 if (micr_status < 0) 296 300 return micr_status; ··· 307 303 MII_DP83867_MICR_DUP_MODE_CHNG_INT_EN | 308 304 MII_DP83867_MICR_SLEEP_MODE_CHNG_INT_EN); 309 305 310 - return phy_write(phydev, MII_DP83867_MICR, micr_status); 306 + err = phy_write(phydev, MII_DP83867_MICR, micr_status); 307 + } else { 308 + micr_status = 0x0; 309 + err = phy_write(phydev, MII_DP83867_MICR, micr_status); 310 + if (err) 311 + return err; 312 + 313 + err = dp83867_ack_interrupt(phydev); 311 314 } 312 315 313 - micr_status = 0x0; 314 - return phy_write(phydev, MII_DP83867_MICR, micr_status); 316 + return err; 317 + } 318 + 319 + static irqreturn_t dp83867_handle_interrupt(struct phy_device *phydev) 320 + { 321 + int irq_status, irq_enabled; 322 + 323 + irq_status = phy_read(phydev, MII_DP83867_ISR); 324 + if (irq_status < 0) { 325 + phy_error(phydev); 326 + return IRQ_NONE; 327 + } 328 + 329 + irq_enabled = phy_read(phydev, MII_DP83867_MICR); 330 + if (irq_enabled < 0) { 331 + phy_error(phydev); 332 + return IRQ_NONE; 333 + } 334 + 335 + if (!(irq_status & irq_enabled)) 336 + return IRQ_NONE; 337 + 338 + phy_trigger_machine(phydev); 339 + 340 + return IRQ_HANDLED; 315 341 } 316 342 317 343 static int dp83867_read_status(struct phy_device *phydev) ··· 859 825 .set_wol = dp83867_set_wol, 860 826 861 827 /* IRQ related */ 862 - .ack_interrupt = dp83867_ack_interrupt, 863 828 .config_intr = dp83867_config_intr, 829 + .handle_interrupt = dp83867_handle_interrupt, 864 830 865 831 .suspend = genphy_suspend, 866 832 .resume = genphy_resume,
+38 -4
drivers/net/phy/dp83869.c
··· 186 186 187 187 static int dp83869_config_intr(struct phy_device *phydev) 188 188 { 189 - int micr_status = 0; 189 + int micr_status = 0, err; 190 190 191 191 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 192 + err = dp83869_ack_interrupt(phydev); 193 + if (err) 194 + return err; 195 + 192 196 micr_status = phy_read(phydev, MII_DP83869_MICR); 193 197 if (micr_status < 0) 194 198 return micr_status; ··· 205 201 MII_DP83869_MICR_DUP_MODE_CHNG_INT_EN | 206 202 MII_DP83869_MICR_SLEEP_MODE_CHNG_INT_EN); 207 203 208 - return phy_write(phydev, MII_DP83869_MICR, micr_status); 204 + err = phy_write(phydev, MII_DP83869_MICR, micr_status); 205 + } else { 206 + err = phy_write(phydev, MII_DP83869_MICR, micr_status); 207 + if (err) 208 + return err; 209 + 210 + err = dp83869_ack_interrupt(phydev); 209 211 } 210 212 211 - return phy_write(phydev, MII_DP83869_MICR, micr_status); 213 + return err; 214 + } 215 + 216 + static irqreturn_t dp83869_handle_interrupt(struct phy_device *phydev) 217 + { 218 + int irq_status, irq_enabled; 219 + 220 + irq_status = phy_read(phydev, MII_DP83869_ISR); 221 + if (irq_status < 0) { 222 + phy_error(phydev); 223 + return IRQ_NONE; 224 + } 225 + 226 + irq_enabled = phy_read(phydev, MII_DP83869_MICR); 227 + if (irq_enabled < 0) { 228 + phy_error(phydev); 229 + return IRQ_NONE; 230 + } 231 + 232 + if (!(irq_status & irq_enabled)) 233 + return IRQ_NONE; 234 + 235 + phy_trigger_machine(phydev); 236 + 237 + return IRQ_HANDLED; 212 238 } 213 239 214 240 static int dp83869_set_wol(struct phy_device *phydev, ··· 884 850 .soft_reset = dp83869_phy_reset, 885 851 886 852 /* IRQ related */ 887 - .ack_interrupt = dp83869_ack_interrupt, 888 853 .config_intr = dp83869_config_intr, 854 + .handle_interrupt = dp83869_handle_interrupt, 889 855 .read_status = dp83869_read_status, 890 856 891 857 .get_tunable = dp83869_get_tunable,
+52 -1
drivers/net/phy/dp83tc811.c
··· 197 197 int misr_status, err; 198 198 199 199 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 200 + err = dp83811_ack_interrupt(phydev); 201 + if (err) 202 + return err; 203 + 200 204 misr_status = phy_read(phydev, MII_DP83811_INT_STAT1); 201 205 if (misr_status < 0) 202 206 return misr_status; ··· 253 249 return err; 254 250 255 251 err = phy_write(phydev, MII_DP83811_INT_STAT3, 0); 252 + if (err < 0) 253 + return err; 254 + 255 + err = dp83811_ack_interrupt(phydev); 256 256 } 257 257 258 258 return err; 259 + } 260 + 261 + static irqreturn_t dp83811_handle_interrupt(struct phy_device *phydev) 262 + { 263 + int irq_status; 264 + 265 + /* The INT_STAT registers 1, 2 and 3 are holding the interrupt status 266 + * in the upper half (15:8), while the lower half (7:0) is used for 267 + * controlling the interrupt enable state of those individual interrupt 268 + * sources. To determine the possible interrupt sources, just read the 269 + * INT_STAT* register and use it directly to know which interrupts have 270 + * been enabled previously or not. 271 + */ 272 + irq_status = phy_read(phydev, MII_DP83811_INT_STAT1); 273 + if (irq_status < 0) { 274 + phy_error(phydev); 275 + return IRQ_NONE; 276 + } 277 + if (irq_status & ((irq_status & GENMASK(7, 0)) << 8)) 278 + goto trigger_machine; 279 + 280 + irq_status = phy_read(phydev, MII_DP83811_INT_STAT2); 281 + if (irq_status < 0) { 282 + phy_error(phydev); 283 + return IRQ_NONE; 284 + } 285 + if (irq_status & ((irq_status & GENMASK(7, 0)) << 8)) 286 + goto trigger_machine; 287 + 288 + irq_status = phy_read(phydev, MII_DP83811_INT_STAT3); 289 + if (irq_status < 0) { 290 + phy_error(phydev); 291 + return IRQ_NONE; 292 + } 293 + if (irq_status & ((irq_status & GENMASK(7, 0)) << 8)) 294 + goto trigger_machine; 295 + 296 + return IRQ_NONE; 297 + 298 + trigger_machine: 299 + phy_trigger_machine(phydev); 300 + 301 + return IRQ_HANDLED; 259 302 } 260 303 261 304 static int dp83811_config_aneg(struct phy_device *phydev) ··· 394 343 .soft_reset = dp83811_phy_reset, 395 344 .get_wol = dp83811_get_wol, 396 345 .set_wol = dp83811_set_wol, 397 - .ack_interrupt = dp83811_ack_interrupt, 398 346 .config_intr = dp83811_config_intr, 347 + .handle_interrupt = dp83811_handle_interrupt, 399 348 .suspend = dp83811_suspend, 400 349 .resume = dp83811_resume, 401 350 },
+47 -27
drivers/net/phy/icplus.c
··· 272 272 return phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c); 273 273 } 274 274 275 - static int ip101a_g_config_intr(struct phy_device *phydev) 276 - { 277 - u16 val; 278 - 279 - if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 280 - /* INTR pin used: Speed/link/duplex will cause an interrupt */ 281 - val = IP101A_G_IRQ_PIN_USED; 282 - else 283 - val = IP101A_G_IRQ_ALL_MASK; 284 - 285 - return phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, val); 286 - } 287 - 288 - static int ip101a_g_did_interrupt(struct phy_device *phydev) 289 - { 290 - int val = phy_read(phydev, IP101A_G_IRQ_CONF_STATUS); 291 - 292 - if (val < 0) 293 - return 0; 294 - 295 - return val & (IP101A_G_IRQ_SPEED_CHANGE | 296 - IP101A_G_IRQ_DUPLEX_CHANGE | 297 - IP101A_G_IRQ_LINK_CHANGE); 298 - } 299 - 300 275 static int ip101a_g_ack_interrupt(struct phy_device *phydev) 301 276 { 302 277 int err = phy_read(phydev, IP101A_G_IRQ_CONF_STATUS); 278 + 303 279 if (err < 0) 304 280 return err; 305 281 306 282 return 0; 283 + } 284 + 285 + static int ip101a_g_config_intr(struct phy_device *phydev) 286 + { 287 + u16 val; 288 + int err; 289 + 290 + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 291 + err = ip101a_g_ack_interrupt(phydev); 292 + if (err) 293 + return err; 294 + 295 + /* INTR pin used: Speed/link/duplex will cause an interrupt */ 296 + val = IP101A_G_IRQ_PIN_USED; 297 + err = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, val); 298 + } else { 299 + val = IP101A_G_IRQ_ALL_MASK; 300 + err = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, val); 301 + if (err) 302 + return err; 303 + 304 + err = ip101a_g_ack_interrupt(phydev); 305 + } 306 + 307 + return err; 308 + } 309 + 310 + static irqreturn_t ip101a_g_handle_interrupt(struct phy_device *phydev) 311 + { 312 + int irq_status; 313 + 314 + irq_status = phy_read(phydev, IP101A_G_IRQ_CONF_STATUS); 315 + if (irq_status < 0) { 316 + phy_error(phydev); 317 + return IRQ_NONE; 318 + } 319 + 320 + if (!(irq_status & (IP101A_G_IRQ_SPEED_CHANGE | 321 + IP101A_G_IRQ_DUPLEX_CHANGE | 322 + IP101A_G_IRQ_LINK_CHANGE))) 323 + return IRQ_NONE; 324 + 325 + phy_trigger_machine(phydev); 326 + 327 + return IRQ_HANDLED; 307 328 } 308 329 309 330 static struct phy_driver icplus_driver[] = { ··· 353 332 /* PHY_BASIC_FEATURES */ 354 333 .probe = ip101a_g_probe, 355 334 .config_intr = ip101a_g_config_intr, 356 - .did_interrupt = ip101a_g_did_interrupt, 357 - .ack_interrupt = ip101a_g_ack_interrupt, 335 + .handle_interrupt = ip101a_g_handle_interrupt, 358 336 .config_init = &ip101a_g_config_init, 359 337 .suspend = genphy_suspend, 360 338 .resume = genphy_resume,
+43 -30
drivers/net/phy/intel-xway.c
··· 209 209 return (reg < 0) ? reg : 0; 210 210 } 211 211 212 - static int xway_gphy_did_interrupt(struct phy_device *phydev) 213 - { 214 - int reg; 215 - 216 - reg = phy_read(phydev, XWAY_MDIO_ISTAT); 217 - return reg & XWAY_MDIO_INIT_MASK; 218 - } 219 - 220 212 static int xway_gphy_config_intr(struct phy_device *phydev) 221 213 { 222 214 u16 mask = 0; 215 + int err; 223 216 224 - if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 217 + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 218 + err = xway_gphy_ack_interrupt(phydev); 219 + if (err) 220 + return err; 221 + 225 222 mask = XWAY_MDIO_INIT_MASK; 223 + err = phy_write(phydev, XWAY_MDIO_IMASK, mask); 224 + } else { 225 + err = phy_write(phydev, XWAY_MDIO_IMASK, mask); 226 + if (err) 227 + return err; 226 228 227 - return phy_write(phydev, XWAY_MDIO_IMASK, mask); 229 + err = xway_gphy_ack_interrupt(phydev); 230 + } 231 + 232 + return err; 233 + } 234 + 235 + static irqreturn_t xway_gphy_handle_interrupt(struct phy_device *phydev) 236 + { 237 + int irq_status; 238 + 239 + irq_status = phy_read(phydev, XWAY_MDIO_ISTAT); 240 + if (irq_status < 0) { 241 + phy_error(phydev); 242 + return IRQ_NONE; 243 + } 244 + 245 + if (!(irq_status & XWAY_MDIO_INIT_MASK)) 246 + return IRQ_NONE; 247 + 248 + phy_trigger_machine(phydev); 249 + 250 + return IRQ_HANDLED; 228 251 } 229 252 230 253 static struct phy_driver xway_gphy[] = { ··· 258 235 /* PHY_GBIT_FEATURES */ 259 236 .config_init = xway_gphy_config_init, 260 237 .config_aneg = xway_gphy14_config_aneg, 261 - .ack_interrupt = xway_gphy_ack_interrupt, 262 - .did_interrupt = xway_gphy_did_interrupt, 238 + .handle_interrupt = xway_gphy_handle_interrupt, 263 239 .config_intr = xway_gphy_config_intr, 264 240 .suspend = genphy_suspend, 265 241 .resume = genphy_resume, ··· 269 247 /* PHY_BASIC_FEATURES */ 270 248 .config_init = xway_gphy_config_init, 271 249 .config_aneg = xway_gphy14_config_aneg, 272 - .ack_interrupt = xway_gphy_ack_interrupt, 273 - .did_interrupt = xway_gphy_did_interrupt, 250 + .handle_interrupt = xway_gphy_handle_interrupt, 274 251 .config_intr = xway_gphy_config_intr, 275 252 .suspend = genphy_suspend, 276 253 .resume = genphy_resume, ··· 280 259 /* PHY_GBIT_FEATURES */ 281 260 .config_init = xway_gphy_config_init, 282 261 .config_aneg = xway_gphy14_config_aneg, 283 - .ack_interrupt = xway_gphy_ack_interrupt, 284 - .did_interrupt = xway_gphy_did_interrupt, 262 + .handle_interrupt = xway_gphy_handle_interrupt, 285 263 .config_intr = xway_gphy_config_intr, 286 264 .suspend = genphy_suspend, 287 265 .resume = genphy_resume, ··· 291 271 /* PHY_BASIC_FEATURES */ 292 272 .config_init = xway_gphy_config_init, 293 273 .config_aneg = xway_gphy14_config_aneg, 294 - .ack_interrupt = xway_gphy_ack_interrupt, 295 - .did_interrupt = xway_gphy_did_interrupt, 274 + .handle_interrupt = xway_gphy_handle_interrupt, 296 275 .config_intr = xway_gphy_config_intr, 297 276 .suspend = genphy_suspend, 298 277 .resume = genphy_resume, ··· 301 282 .name = "Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.5 / v1.6", 302 283 /* PHY_GBIT_FEATURES */ 303 284 .config_init = xway_gphy_config_init, 304 - .ack_interrupt = xway_gphy_ack_interrupt, 305 - .did_interrupt = xway_gphy_did_interrupt, 285 + .handle_interrupt = xway_gphy_handle_interrupt, 306 286 .config_intr = xway_gphy_config_intr, 307 287 .suspend = genphy_suspend, 308 288 .resume = genphy_resume, ··· 311 293 .name = "Intel XWAY PHY22F (PEF 7061) v1.5 / v1.6", 312 294 /* PHY_BASIC_FEATURES */ 313 295 .config_init = xway_gphy_config_init, 314 - .ack_interrupt = xway_gphy_ack_interrupt, 315 - .did_interrupt = xway_gphy_did_interrupt, 296 + .handle_interrupt = xway_gphy_handle_interrupt, 316 297 .config_intr = xway_gphy_config_intr, 317 298 .suspend = genphy_suspend, 318 299 .resume = genphy_resume, ··· 321 304 .name = "Intel XWAY PHY11G (xRX v1.1 integrated)", 322 305 /* PHY_GBIT_FEATURES */ 323 306 .config_init = xway_gphy_config_init, 324 - .ack_interrupt = xway_gphy_ack_interrupt, 325 - .did_interrupt = xway_gphy_did_interrupt, 307 + .handle_interrupt = xway_gphy_handle_interrupt, 326 308 .config_intr = xway_gphy_config_intr, 327 309 .suspend = genphy_suspend, 328 310 .resume = genphy_resume, ··· 331 315 .name = "Intel XWAY PHY22F (xRX v1.1 integrated)", 332 316 /* PHY_BASIC_FEATURES */ 333 317 .config_init = xway_gphy_config_init, 334 - .ack_interrupt = xway_gphy_ack_interrupt, 335 - .did_interrupt = xway_gphy_did_interrupt, 318 + .handle_interrupt = xway_gphy_handle_interrupt, 336 319 .config_intr = xway_gphy_config_intr, 337 320 .suspend = genphy_suspend, 338 321 .resume = genphy_resume, ··· 341 326 .name = "Intel XWAY PHY11G (xRX v1.2 integrated)", 342 327 /* PHY_GBIT_FEATURES */ 343 328 .config_init = xway_gphy_config_init, 344 - .ack_interrupt = xway_gphy_ack_interrupt, 345 - .did_interrupt = xway_gphy_did_interrupt, 329 + .handle_interrupt = xway_gphy_handle_interrupt, 346 330 .config_intr = xway_gphy_config_intr, 347 331 .suspend = genphy_suspend, 348 332 .resume = genphy_resume, ··· 351 337 .name = "Intel XWAY PHY22F (xRX v1.2 integrated)", 352 338 /* PHY_BASIC_FEATURES */ 353 339 .config_init = xway_gphy_config_init, 354 - .ack_interrupt = xway_gphy_ack_interrupt, 355 - .did_interrupt = xway_gphy_did_interrupt, 340 + .handle_interrupt = xway_gphy_handle_interrupt, 356 341 .config_intr = xway_gphy_config_intr, 357 342 .suspend = genphy_suspend, 358 343 .resume = genphy_resume,
+30 -7
drivers/net/phy/meson-gxl.c
··· 204 204 int ret; 205 205 206 206 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 207 + /* Ack any pending IRQ */ 208 + ret = meson_gxl_ack_interrupt(phydev); 209 + if (ret) 210 + return ret; 211 + 207 212 val = INTSRC_ANEG_PR 208 213 | INTSRC_PARALLEL_FAULT 209 214 | INTSRC_ANEG_LP_ACK 210 215 | INTSRC_LINK_DOWN 211 216 | INTSRC_REMOTE_FAULT 212 217 | INTSRC_ANEG_COMPLETE; 218 + ret = phy_write(phydev, INTSRC_MASK, val); 213 219 } else { 214 220 val = 0; 221 + ret = phy_write(phydev, INTSRC_MASK, val); 222 + 223 + /* Ack any pending IRQ */ 224 + ret = meson_gxl_ack_interrupt(phydev); 215 225 } 216 226 217 - /* Ack any pending IRQ */ 218 - ret = meson_gxl_ack_interrupt(phydev); 219 - if (ret) 220 - return ret; 227 + return ret; 228 + } 221 229 222 - return phy_write(phydev, INTSRC_MASK, val); 230 + static irqreturn_t meson_gxl_handle_interrupt(struct phy_device *phydev) 231 + { 232 + int irq_status; 233 + 234 + irq_status = phy_read(phydev, INTSRC_FLAG); 235 + if (irq_status < 0) { 236 + phy_error(phydev); 237 + return IRQ_NONE; 238 + } 239 + 240 + if (irq_status == 0) 241 + return IRQ_NONE; 242 + 243 + phy_trigger_machine(phydev); 244 + 245 + return IRQ_HANDLED; 223 246 } 224 247 225 248 static struct phy_driver meson_gxl_phy[] = { ··· 254 231 .soft_reset = genphy_soft_reset, 255 232 .config_init = meson_gxl_config_init, 256 233 .read_status = meson_gxl_read_status, 257 - .ack_interrupt = meson_gxl_ack_interrupt, 258 234 .config_intr = meson_gxl_config_intr, 235 + .handle_interrupt = meson_gxl_handle_interrupt, 259 236 .suspend = genphy_suspend, 260 237 .resume = genphy_resume, 261 238 }, { ··· 264 241 /* PHY_BASIC_FEATURES */ 265 242 .flags = PHY_IS_INTERNAL, 266 243 .soft_reset = genphy_soft_reset, 267 - .ack_interrupt = meson_gxl_ack_interrupt, 268 244 .config_intr = meson_gxl_config_intr, 245 + .handle_interrupt = meson_gxl_handle_interrupt, 269 246 .suspend = genphy_suspend, 270 247 .resume = genphy_resume, 271 248 },
+51 -18
drivers/net/phy/micrel.c
··· 48 48 #define KSZPHY_INTCS_LINK_UP BIT(8) 49 49 #define KSZPHY_INTCS_ALL (KSZPHY_INTCS_LINK_UP |\ 50 50 KSZPHY_INTCS_LINK_DOWN) 51 + #define KSZPHY_INTCS_LINK_DOWN_STATUS BIT(2) 52 + #define KSZPHY_INTCS_LINK_UP_STATUS BIT(0) 53 + #define KSZPHY_INTCS_STATUS (KSZPHY_INTCS_LINK_DOWN_STATUS |\ 54 + KSZPHY_INTCS_LINK_UP_STATUS) 51 55 52 56 /* PHY Control 1 */ 53 57 #define MII_KSZPHY_CTRL_1 0x1e ··· 162 158 static int kszphy_config_intr(struct phy_device *phydev) 163 159 { 164 160 const struct kszphy_type *type = phydev->drv->driver_data; 165 - int temp; 161 + int temp, err; 166 162 u16 mask; 167 163 168 164 if (type && type->interrupt_level_mask) ··· 178 174 phy_write(phydev, MII_KSZPHY_CTRL, temp); 179 175 180 176 /* enable / disable interrupts */ 181 - if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 182 - temp = KSZPHY_INTCS_ALL; 183 - else 184 - temp = 0; 177 + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 178 + err = kszphy_ack_interrupt(phydev); 179 + if (err) 180 + return err; 185 181 186 - return phy_write(phydev, MII_KSZPHY_INTCS, temp); 182 + temp = KSZPHY_INTCS_ALL; 183 + err = phy_write(phydev, MII_KSZPHY_INTCS, temp); 184 + } else { 185 + temp = 0; 186 + err = phy_write(phydev, MII_KSZPHY_INTCS, temp); 187 + if (err) 188 + return err; 189 + 190 + err = kszphy_ack_interrupt(phydev); 191 + } 192 + 193 + return err; 194 + } 195 + 196 + static irqreturn_t kszphy_handle_interrupt(struct phy_device *phydev) 197 + { 198 + int irq_status; 199 + 200 + irq_status = phy_read(phydev, MII_KSZPHY_INTCS); 201 + if (irq_status < 0) { 202 + phy_error(phydev); 203 + return IRQ_NONE; 204 + } 205 + 206 + if ((irq_status & KSZPHY_INTCS_STATUS)) 207 + return IRQ_NONE; 208 + 209 + phy_trigger_machine(phydev); 210 + 211 + return IRQ_HANDLED; 187 212 } 188 213 189 214 static int kszphy_rmii_clk_sel(struct phy_device *phydev, bool val) ··· 1193 1160 /* PHY_BASIC_FEATURES */ 1194 1161 .driver_data = &ks8737_type, 1195 1162 .config_init = kszphy_config_init, 1196 - .ack_interrupt = kszphy_ack_interrupt, 1197 1163 .config_intr = kszphy_config_intr, 1164 + .handle_interrupt = kszphy_handle_interrupt, 1198 1165 .suspend = genphy_suspend, 1199 1166 .resume = genphy_resume, 1200 1167 }, { ··· 1205 1172 .driver_data = &ksz8021_type, 1206 1173 .probe = kszphy_probe, 1207 1174 .config_init = kszphy_config_init, 1208 - .ack_interrupt = kszphy_ack_interrupt, 1209 1175 .config_intr = kszphy_config_intr, 1176 + .handle_interrupt = kszphy_handle_interrupt, 1210 1177 .get_sset_count = kszphy_get_sset_count, 1211 1178 .get_strings = kszphy_get_strings, 1212 1179 .get_stats = kszphy_get_stats, ··· 1220 1187 .driver_data = &ksz8021_type, 1221 1188 .probe = kszphy_probe, 1222 1189 .config_init = kszphy_config_init, 1223 - .ack_interrupt = kszphy_ack_interrupt, 1224 1190 .config_intr = kszphy_config_intr, 1191 + .handle_interrupt = kszphy_handle_interrupt, 1225 1192 .get_sset_count = kszphy_get_sset_count, 1226 1193 .get_strings = kszphy_get_strings, 1227 1194 .get_stats = kszphy_get_stats, ··· 1236 1203 .probe = kszphy_probe, 1237 1204 .config_init = ksz8041_config_init, 1238 1205 .config_aneg = ksz8041_config_aneg, 1239 - .ack_interrupt = kszphy_ack_interrupt, 1240 1206 .config_intr = kszphy_config_intr, 1207 + .handle_interrupt = kszphy_handle_interrupt, 1241 1208 .get_sset_count = kszphy_get_sset_count, 1242 1209 .get_strings = kszphy_get_strings, 1243 1210 .get_stats = kszphy_get_stats, ··· 1251 1218 .driver_data = &ksz8041_type, 1252 1219 .probe = kszphy_probe, 1253 1220 .config_init = kszphy_config_init, 1254 - .ack_interrupt = kszphy_ack_interrupt, 1255 1221 .config_intr = kszphy_config_intr, 1222 + .handle_interrupt = kszphy_handle_interrupt, 1256 1223 .get_sset_count = kszphy_get_sset_count, 1257 1224 .get_strings = kszphy_get_strings, 1258 1225 .get_stats = kszphy_get_stats, ··· 1264 1231 .driver_data = &ksz8051_type, 1265 1232 .probe = kszphy_probe, 1266 1233 .config_init = kszphy_config_init, 1267 - .ack_interrupt = kszphy_ack_interrupt, 1268 1234 .config_intr = kszphy_config_intr, 1235 + .handle_interrupt = kszphy_handle_interrupt, 1269 1236 .get_sset_count = kszphy_get_sset_count, 1270 1237 .get_strings = kszphy_get_strings, 1271 1238 .get_stats = kszphy_get_stats, ··· 1280 1247 .driver_data = &ksz8041_type, 1281 1248 .probe = kszphy_probe, 1282 1249 .config_init = kszphy_config_init, 1283 - .ack_interrupt = kszphy_ack_interrupt, 1284 1250 .config_intr = kszphy_config_intr, 1251 + .handle_interrupt = kszphy_handle_interrupt, 1285 1252 .get_sset_count = kszphy_get_sset_count, 1286 1253 .get_strings = kszphy_get_strings, 1287 1254 .get_stats = kszphy_get_stats, ··· 1295 1262 .driver_data = &ksz8081_type, 1296 1263 .probe = kszphy_probe, 1297 1264 .config_init = ksz8081_config_init, 1298 - .ack_interrupt = kszphy_ack_interrupt, 1299 1265 .config_intr = kszphy_config_intr, 1266 + .handle_interrupt = kszphy_handle_interrupt, 1300 1267 .get_sset_count = kszphy_get_sset_count, 1301 1268 .get_strings = kszphy_get_strings, 1302 1269 .get_stats = kszphy_get_stats, ··· 1308 1275 .phy_id_mask = MICREL_PHY_ID_MASK, 1309 1276 /* PHY_BASIC_FEATURES */ 1310 1277 .config_init = ksz8061_config_init, 1311 - .ack_interrupt = kszphy_ack_interrupt, 1312 1278 .config_intr = kszphy_config_intr, 1279 + .handle_interrupt = kszphy_handle_interrupt, 1313 1280 .suspend = genphy_suspend, 1314 1281 .resume = genphy_resume, 1315 1282 }, { ··· 1321 1288 .probe = kszphy_probe, 1322 1289 .get_features = ksz9031_get_features, 1323 1290 .config_init = ksz9021_config_init, 1324 - .ack_interrupt = kszphy_ack_interrupt, 1325 1291 .config_intr = kszphy_config_intr, 1292 + .handle_interrupt = kszphy_handle_interrupt, 1326 1293 .get_sset_count = kszphy_get_sset_count, 1327 1294 .get_strings = kszphy_get_strings, 1328 1295 .get_stats = kszphy_get_stats, ··· 1340 1307 .config_init = ksz9031_config_init, 1341 1308 .soft_reset = genphy_soft_reset, 1342 1309 .read_status = ksz9031_read_status, 1343 - .ack_interrupt = kszphy_ack_interrupt, 1344 1310 .config_intr = kszphy_config_intr, 1311 + .handle_interrupt = kszphy_handle_interrupt, 1345 1312 .get_sset_count = kszphy_get_sset_count, 1346 1313 .get_strings = kszphy_get_strings, 1347 1314 .get_stats = kszphy_get_stats, ··· 1369 1336 .probe = kszphy_probe, 1370 1337 .config_init = ksz9131_config_init, 1371 1338 .read_status = genphy_read_status, 1372 - .ack_interrupt = kszphy_ack_interrupt, 1373 1339 .config_intr = kszphy_config_intr, 1340 + .handle_interrupt = kszphy_handle_interrupt, 1374 1341 .get_sset_count = kszphy_get_sset_count, 1375 1342 .get_strings = kszphy_get_strings, 1376 1343 .get_stats = kszphy_get_stats,
+44 -14
drivers/net/phy/national.c
··· 63 63 phy_write(phydev, NS_EXP_MEM_DATA, data); 64 64 } 65 65 66 - static int ns_config_intr(struct phy_device *phydev) 67 - { 68 - int err; 69 - 70 - if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 71 - err = phy_write(phydev, DP83865_INT_MASK, 72 - DP83865_INT_MASK_DEFAULT); 73 - else 74 - err = phy_write(phydev, DP83865_INT_MASK, 0); 75 - 76 - return err; 77 - } 78 - 79 66 static int ns_ack_interrupt(struct phy_device *phydev) 80 67 { 81 68 int ret = phy_read(phydev, DP83865_INT_STATUS); ··· 74 87 ret = phy_write(phydev, DP83865_INT_CLEAR, ret & ~0x7); 75 88 76 89 return ret; 90 + } 91 + 92 + static irqreturn_t ns_handle_interrupt(struct phy_device *phydev) 93 + { 94 + int irq_status; 95 + 96 + irq_status = phy_read(phydev, DP83865_INT_STATUS); 97 + if (irq_status < 0) { 98 + phy_error(phydev); 99 + return IRQ_NONE; 100 + } 101 + 102 + if (!(irq_status & DP83865_INT_MASK_DEFAULT)) 103 + return IRQ_NONE; 104 + 105 + /* clear the interrupt */ 106 + phy_write(phydev, DP83865_INT_CLEAR, irq_status & ~0x7); 107 + 108 + phy_trigger_machine(phydev); 109 + 110 + return IRQ_HANDLED; 111 + } 112 + 113 + static int ns_config_intr(struct phy_device *phydev) 114 + { 115 + int err; 116 + 117 + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 118 + err = ns_ack_interrupt(phydev); 119 + if (err) 120 + return err; 121 + 122 + err = phy_write(phydev, DP83865_INT_MASK, 123 + DP83865_INT_MASK_DEFAULT); 124 + } else { 125 + err = phy_write(phydev, DP83865_INT_MASK, 0); 126 + if (err) 127 + return err; 128 + 129 + err = ns_ack_interrupt(phydev); 130 + } 131 + 132 + return err; 77 133 } 78 134 79 135 static void ns_giga_speed_fallback(struct phy_device *phydev, int mode) ··· 163 133 .name = "NatSemi DP83865", 164 134 /* PHY_GBIT_FEATURES */ 165 135 .config_init = ns_config_init, 166 - .ack_interrupt = ns_ack_interrupt, 167 136 .config_intr = ns_config_intr, 137 + .handle_interrupt = ns_handle_interrupt, 168 138 } }; 169 139 170 140 module_phy_driver(dp83865_driver);
+2 -46
drivers/net/phy/phy.c
··· 114 114 EXPORT_SYMBOL(phy_print_status); 115 115 116 116 /** 117 - * phy_clear_interrupt - Ack the phy device's interrupt 118 - * @phydev: the phy_device struct 119 - * 120 - * If the @phydev driver has an ack_interrupt function, call it to 121 - * ack and clear the phy device's interrupt. 122 - * 123 - * Returns 0 on success or < 0 on error. 124 - */ 125 - static int phy_clear_interrupt(struct phy_device *phydev) 126 - { 127 - if (phydev->drv->ack_interrupt) 128 - return phydev->drv->ack_interrupt(phydev); 129 - 130 - return 0; 131 - } 132 - 133 - /** 134 117 * phy_config_interrupt - configure the PHY device for the requested interrupts 135 118 * @phydev: the phy_device struct 136 119 * @interrupts: interrupt flags to configure for this @phydev ··· 926 943 */ 927 944 int phy_disable_interrupts(struct phy_device *phydev) 928 945 { 929 - int err; 930 - 931 946 /* Disable PHY interrupts */ 932 - err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED); 933 - if (err) 934 - return err; 935 - 936 - /* Clear the interrupt */ 937 - return phy_clear_interrupt(phydev); 947 + return phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED); 938 948 } 939 949 940 950 /** ··· 942 966 struct phy_device *phydev = phy_dat; 943 967 struct phy_driver *drv = phydev->drv; 944 968 945 - if (drv->handle_interrupt) 946 - return drv->handle_interrupt(phydev); 947 - 948 - if (drv->did_interrupt && !drv->did_interrupt(phydev)) 949 - return IRQ_NONE; 950 - 951 - /* reschedule state queue work to run as soon as possible */ 952 - phy_trigger_machine(phydev); 953 - 954 - /* did_interrupt() may have cleared the interrupt already */ 955 - if (!drv->did_interrupt && phy_clear_interrupt(phydev)) { 956 - phy_error(phydev); 957 - return IRQ_NONE; 958 - } 959 - 960 - return IRQ_HANDLED; 969 + return drv->handle_interrupt(phydev); 961 970 } 962 971 963 972 /** ··· 951 990 */ 952 991 static int phy_enable_interrupts(struct phy_device *phydev) 953 992 { 954 - int err = phy_clear_interrupt(phydev); 955 - 956 - if (err < 0) 957 - return err; 958 - 959 993 return phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED); 960 994 } 961 995
+1 -1
drivers/net/phy/phy_device.c
··· 2826 2826 2827 2827 static bool phy_drv_supports_irq(struct phy_driver *phydrv) 2828 2828 { 2829 - return phydrv->config_intr && (phydrv->ack_interrupt || phydrv->handle_interrupt); 2829 + return phydrv->config_intr && phydrv->handle_interrupt; 2830 2830 } 2831 2831 2832 2832 /**
+39 -3
drivers/net/phy/qsemi.c
··· 75 75 { 76 76 int err; 77 77 78 + /* The Interrupt Source register is not self-clearing, bits 4 and 5 are 79 + * cleared when MII_BMSR is read and bits 1 and 3 are cleared when 80 + * MII_EXPANSION is read 81 + */ 78 82 err = phy_read(phydev, MII_QS6612_ISR); 79 83 80 84 if (err < 0) ··· 100 96 static int qs6612_config_intr(struct phy_device *phydev) 101 97 { 102 98 int err; 103 - if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 99 + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 100 + /* clear any interrupts before enabling them */ 101 + err = qs6612_ack_interrupt(phydev); 102 + if (err) 103 + return err; 104 + 104 105 err = phy_write(phydev, MII_QS6612_IMR, 105 106 MII_QS6612_IMR_INIT); 106 - else 107 + } else { 107 108 err = phy_write(phydev, MII_QS6612_IMR, 0); 109 + if (err) 110 + return err; 111 + 112 + /* clear any leftover interrupts */ 113 + err = qs6612_ack_interrupt(phydev); 114 + } 108 115 109 116 return err; 110 117 118 + } 119 + 120 + static irqreturn_t qs6612_handle_interrupt(struct phy_device *phydev) 121 + { 122 + int irq_status; 123 + 124 + irq_status = phy_read(phydev, MII_QS6612_ISR); 125 + if (irq_status < 0) { 126 + phy_error(phydev); 127 + return IRQ_NONE; 128 + } 129 + 130 + if (!(irq_status & MII_QS6612_IMR_INIT)) 131 + return IRQ_NONE; 132 + 133 + /* the interrupt source register is not self-clearing */ 134 + qs6612_ack_interrupt(phydev); 135 + 136 + phy_trigger_machine(phydev); 137 + 138 + return IRQ_HANDLED; 111 139 } 112 140 113 141 static struct phy_driver qs6612_driver[] = { { ··· 148 112 .phy_id_mask = 0xfffffff0, 149 113 /* PHY_BASIC_FEATURES */ 150 114 .config_init = qs6612_config_init, 151 - .ack_interrupt = qs6612_ack_interrupt, 152 115 .config_intr = qs6612_config_intr, 116 + .handle_interrupt = qs6612_handle_interrupt, 153 117 } }; 154 118 155 119 module_phy_driver(qs6612_driver);
+4 -15
include/linux/phy.h
··· 743 743 /** @read_status: Determines the negotiated speed and duplex */ 744 744 int (*read_status)(struct phy_device *phydev); 745 745 746 - /** @ack_interrupt: Clears any pending interrupts */ 747 - int (*ack_interrupt)(struct phy_device *phydev); 748 - 749 - /** @config_intr: Enables or disables interrupts */ 750 - int (*config_intr)(struct phy_device *phydev); 751 - 752 - /** 753 - * @did_interrupt: Checks if the PHY generated an interrupt. 754 - * For multi-PHY devices with shared PHY interrupt pin 755 - * Set interrupt bits have to be cleared. 746 + /** @config_intr: Enables or disables interrupts. 747 + * It should also clear any pending interrupts prior to enabling the 748 + * IRQs and after disabling them. 756 749 */ 757 - int (*did_interrupt)(struct phy_device *phydev); 750 + int (*config_intr)(struct phy_device *phydev); 758 751 759 752 /** @handle_interrupt: Override default interrupt handling */ 760 753 irqreturn_t (*handle_interrupt)(struct phy_device *phydev); ··· 1480 1487 return __genphy_config_aneg(phydev, false); 1481 1488 } 1482 1489 1483 - static inline int genphy_no_ack_interrupt(struct phy_device *phydev) 1484 - { 1485 - return 0; 1486 - } 1487 1490 static inline int genphy_no_config_intr(struct phy_device *phydev) 1488 1491 { 1489 1492 return 0;