100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming/* 200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * drivers/net/phy/phy.c 300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * Framework for configuring and reading PHY devices 500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * Based on code in sungem_phy.c and gianfar_phy.c 600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * Author: Andy Fleming 800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * Copyright (c) 2004 Freescale Semiconductor, Inc. 100ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki * Copyright (c) 2006, 2007 Maciej W. Rozycki 1100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 1200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * This program is free software; you can redistribute it and/or modify it 1300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * under the terms of the GNU General Public License as published by the 1400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * Free Software Foundation; either version 2 of the License, or (at your 1500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * option) any later version. 1600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 1700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming */ 1800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/kernel.h> 1900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/string.h> 2000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/errno.h> 2100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/unistd.h> 2200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/interrupt.h> 2300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/init.h> 2400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/delay.h> 2500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/netdevice.h> 2600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/etherdevice.h> 2700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/skbuff.h> 2800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/mm.h> 2900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/module.h> 3000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/mii.h> 3100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/ethtool.h> 3200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <linux/phy.h> 333c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki#include <linux/timer.h> 343c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki#include <linux/workqueue.h> 3500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 3660063497a95e716c9a689af3be2687d261f115b4Arun Sharma#include <linux/atomic.h> 3700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <asm/io.h> 3800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <asm/irq.h> 3900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming#include <asm/uaccess.h> 4000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 41b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 42b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_print_status - Convenience function to print out the current phy status 43b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: the phy_device struct 44e13934563db047043ccead26412f552375cea90cAndy Fleming */ 45e13934563db047043ccead26412f552375cea90cAndy Flemingvoid phy_print_status(struct phy_device *phydev) 46e13934563db047043ccead26412f552375cea90cAndy Fleming{ 47fb28ad35906af2f042c94e2f9c0f898ef9acfa37Kay Sievers pr_info("PHY: %s - Link is %s", dev_name(&phydev->dev), 48e13934563db047043ccead26412f552375cea90cAndy Fleming phydev->link ? "Up" : "Down"); 49e13934563db047043ccead26412f552375cea90cAndy Fleming if (phydev->link) 50a40c9f88b5e3da500ddab9440e5ddac170c12281Uwe Kleine-König printk(KERN_CONT " - %d/%s", phydev->speed, 51e13934563db047043ccead26412f552375cea90cAndy Fleming DUPLEX_FULL == phydev->duplex ? 52e13934563db047043ccead26412f552375cea90cAndy Fleming "Full" : "Half"); 53e13934563db047043ccead26412f552375cea90cAndy Fleming 54a40c9f88b5e3da500ddab9440e5ddac170c12281Uwe Kleine-König printk(KERN_CONT "\n"); 55e13934563db047043ccead26412f552375cea90cAndy Fleming} 56e13934563db047043ccead26412f552375cea90cAndy FlemingEXPORT_SYMBOL(phy_print_status); 5700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 5800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 59b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 60b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_clear_interrupt - Ack the phy device's interrupt 61b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: the phy_device struct 62b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * 63b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * If the @phydev driver has an ack_interrupt function, call it to 64b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * ack and clear the phy device's interrupt. 65b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * 66b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * Returns 0 on success on < 0 on error. 67b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap */ 6889ff05ec553f3e70b8773c501da01bf7ad952cabstephen hemmingerstatic int phy_clear_interrupt(struct phy_device *phydev) 6900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 7000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming int err = 0; 7100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 7200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (phydev->drv->ack_interrupt) 7300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = phydev->drv->ack_interrupt(phydev); 7400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 7500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return err; 7600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 7700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 78b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 79b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_config_interrupt - configure the PHY device for the requested interrupts 80b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: the phy_device struct 81b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @interrupts: interrupt flags to configure for this @phydev 82b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * 83b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * Returns 0 on success on < 0 on error. 84b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap */ 8589ff05ec553f3e70b8773c501da01bf7ad952cabstephen hemmingerstatic int phy_config_interrupt(struct phy_device *phydev, u32 interrupts) 8600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 8700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming int err = 0; 8800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 8900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->interrupts = interrupts; 9000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (phydev->drv->config_intr) 9100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = phydev->drv->config_intr(phydev); 9200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 9300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return err; 9400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 9500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 9600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 97b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 98b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_aneg_done - return auto-negotiation status 99b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: target phy_device struct 10000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 101b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * Description: Reads the status register and returns 0 either if 10200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * auto-negotiation is incomplete, or if there was an error. 10300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * Returns BMSR_ANEGCOMPLETE if auto-negotiation is done. 10400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming */ 10500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingstatic inline int phy_aneg_done(struct phy_device *phydev) 10600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 10700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming int retval; 10800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 10900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming retval = phy_read(phydev, MII_BMSR); 11000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 11100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE); 11200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 11300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 11400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming/* A structure for mapping a particular speed and duplex 11500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * combination to a particular SUPPORTED and ADVERTISED value */ 11600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingstruct phy_setting { 11700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming int speed; 11800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming int duplex; 11900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming u32 setting; 12000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming}; 12100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 12200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming/* A mapping of all SUPPORTED settings to speed/duplex */ 123f71e130966ba429dbd24be08ddbcdf263df9a5adArjan van de Venstatic const struct phy_setting settings[] = { 12400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming { 12500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .speed = 10000, 12600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .duplex = DUPLEX_FULL, 12700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .setting = SUPPORTED_10000baseT_Full, 12800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming }, 12900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming { 13000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .speed = SPEED_1000, 13100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .duplex = DUPLEX_FULL, 13200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .setting = SUPPORTED_1000baseT_Full, 13300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming }, 13400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming { 13500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .speed = SPEED_1000, 13600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .duplex = DUPLEX_HALF, 13700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .setting = SUPPORTED_1000baseT_Half, 13800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming }, 13900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming { 14000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .speed = SPEED_100, 14100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .duplex = DUPLEX_FULL, 14200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .setting = SUPPORTED_100baseT_Full, 14300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming }, 14400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming { 14500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .speed = SPEED_100, 14600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .duplex = DUPLEX_HALF, 14700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .setting = SUPPORTED_100baseT_Half, 14800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming }, 14900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming { 15000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .speed = SPEED_10, 15100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .duplex = DUPLEX_FULL, 15200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .setting = SUPPORTED_10baseT_Full, 15300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming }, 15400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming { 15500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .speed = SPEED_10, 15600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .duplex = DUPLEX_HALF, 15700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming .setting = SUPPORTED_10baseT_Half, 15800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming }, 15900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming}; 16000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 161ff8ac60948ba819b89e9c87083e8050fc2f89999Denis Cheng#define MAX_NUM_SETTINGS ARRAY_SIZE(settings) 16200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 163b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 164b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_find_setting - find a PHY settings array entry that matches speed & duplex 165b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @speed: speed to match 166b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @duplex: duplex to match 16700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 168b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * Description: Searches the settings array for the setting which 16900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * matches the desired speed and duplex, and returns the index 17000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * of that setting. Returns the index of the last setting if 17100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * none of the others match. 17200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming */ 17300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingstatic inline int phy_find_setting(int speed, int duplex) 17400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 17500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming int idx = 0; 17600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 17700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming while (idx < ARRAY_SIZE(settings) && 17800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming (settings[idx].speed != speed || 17900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming settings[idx].duplex != duplex)) 18000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming idx++; 18100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 18200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1; 18300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 18400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 185b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 186b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_find_valid - find a PHY setting that matches the requested features mask 187b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @idx: The first index in settings[] to search 188b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @features: A mask of the valid settings 18900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 190b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * Description: Returns the index of the first valid setting less 19100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * than or equal to the one pointed to by idx, as determined by 19200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * the mask in features. Returns the index of the last setting 19300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * if nothing else matches. 19400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming */ 19500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingstatic inline int phy_find_valid(int idx, u32 features) 19600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 19700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming while (idx < MAX_NUM_SETTINGS && !(settings[idx].setting & features)) 19800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming idx++; 19900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 20000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1; 20100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 20200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 203b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 204b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_sanitize_settings - make sure the PHY is set to supported speed and duplex 205b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: the target phy_device struct 20600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 207b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * Description: Make sure the PHY is set to supported speeds and 20800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * duplexes. Drop down by one in this order: 1000/FULL, 209b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * 1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF. 21000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming */ 21189ff05ec553f3e70b8773c501da01bf7ad952cabstephen hemmingerstatic void phy_sanitize_settings(struct phy_device *phydev) 21200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 21300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming u32 features = phydev->supported; 21400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming int idx; 21500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 21600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming /* Sanitize settings based on PHY capabilities */ 21700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if ((features & SUPPORTED_Autoneg) == 0) 218163642a24a44d7b1d1e1b3cb8da25a142a919e24Domen Puncer phydev->autoneg = AUTONEG_DISABLE; 21900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 22000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming idx = phy_find_valid(phy_find_setting(phydev->speed, phydev->duplex), 22100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming features); 22200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 22300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->speed = settings[idx].speed; 22400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->duplex = settings[idx].duplex; 22500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 22600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 227b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 228b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_ethtool_sset - generic ethtool sset function, handles all the details 229b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: target phy_device struct 230b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @cmd: ethtool_cmd 23100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 23200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * A few notes about parameter checking: 23300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * - We don't set port or transceiver, so we don't care what they 23400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * were set to. 23500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * - phy_start_aneg() will make sure forced settings are sane, and 23600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * choose the next best ones from the ones selected, so we don't 237b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * care if ethtool tries to give us bad values. 23800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming */ 23900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingint phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd) 24000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 24125db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny u32 speed = ethtool_cmd_speed(cmd); 24225db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny 24300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (cmd->phy_address != phydev->addr) 24400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return -EINVAL; 24500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 24600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming /* We make sure that we don't pass unsupported 24700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * values in to the PHY */ 24800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming cmd->advertising &= phydev->supported; 24900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 25000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming /* Verify the settings we care about. */ 25100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE) 25200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return -EINVAL; 25300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 25400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0) 25500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return -EINVAL; 25600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 2578e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches if (cmd->autoneg == AUTONEG_DISABLE && 25825db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny ((speed != SPEED_1000 && 25925db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny speed != SPEED_100 && 26025db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny speed != SPEED_10) || 2618e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches (cmd->duplex != DUPLEX_HALF && 2628e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches cmd->duplex != DUPLEX_FULL))) 26300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return -EINVAL; 26400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 26500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->autoneg = cmd->autoneg; 26600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 26725db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny phydev->speed = speed; 26800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 26900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->advertising = cmd->advertising; 27000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 27100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (AUTONEG_ENABLE == cmd->autoneg) 27200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->advertising |= ADVERTISED_Autoneg; 27300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming else 27400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->advertising &= ~ADVERTISED_Autoneg; 27500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 27600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->duplex = cmd->duplex; 27700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 27800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming /* Restart the PHY */ 27900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phy_start_aneg(phydev); 28000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 28100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return 0; 28200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 2839f6d55d0846dd8628fd3eac15be377c4d3493c3eKumar GalaEXPORT_SYMBOL(phy_ethtool_sset); 28400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 28500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingint phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd) 28600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 28700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming cmd->supported = phydev->supported; 28800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 28900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming cmd->advertising = phydev->advertising; 29000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 291707394972093e2056e1e8cc39be19cf9bcb3e7b3David Decotigny ethtool_cmd_speed_set(cmd, phydev->speed); 29200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming cmd->duplex = phydev->duplex; 29300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming cmd->port = PORT_MII; 29400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming cmd->phy_address = phydev->addr; 29500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming cmd->transceiver = XCVR_EXTERNAL; 29600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming cmd->autoneg = phydev->autoneg; 29700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 29800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return 0; 29900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 3009f6d55d0846dd8628fd3eac15be377c4d3493c3eKumar GalaEXPORT_SYMBOL(phy_ethtool_gset); 30100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 302b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 303b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_mii_ioctl - generic PHY MII ioctl interface 304b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: the phy_device struct 30500c7d9202a19091d1873954ba158375d2efd5a64Randy Dunlap * @ifr: &struct ifreq for socket ioctl's 306b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @cmd: ioctl cmd to execute 307b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * 308b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * Note that this function is currently incompatible with the 30900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * PHYCONTROL layer. It changes registers without regard to 310b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * current state. Use at own risk. 31100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming */ 31200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingint phy_mii_ioctl(struct phy_device *phydev, 31328b041139e344ecd0f144d6205b004ae354cfa1eRichard Cochran struct ifreq *ifr, int cmd) 31400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 31528b041139e344ecd0f144d6205b004ae354cfa1eRichard Cochran struct mii_ioctl_data *mii_data = if_mii(ifr); 31600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming u16 val = mii_data->val_in; 31700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 31800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming switch (cmd) { 31900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case SIOCGMIIPHY: 32000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming mii_data->phy_id = phydev->addr; 321c6d6a511d768cf7627ab54fc18f40edf85097362Lennert Buytenhek /* fall through */ 322c6d6a511d768cf7627ab54fc18f40edf85097362Lennert Buytenhek 32300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case SIOCGMIIREG: 324af1dc13e607c1d1a909e21ee87aafbe7b9d4ae81Peter Korsgaard mii_data->val_out = mdiobus_read(phydev->bus, mii_data->phy_id, 325af1dc13e607c1d1a909e21ee87aafbe7b9d4ae81Peter Korsgaard mii_data->reg_num); 32600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 32700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 32800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case SIOCSMIIREG: 32900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (mii_data->phy_id == phydev->addr) { 33000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming switch(mii_data->reg_num) { 33100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case MII_BMCR: 332163642a24a44d7b1d1e1b3cb8da25a142a919e24Domen Puncer if ((val & (BMCR_RESET|BMCR_ANENABLE)) == 0) 33300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->autoneg = AUTONEG_DISABLE; 33400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming else 33500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->autoneg = AUTONEG_ENABLE; 33600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if ((!phydev->autoneg) && (val & BMCR_FULLDPLX)) 33700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->duplex = DUPLEX_FULL; 33800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming else 33900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->duplex = DUPLEX_HALF; 340024a0a3cfb4c98cb3c6c81ec70672c6a925cf164Shan Lu if ((!phydev->autoneg) && 341024a0a3cfb4c98cb3c6c81ec70672c6a925cf164Shan Lu (val & BMCR_SPEED1000)) 342024a0a3cfb4c98cb3c6c81ec70672c6a925cf164Shan Lu phydev->speed = SPEED_1000; 343024a0a3cfb4c98cb3c6c81ec70672c6a925cf164Shan Lu else if ((!phydev->autoneg) && 344024a0a3cfb4c98cb3c6c81ec70672c6a925cf164Shan Lu (val & BMCR_SPEED100)) 345024a0a3cfb4c98cb3c6c81ec70672c6a925cf164Shan Lu phydev->speed = SPEED_100; 34600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 34700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case MII_ADVERTISE: 34800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->advertising = val; 34900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 35000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming default: 35100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming /* do nothing */ 35200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 35300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming } 35400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming } 35500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 356af1dc13e607c1d1a909e21ee87aafbe7b9d4ae81Peter Korsgaard mdiobus_write(phydev->bus, mii_data->phy_id, 357af1dc13e607c1d1a909e21ee87aafbe7b9d4ae81Peter Korsgaard mii_data->reg_num, val); 358af1dc13e607c1d1a909e21ee87aafbe7b9d4ae81Peter Korsgaard 3598e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches if (mii_data->reg_num == MII_BMCR && 3608e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches val & BMCR_RESET && 3618e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches phydev->drv->config_init) { 362f62220d3a9ccb879c3f90f845ae57b724b7bbb62Andy Fleming phy_scan_fixups(phydev); 36300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->drv->config_init(phydev); 364f62220d3a9ccb879c3f90f845ae57b724b7bbb62Andy Fleming } 36500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 366dda93b486a25009456fca6b9c925ab4d7c6b6d6aDavid Woodhouse 367c1f19b51d1d87f3e3bb7e6648f43f7d57ed2da6bRichard Cochran case SIOCSHWTSTAMP: 368c1f19b51d1d87f3e3bb7e6648f43f7d57ed2da6bRichard Cochran if (phydev->drv->hwtstamp) 369c1f19b51d1d87f3e3bb7e6648f43f7d57ed2da6bRichard Cochran return phydev->drv->hwtstamp(phydev, ifr); 370c1f19b51d1d87f3e3bb7e6648f43f7d57ed2da6bRichard Cochran /* fall through */ 371c1f19b51d1d87f3e3bb7e6648f43f7d57ed2da6bRichard Cochran 372dda93b486a25009456fca6b9c925ab4d7c6b6d6aDavid Woodhouse default: 373c6d6a511d768cf7627ab54fc18f40edf85097362Lennert Buytenhek return -EOPNOTSUPP; 37400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming } 37500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 37600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return 0; 37700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 378680e9fe9d69ea86e81c859932bfd751be91cc0e0Domen PuncerEXPORT_SYMBOL(phy_mii_ioctl); 37900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 380b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 381b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_start_aneg - start auto-negotiation for this PHY device 382b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: the phy_device struct 383e13934563db047043ccead26412f552375cea90cAndy Fleming * 384b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * Description: Sanitizes the settings (if we're not autonegotiating 385b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * them), and then calls the driver's config_aneg function. 386b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * If the PHYCONTROL Layer is operating, we change the state to 387b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * reflect the beginning of Auto-negotiation or forcing. 388e13934563db047043ccead26412f552375cea90cAndy Fleming */ 389e13934563db047043ccead26412f552375cea90cAndy Flemingint phy_start_aneg(struct phy_device *phydev) 390e13934563db047043ccead26412f552375cea90cAndy Fleming{ 391e13934563db047043ccead26412f552375cea90cAndy Fleming int err; 392e13934563db047043ccead26412f552375cea90cAndy Fleming 39335b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case mutex_lock(&phydev->lock); 394e13934563db047043ccead26412f552375cea90cAndy Fleming 395e13934563db047043ccead26412f552375cea90cAndy Fleming if (AUTONEG_DISABLE == phydev->autoneg) 396e13934563db047043ccead26412f552375cea90cAndy Fleming phy_sanitize_settings(phydev); 397e13934563db047043ccead26412f552375cea90cAndy Fleming 398e13934563db047043ccead26412f552375cea90cAndy Fleming err = phydev->drv->config_aneg(phydev); 399e13934563db047043ccead26412f552375cea90cAndy Fleming 400e13934563db047043ccead26412f552375cea90cAndy Fleming if (err < 0) 401e13934563db047043ccead26412f552375cea90cAndy Fleming goto out_unlock; 402e13934563db047043ccead26412f552375cea90cAndy Fleming 403e13934563db047043ccead26412f552375cea90cAndy Fleming if (phydev->state != PHY_HALTED) { 404e13934563db047043ccead26412f552375cea90cAndy Fleming if (AUTONEG_ENABLE == phydev->autoneg) { 405e13934563db047043ccead26412f552375cea90cAndy Fleming phydev->state = PHY_AN; 406e13934563db047043ccead26412f552375cea90cAndy Fleming phydev->link_timeout = PHY_AN_TIMEOUT; 407e13934563db047043ccead26412f552375cea90cAndy Fleming } else { 408e13934563db047043ccead26412f552375cea90cAndy Fleming phydev->state = PHY_FORCING; 409e13934563db047043ccead26412f552375cea90cAndy Fleming phydev->link_timeout = PHY_FORCE_TIMEOUT; 410e13934563db047043ccead26412f552375cea90cAndy Fleming } 411e13934563db047043ccead26412f552375cea90cAndy Fleming } 412e13934563db047043ccead26412f552375cea90cAndy Fleming 413e13934563db047043ccead26412f552375cea90cAndy Flemingout_unlock: 41435b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case mutex_unlock(&phydev->lock); 415e13934563db047043ccead26412f552375cea90cAndy Fleming return err; 416e13934563db047043ccead26412f552375cea90cAndy Fleming} 417e13934563db047043ccead26412f552375cea90cAndy FlemingEXPORT_SYMBOL(phy_start_aneg); 418e13934563db047043ccead26412f552375cea90cAndy Fleming 419e13934563db047043ccead26412f552375cea90cAndy Fleming 420c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howellsstatic void phy_change(struct work_struct *work); 421e13934563db047043ccead26412f552375cea90cAndy Fleming 422b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 423b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_start_machine - start PHY state machine tracking 424b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: the phy_device struct 425b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @handler: callback function for state change notifications 42600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 427b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * Description: The PHY infrastructure can run a state machine 42800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * which tracks whether the PHY is starting up, negotiating, 42900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * etc. This function starts the timer which tracks the state 430b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * of the PHY. If you want to be notified when the state changes, 431b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * pass in the callback @handler, otherwise, pass NULL. If you 43200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * want to maintain your own state machine, do not call this 433b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * function. 434b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap */ 43500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingvoid phy_start_machine(struct phy_device *phydev, 43600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming void (*handler)(struct net_device *)) 43700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 43800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->adjust_state = handler; 43900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 4403664090e199f10cb0282097faae8f8ca58c1e4aeAtsushi Nemoto schedule_delayed_work(&phydev->state_queue, HZ); 44100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 44200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 443b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 444b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_stop_machine - stop the PHY state machine tracking 445b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: target phy_device struct 44600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 447b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * Description: Stops the state machine timer, sets the state to UP 448817acf5ebd9ea21f134fc90064b0f6686c5b169dSergei Shtylylov * (unless it wasn't up yet). This function must be called BEFORE 44900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * phy_detach. 45000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming */ 45100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingvoid phy_stop_machine(struct phy_device *phydev) 45200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 453a390d1f379cf821248b735f43d2e1147ebb8241dMarcin Slusarz cancel_delayed_work_sync(&phydev->state_queue); 45400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 45535b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case mutex_lock(&phydev->lock); 45600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (phydev->state > PHY_UP) 45700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->state = PHY_UP; 45835b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case mutex_unlock(&phydev->lock); 45900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 46000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->adjust_state = NULL; 46100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 46200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 463b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 464b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_force_reduction - reduce PHY speed/duplex settings by one step 465b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: target phy_device struct 466e13934563db047043ccead26412f552375cea90cAndy Fleming * 467b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * Description: Reduces the speed/duplex settings by one notch, 468b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * in this order-- 469b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * 1000/FULL, 1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF. 470b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * The function bottoms out at 10/HALF. 471e13934563db047043ccead26412f552375cea90cAndy Fleming */ 472e13934563db047043ccead26412f552375cea90cAndy Flemingstatic void phy_force_reduction(struct phy_device *phydev) 473e13934563db047043ccead26412f552375cea90cAndy Fleming{ 474e13934563db047043ccead26412f552375cea90cAndy Fleming int idx; 475e13934563db047043ccead26412f552375cea90cAndy Fleming 476e13934563db047043ccead26412f552375cea90cAndy Fleming idx = phy_find_setting(phydev->speed, phydev->duplex); 477e13934563db047043ccead26412f552375cea90cAndy Fleming 478e13934563db047043ccead26412f552375cea90cAndy Fleming idx++; 479e13934563db047043ccead26412f552375cea90cAndy Fleming 480e13934563db047043ccead26412f552375cea90cAndy Fleming idx = phy_find_valid(idx, phydev->supported); 481e13934563db047043ccead26412f552375cea90cAndy Fleming 482e13934563db047043ccead26412f552375cea90cAndy Fleming phydev->speed = settings[idx].speed; 483e13934563db047043ccead26412f552375cea90cAndy Fleming phydev->duplex = settings[idx].duplex; 484e13934563db047043ccead26412f552375cea90cAndy Fleming 485e13934563db047043ccead26412f552375cea90cAndy Fleming pr_info("Trying %d/%s\n", phydev->speed, 486e13934563db047043ccead26412f552375cea90cAndy Fleming DUPLEX_FULL == phydev->duplex ? 487e13934563db047043ccead26412f552375cea90cAndy Fleming "FULL" : "HALF"); 488e13934563db047043ccead26412f552375cea90cAndy Fleming} 489e13934563db047043ccead26412f552375cea90cAndy Fleming 490e13934563db047043ccead26412f552375cea90cAndy Fleming 491b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 492b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_error - enter HALTED state for this PHY device 493b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: target phy_device struct 49400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * 49500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * Moves the PHY to the HALTED state in response to a read 49600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * or write error, and tells the controller the link is down. 49700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * Must not be called from interrupt context, or while the 49800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * phydev->lock is held. 49900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming */ 5009b9a8bfc8dfbe09dc57f274e32e8b06151abbad7Andy Flemingstatic void phy_error(struct phy_device *phydev) 50100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 50235b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case mutex_lock(&phydev->lock); 50300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->state = PHY_HALTED; 50435b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case mutex_unlock(&phydev->lock); 50500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 50600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 507b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 508b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_interrupt - PHY interrupt handler 509b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @irq: interrupt line 510b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phy_dat: phy_device pointer 511e13934563db047043ccead26412f552375cea90cAndy Fleming * 512b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * Description: When a PHY interrupt occurs, the handler disables 513e13934563db047043ccead26412f552375cea90cAndy Fleming * interrupts, and schedules a work task to clear the interrupt. 514e13934563db047043ccead26412f552375cea90cAndy Fleming */ 5157d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t phy_interrupt(int irq, void *phy_dat) 516e13934563db047043ccead26412f552375cea90cAndy Fleming{ 517e13934563db047043ccead26412f552375cea90cAndy Fleming struct phy_device *phydev = phy_dat; 518e13934563db047043ccead26412f552375cea90cAndy Fleming 5193c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki if (PHY_HALTED == phydev->state) 5203c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki return IRQ_NONE; /* It can't be ours. */ 5213c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki 522e13934563db047043ccead26412f552375cea90cAndy Fleming /* The MDIO bus is not allowed to be written in interrupt 523e13934563db047043ccead26412f552375cea90cAndy Fleming * context, so we need to disable the irq here. A work 524e13934563db047043ccead26412f552375cea90cAndy Fleming * queue will write the PHY to disable and clear the 525e13934563db047043ccead26412f552375cea90cAndy Fleming * interrupt, and then reenable the irq line. */ 526e13934563db047043ccead26412f552375cea90cAndy Fleming disable_irq_nosync(irq); 5270ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki atomic_inc(&phydev->irq_disable); 528e13934563db047043ccead26412f552375cea90cAndy Fleming 529e13934563db047043ccead26412f552375cea90cAndy Fleming schedule_work(&phydev->phy_queue); 530e13934563db047043ccead26412f552375cea90cAndy Fleming 531e13934563db047043ccead26412f552375cea90cAndy Fleming return IRQ_HANDLED; 532e13934563db047043ccead26412f552375cea90cAndy Fleming} 533e13934563db047043ccead26412f552375cea90cAndy Fleming 534b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 535b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_enable_interrupts - Enable the interrupts from the PHY side 536b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: target phy_device struct 537b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap */ 53889ff05ec553f3e70b8773c501da01bf7ad952cabstephen hemmingerstatic int phy_enable_interrupts(struct phy_device *phydev) 53900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 54000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming int err; 54100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 542e13934563db047043ccead26412f552375cea90cAndy Fleming err = phy_clear_interrupt(phydev); 54300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 544e13934563db047043ccead26412f552375cea90cAndy Fleming if (err < 0) 545e13934563db047043ccead26412f552375cea90cAndy Fleming return err; 54600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 547e13934563db047043ccead26412f552375cea90cAndy Fleming err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED); 54800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 54900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return err; 55000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 55100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 552b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 553b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_disable_interrupts - Disable the PHY interrupts from the PHY side 554b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: target phy_device struct 555b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap */ 55689ff05ec553f3e70b8773c501da01bf7ad952cabstephen hemmingerstatic int phy_disable_interrupts(struct phy_device *phydev) 55700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 55800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming int err; 55900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 56000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming /* Disable PHY interrupts */ 56100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED); 56200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 56300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err) 56400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming goto phy_err; 56500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 56600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming /* Clear the interrupt */ 56700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = phy_clear_interrupt(phydev); 56800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 56900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err) 57000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming goto phy_err; 57100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 57200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return 0; 57300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 57400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Flemingphy_err: 57500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phy_error(phydev); 57600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 57700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming return err; 57800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming} 579e13934563db047043ccead26412f552375cea90cAndy Fleming 580b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 581b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_start_interrupts - request and enable interrupts for a PHY device 582b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: target phy_device struct 583e13934563db047043ccead26412f552375cea90cAndy Fleming * 584b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * Description: Request the interrupt for the given PHY. 585b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * If this fails, then we set irq to PHY_POLL. 586e13934563db047043ccead26412f552375cea90cAndy Fleming * Otherwise, we enable the interrupts in the PHY. 587e13934563db047043ccead26412f552375cea90cAndy Fleming * This should only be called with a valid IRQ number. 588b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * Returns 0 on success or < 0 on error. 589e13934563db047043ccead26412f552375cea90cAndy Fleming */ 590e13934563db047043ccead26412f552375cea90cAndy Flemingint phy_start_interrupts(struct phy_device *phydev) 591e13934563db047043ccead26412f552375cea90cAndy Fleming{ 592e13934563db047043ccead26412f552375cea90cAndy Fleming int err = 0; 593e13934563db047043ccead26412f552375cea90cAndy Fleming 594c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells INIT_WORK(&phydev->phy_queue, phy_change); 595e13934563db047043ccead26412f552375cea90cAndy Fleming 5960ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki atomic_set(&phydev->irq_disable, 0); 597e13934563db047043ccead26412f552375cea90cAndy Fleming if (request_irq(phydev->irq, phy_interrupt, 5981fb9df5d3069064c037c81c0ab8bf783ffa5e373Thomas Gleixner IRQF_SHARED, 599e13934563db047043ccead26412f552375cea90cAndy Fleming "phy_interrupt", 600e13934563db047043ccead26412f552375cea90cAndy Fleming phydev) < 0) { 601e13934563db047043ccead26412f552375cea90cAndy Fleming printk(KERN_WARNING "%s: Can't get IRQ %d (PHY)\n", 602e13934563db047043ccead26412f552375cea90cAndy Fleming phydev->bus->name, 603e13934563db047043ccead26412f552375cea90cAndy Fleming phydev->irq); 604e13934563db047043ccead26412f552375cea90cAndy Fleming phydev->irq = PHY_POLL; 605e13934563db047043ccead26412f552375cea90cAndy Fleming return 0; 606e13934563db047043ccead26412f552375cea90cAndy Fleming } 607e13934563db047043ccead26412f552375cea90cAndy Fleming 608e13934563db047043ccead26412f552375cea90cAndy Fleming err = phy_enable_interrupts(phydev); 609e13934563db047043ccead26412f552375cea90cAndy Fleming 610e13934563db047043ccead26412f552375cea90cAndy Fleming return err; 611e13934563db047043ccead26412f552375cea90cAndy Fleming} 612e13934563db047043ccead26412f552375cea90cAndy FlemingEXPORT_SYMBOL(phy_start_interrupts); 613e13934563db047043ccead26412f552375cea90cAndy Fleming 614b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 615b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_stop_interrupts - disable interrupts from a PHY device 616b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: target phy_device struct 617b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap */ 618e13934563db047043ccead26412f552375cea90cAndy Flemingint phy_stop_interrupts(struct phy_device *phydev) 619e13934563db047043ccead26412f552375cea90cAndy Fleming{ 620e13934563db047043ccead26412f552375cea90cAndy Fleming int err; 621e13934563db047043ccead26412f552375cea90cAndy Fleming 622e13934563db047043ccead26412f552375cea90cAndy Fleming err = phy_disable_interrupts(phydev); 623e13934563db047043ccead26412f552375cea90cAndy Fleming 624e13934563db047043ccead26412f552375cea90cAndy Fleming if (err) 625e13934563db047043ccead26412f552375cea90cAndy Fleming phy_error(phydev); 626e13934563db047043ccead26412f552375cea90cAndy Fleming 6270ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki free_irq(phydev->irq, phydev); 6280ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki 6293c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki /* 6300ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki * Cannot call flush_scheduled_work() here as desired because 6310ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki * of rtnl_lock(), but we do not really care about what would 6320ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki * be done, except from enable_irq(), so cancel any work 6330ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki * possibly pending and take care of the matter below. 6343c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki */ 63528e53bddf814485699a4142bc056fd37d4e11dd4Oleg Nesterov cancel_work_sync(&phydev->phy_queue); 6360ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki /* 6370ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki * If work indeed has been cancelled, disable_irq() will have 6380ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki * been left unbalanced from phy_interrupt() and enable_irq() 6390ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki * has to be called so that other devices on the line work. 6400ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki */ 6410ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki while (atomic_dec_return(&phydev->irq_disable) >= 0) 6420ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki enable_irq(phydev->irq); 643e13934563db047043ccead26412f552375cea90cAndy Fleming 644e13934563db047043ccead26412f552375cea90cAndy Fleming return err; 645e13934563db047043ccead26412f552375cea90cAndy Fleming} 646e13934563db047043ccead26412f552375cea90cAndy FlemingEXPORT_SYMBOL(phy_stop_interrupts); 647e13934563db047043ccead26412f552375cea90cAndy Fleming 648e13934563db047043ccead26412f552375cea90cAndy Fleming 649b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 650b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_change - Scheduled by the phy_interrupt/timer to handle PHY changes 651b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @work: work_struct that describes the work to be done 652b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap */ 653c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howellsstatic void phy_change(struct work_struct *work) 654e13934563db047043ccead26412f552375cea90cAndy Fleming{ 655e13934563db047043ccead26412f552375cea90cAndy Fleming int err; 656c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells struct phy_device *phydev = 657c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells container_of(work, struct phy_device, phy_queue); 658e13934563db047043ccead26412f552375cea90cAndy Fleming 659a8729eb302a5b5da8b0b4d29582c42648a2e0f12Anatolij Gustschin if (phydev->drv->did_interrupt && 660a8729eb302a5b5da8b0b4d29582c42648a2e0f12Anatolij Gustschin !phydev->drv->did_interrupt(phydev)) 661a8729eb302a5b5da8b0b4d29582c42648a2e0f12Anatolij Gustschin goto ignore; 662a8729eb302a5b5da8b0b4d29582c42648a2e0f12Anatolij Gustschin 663e13934563db047043ccead26412f552375cea90cAndy Fleming err = phy_disable_interrupts(phydev); 664e13934563db047043ccead26412f552375cea90cAndy Fleming 665e13934563db047043ccead26412f552375cea90cAndy Fleming if (err) 666e13934563db047043ccead26412f552375cea90cAndy Fleming goto phy_err; 667e13934563db047043ccead26412f552375cea90cAndy Fleming 66835b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case mutex_lock(&phydev->lock); 669e13934563db047043ccead26412f552375cea90cAndy Fleming if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state)) 670e13934563db047043ccead26412f552375cea90cAndy Fleming phydev->state = PHY_CHANGELINK; 67135b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case mutex_unlock(&phydev->lock); 672e13934563db047043ccead26412f552375cea90cAndy Fleming 6730ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki atomic_dec(&phydev->irq_disable); 674e13934563db047043ccead26412f552375cea90cAndy Fleming enable_irq(phydev->irq); 675e13934563db047043ccead26412f552375cea90cAndy Fleming 676e13934563db047043ccead26412f552375cea90cAndy Fleming /* Reenable interrupts */ 6773c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki if (PHY_HALTED != phydev->state) 6783c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED); 679e13934563db047043ccead26412f552375cea90cAndy Fleming 680e13934563db047043ccead26412f552375cea90cAndy Fleming if (err) 681e13934563db047043ccead26412f552375cea90cAndy Fleming goto irq_enable_err; 682e13934563db047043ccead26412f552375cea90cAndy Fleming 683a390d1f379cf821248b735f43d2e1147ebb8241dMarcin Slusarz /* reschedule state queue work to run as soon as possible */ 684a390d1f379cf821248b735f43d2e1147ebb8241dMarcin Slusarz cancel_delayed_work_sync(&phydev->state_queue); 685a390d1f379cf821248b735f43d2e1147ebb8241dMarcin Slusarz schedule_delayed_work(&phydev->state_queue, 0); 6860acb28396728f42b6b1553c85d27c37513796043Trent Piepho 687e13934563db047043ccead26412f552375cea90cAndy Fleming return; 688e13934563db047043ccead26412f552375cea90cAndy Fleming 689a8729eb302a5b5da8b0b4d29582c42648a2e0f12Anatolij Gustschinignore: 690a8729eb302a5b5da8b0b4d29582c42648a2e0f12Anatolij Gustschin atomic_dec(&phydev->irq_disable); 691a8729eb302a5b5da8b0b4d29582c42648a2e0f12Anatolij Gustschin enable_irq(phydev->irq); 692a8729eb302a5b5da8b0b4d29582c42648a2e0f12Anatolij Gustschin return; 693a8729eb302a5b5da8b0b4d29582c42648a2e0f12Anatolij Gustschin 694e13934563db047043ccead26412f552375cea90cAndy Flemingirq_enable_err: 695e13934563db047043ccead26412f552375cea90cAndy Fleming disable_irq(phydev->irq); 6960ac49527318bc388a881152d60f49d7951606024Maciej W. Rozycki atomic_inc(&phydev->irq_disable); 697e13934563db047043ccead26412f552375cea90cAndy Flemingphy_err: 698e13934563db047043ccead26412f552375cea90cAndy Fleming phy_error(phydev); 699e13934563db047043ccead26412f552375cea90cAndy Fleming} 700e13934563db047043ccead26412f552375cea90cAndy Fleming 701b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 702b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_stop - Bring down the PHY link, and stop checking the status 703b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: target phy_device struct 704b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap */ 705e13934563db047043ccead26412f552375cea90cAndy Flemingvoid phy_stop(struct phy_device *phydev) 706e13934563db047043ccead26412f552375cea90cAndy Fleming{ 70735b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case mutex_lock(&phydev->lock); 708e13934563db047043ccead26412f552375cea90cAndy Fleming 709e13934563db047043ccead26412f552375cea90cAndy Fleming if (PHY_HALTED == phydev->state) 710e13934563db047043ccead26412f552375cea90cAndy Fleming goto out_unlock; 711e13934563db047043ccead26412f552375cea90cAndy Fleming 7123c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki if (phydev->irq != PHY_POLL) { 713e13934563db047043ccead26412f552375cea90cAndy Fleming /* Disable PHY Interrupts */ 714e13934563db047043ccead26412f552375cea90cAndy Fleming phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED); 715e13934563db047043ccead26412f552375cea90cAndy Fleming 7163c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki /* Clear any pending interrupts */ 7173c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki phy_clear_interrupt(phydev); 7183c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki } 719e13934563db047043ccead26412f552375cea90cAndy Fleming 7206daf65310374d24d888201b7a6eba90b44008b7bMaciej W. Rozycki phydev->state = PHY_HALTED; 7216daf65310374d24d888201b7a6eba90b44008b7bMaciej W. Rozycki 722e13934563db047043ccead26412f552375cea90cAndy Flemingout_unlock: 72335b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case mutex_unlock(&phydev->lock); 7243c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki 7253c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki /* 7263c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki * Cannot call flush_scheduled_work() here as desired because 7273c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki * of rtnl_lock(), but PHY_HALTED shall guarantee phy_change() 7283c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki * will not reenable interrupts. 7293c3070d713d798f7f9e7ee3614e49b47655d14d8Maciej W. Rozycki */ 730e13934563db047043ccead26412f552375cea90cAndy Fleming} 731e13934563db047043ccead26412f552375cea90cAndy Fleming 732e13934563db047043ccead26412f552375cea90cAndy Fleming 733b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap/** 734b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * phy_start - start or restart a PHY device 735b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * @phydev: target phy_device struct 736e13934563db047043ccead26412f552375cea90cAndy Fleming * 737b3df0da886ffdb3e70c3197f589e959e5f8c9c04Randy Dunlap * Description: Indicates the attached device's readiness to 738e13934563db047043ccead26412f552375cea90cAndy Fleming * handle PHY-related work. Used during startup to start the 739e13934563db047043ccead26412f552375cea90cAndy Fleming * PHY, and after a call to phy_stop() to resume operation. 740e13934563db047043ccead26412f552375cea90cAndy Fleming * Also used to indicate the MDIO bus has cleared an error 741e13934563db047043ccead26412f552375cea90cAndy Fleming * condition. 742e13934563db047043ccead26412f552375cea90cAndy Fleming */ 743e13934563db047043ccead26412f552375cea90cAndy Flemingvoid phy_start(struct phy_device *phydev) 744e13934563db047043ccead26412f552375cea90cAndy Fleming{ 74535b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case mutex_lock(&phydev->lock); 746e13934563db047043ccead26412f552375cea90cAndy Fleming 747e13934563db047043ccead26412f552375cea90cAndy Fleming switch (phydev->state) { 748e13934563db047043ccead26412f552375cea90cAndy Fleming case PHY_STARTING: 749e13934563db047043ccead26412f552375cea90cAndy Fleming phydev->state = PHY_PENDING; 750e13934563db047043ccead26412f552375cea90cAndy Fleming break; 751e13934563db047043ccead26412f552375cea90cAndy Fleming case PHY_READY: 752e13934563db047043ccead26412f552375cea90cAndy Fleming phydev->state = PHY_UP; 753e13934563db047043ccead26412f552375cea90cAndy Fleming break; 754e13934563db047043ccead26412f552375cea90cAndy Fleming case PHY_HALTED: 755e13934563db047043ccead26412f552375cea90cAndy Fleming phydev->state = PHY_RESUMING; 756e13934563db047043ccead26412f552375cea90cAndy Fleming default: 757e13934563db047043ccead26412f552375cea90cAndy Fleming break; 758e13934563db047043ccead26412f552375cea90cAndy Fleming } 75935b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case mutex_unlock(&phydev->lock); 760e13934563db047043ccead26412f552375cea90cAndy Fleming} 761e13934563db047043ccead26412f552375cea90cAndy FlemingEXPORT_SYMBOL(phy_stop); 762e13934563db047043ccead26412f552375cea90cAndy FlemingEXPORT_SYMBOL(phy_start); 76367c4f3fa25502ce7ed82fb0307e09cf36f1f81daJeff Garzik 76435b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case/** 76535b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case * phy_state_machine - Handle the state machine 76635b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case * @work: work_struct that describes the work to be done 76735b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case */ 7684f9c85a1b03bfa5c0a0d8488a3a7766f3c9fb756Anton Vorontsovvoid phy_state_machine(struct work_struct *work) 76900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming{ 770bf6aede712334d7338d5c47a5ee5ba3883c82a61Jean Delvare struct delayed_work *dwork = to_delayed_work(work); 77135b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case struct phy_device *phydev = 772a390d1f379cf821248b735f43d2e1147ebb8241dMarcin Slusarz container_of(dwork, struct phy_device, state_queue); 77300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming int needs_aneg = 0; 77400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming int err = 0; 77500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 77635b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case mutex_lock(&phydev->lock); 77700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 77800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (phydev->adjust_state) 77900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->adjust_state(phydev->attached_dev); 78000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 78100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming switch(phydev->state) { 78200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case PHY_DOWN: 78300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case PHY_STARTING: 78400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case PHY_READY: 78500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case PHY_PENDING: 78600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 78700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case PHY_UP: 78800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming needs_aneg = 1; 78900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 79000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->link_timeout = PHY_AN_TIMEOUT; 79100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 79200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 79300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case PHY_AN: 7946b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming err = phy_read_status(phydev); 7956b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming 7966b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming if (err < 0) 7976b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming break; 7986b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming 7996b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming /* If the link is down, give up on 8006b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming * negotiation for now */ 8016b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming if (!phydev->link) { 8026b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming phydev->state = PHY_NOLINK; 8036b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming netif_carrier_off(phydev->attached_dev); 8046b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming phydev->adjust_link(phydev->attached_dev); 8056b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming break; 8066b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming } 8076b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming 80800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming /* Check if negotiation is done. Break 80900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * if there's an error */ 81000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = phy_aneg_done(phydev); 81100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err < 0) 81200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 81300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 8146b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming /* If AN is done, we're running */ 81500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err > 0) { 8166b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming phydev->state = PHY_RUNNING; 8176b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming netif_carrier_on(phydev->attached_dev); 8186b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming phydev->adjust_link(phydev->attached_dev); 81900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 8206b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming } else if (0 == phydev->link_timeout--) { 8216b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming int idx; 82200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 8236b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming needs_aneg = 1; 8246b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming /* If we have the magic_aneg bit, 8256b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming * we try again */ 8266b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming if (phydev->drv->flags & PHY_HAS_MAGICANEG) 82700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 82800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 8296b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming /* The timer expired, and we still 8306b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming * don't have a setting, so we try 8316b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming * forcing it until we find one that 8326b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming * works, starting from the fastest speed, 8336b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming * and working our way down */ 8346b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming idx = phy_find_valid(0, phydev->supported); 83500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 8366b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming phydev->speed = settings[idx].speed; 8376b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming phydev->duplex = settings[idx].duplex; 83800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 8396b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming phydev->autoneg = AUTONEG_DISABLE; 84000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 8416b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming pr_info("Trying %d/%s\n", phydev->speed, 8426b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming DUPLEX_FULL == 8436b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming phydev->duplex ? 8446b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming "FULL" : "HALF"); 84500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming } 84600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 84700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case PHY_NOLINK: 84800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = phy_read_status(phydev); 84900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 85000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err) 85100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 85200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 85300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (phydev->link) { 85400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->state = PHY_RUNNING; 85500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming netif_carrier_on(phydev->attached_dev); 85600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->adjust_link(phydev->attached_dev); 85700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming } 85800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 85900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case PHY_FORCING: 8606b655529c3d817ed1b69cf2dd29e2c3ce5148a2bAndy Fleming err = genphy_update_link(phydev); 86100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 86200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err) 86300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 86400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 86500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (phydev->link) { 86600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->state = PHY_RUNNING; 86700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming netif_carrier_on(phydev->attached_dev); 86800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming } else { 86900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (0 == phydev->link_timeout--) { 87000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phy_force_reduction(phydev); 87100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming needs_aneg = 1; 87200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming } 87300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming } 87400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 87500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->adjust_link(phydev->attached_dev); 87600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 87700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case PHY_RUNNING: 87800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming /* Only register a CHANGE if we are 87900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * polling */ 88000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (PHY_POLL == phydev->irq) 88100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->state = PHY_CHANGELINK; 88200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 88300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case PHY_CHANGELINK: 88400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = phy_read_status(phydev); 88500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 88600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err) 88700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 88800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 88900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (phydev->link) { 89000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->state = PHY_RUNNING; 89100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming netif_carrier_on(phydev->attached_dev); 89200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming } else { 89300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->state = PHY_NOLINK; 89400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming netif_carrier_off(phydev->attached_dev); 89500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming } 89600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 89700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->adjust_link(phydev->attached_dev); 89800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 89900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (PHY_POLL != phydev->irq) 90000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = phy_config_interrupt(phydev, 90100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming PHY_INTERRUPT_ENABLED); 90200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 90300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case PHY_HALTED: 90400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (phydev->link) { 90500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->link = 0; 90600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming netif_carrier_off(phydev->attached_dev); 90700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->adjust_link(phydev->attached_dev); 90800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming } 90900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 91000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming case PHY_RESUMING: 91100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 91200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = phy_clear_interrupt(phydev); 91300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 91400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err) 91500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 91600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 91700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = phy_config_interrupt(phydev, 91800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming PHY_INTERRUPT_ENABLED); 91900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 92000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err) 92100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 92200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 92300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (AUTONEG_ENABLE == phydev->autoneg) { 92400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = phy_aneg_done(phydev); 92500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err < 0) 92600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 92700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 92800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming /* err > 0 if AN is done. 92900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * Otherwise, it's 0, and we're 93000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming * still waiting for AN */ 93100db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err > 0) { 93242caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth err = phy_read_status(phydev); 93342caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth if (err) 93442caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth break; 93542caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth 93642caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth if (phydev->link) { 93742caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth phydev->state = PHY_RUNNING; 93842caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth netif_carrier_on(phydev->attached_dev); 93942caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth } else 94042caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth phydev->state = PHY_NOLINK; 94142caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth phydev->adjust_link(phydev->attached_dev); 94200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming } else { 94300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->state = PHY_AN; 94400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phydev->link_timeout = PHY_AN_TIMEOUT; 94500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming } 94642caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth } else { 94742caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth err = phy_read_status(phydev); 94842caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth if (err) 94942caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth break; 95042caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth 95142caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth if (phydev->link) { 95242caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth phydev->state = PHY_RUNNING; 95342caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth netif_carrier_on(phydev->attached_dev); 95442caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth } else 95542caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth phydev->state = PHY_NOLINK; 95642caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth phydev->adjust_link(phydev->attached_dev); 95742caa074042e22f873c408a0d13be657b16192f1Wade Farnsworth } 95800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming break; 95900db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming } 96000db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 96135b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case mutex_unlock(&phydev->lock); 96200db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 96300db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (needs_aneg) 96400db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming err = phy_start_aneg(phydev); 96500db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 96600db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming if (err < 0) 96700db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming phy_error(phydev); 96800db8189d984d6c51226dafbbe4a667ce9b7d5daAndy Fleming 9693664090e199f10cb0282097faae8f8ca58c1e4aeAtsushi Nemoto schedule_delayed_work(&phydev->state_queue, PHY_STATE_TIME * HZ); 97035b5f6b1a82b5c586e0b24c711dc6ba944e88ef1Nate Case} 971