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