summaryrefslogtreecommitdiff
path: root/include/linux/phylink.h
blob: 4872f498e335d7d7149791604ab48fb20636fe53 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#ifndef NETDEV_PCS_H
#define NETDEV_PCS_H

#include <linux/phy.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>

struct device_node;
struct ethtool_cmd;
struct net_device;

enum {
	MLO_PAUSE_NONE,
	MLO_PAUSE_ASYM = BIT(0),
	MLO_PAUSE_SYM = BIT(1),
	MLO_PAUSE_RX = BIT(2),
	MLO_PAUSE_TX = BIT(3),
	MLO_PAUSE_TXRX_MASK = MLO_PAUSE_TX | MLO_PAUSE_RX,
	MLO_PAUSE_AN = BIT(4),

	MLO_AN_PHY = 0,	/* Conventional PHY */
	MLO_AN_FIXED,	/* Fixed-link mode */
	MLO_AN_SGMII,	/* Cisco SGMII protocol */
	MLO_AN_8023Z,	/* 1000base-X protocol */
};

static inline bool phylink_autoneg_inband(unsigned int mode)
{
	return mode == MLO_AN_SGMII || mode == MLO_AN_8023Z;
}

struct phylink_link_state {
	__ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
	__ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising);
	int speed;
	int duplex;
	int pause;
	unsigned int link:1;
	unsigned int an_enabled:1;
	unsigned int an_complete:1;
};

struct phylink_mac_ops {
	/**
	 * validate_support: validate and update the support mask
	 * @ndev: net_device structure associated with MAC
	 * @mode: desired negotiation operating mode
	 * @support: pointer to the desired support mask
	 *
	 * Validate and update the support mask provided by a PHY or
	 * module.  Unsupported link modes should be cleared by the
	 * MAC.
	 *
	 * Note: the PHY may be able to transform from one connection
	 * technology to another, so, eg, don't clear 1000base-X just
	 * because the MAC is unable to support it.  This is more about
	 * clearing unsupported speeds and duplex settings.
	 */
	void (*validate_support)(struct net_device *ndev, unsigned int mode,
				 unsigned long *support);

	/**
	 * validate_advert: validate and update the advertisment
	 * @ndev: net_device structure associated with the MAC
	 * @mode: desired negotiation operating mode
	 * @support: current support mask
	 * @advert: desired advertisment mask
	 *
	 * Validate and update the advertisment mask, clearing bits that
	 * can not be advertised in the chosen mode or with each other.
	 */
	void (*validate_advert)(struct net_device *ndev, unsigned int mode,
				const unsigned long *support,
				unsigned long *advert);

	/* Read the current link state from the hardware */
	int (*mac_link_state)(struct net_device *, struct phylink_link_state *);

	/* Configure the MAC */
	/**
	 * mac_config: configure the MAC for the selected mode and state
	 * @ndev: net_device structure for the MAC
	 * @mode: one of MLO_AN_FIXED, MLO_AN_PHY, MLO_AN_8023Z, MLO_AN_SGMII
	 * @state: state structure
	 *
	 * The action performed depends on the currently selected mode:
	 *
	 * %MLO_AN_FIXED, %MLO_AN_PHY:
	 *   set the specified speed, duplex, pause mode, and phy interface
	 *   mode in the provided @state.
	 * %MLO_AN_8023Z:
	 *   place the link in 1000base-X mode, advertising the parameters
	 *   given in advertising in @state.
	 * %MLO_AN_SGMII:
	 *   place the link in Cisco SGMII mode - there is no advertisment
	 *   to make as the PHY communicates the speed and duplex to the
	 *   MAC over the in-band control word.  Configuration of the pause
	 *   mode is as per MLO_AN_PHY since this is not included.
	 */
	void (*mac_config)(struct net_device *ndev, unsigned int mode,
			   const struct phylink_link_state *state);

	/**
	 * mac_an_restart: restart 802.3z BaseX autonegotiation
	 * @ndev: net_device structure for the MAC
	 */
	void (*mac_an_restart)(struct net_device *ndev);

	void (*mac_link_down)(struct net_device *, unsigned int mode);
	void (*mac_link_up)(struct net_device *, unsigned int mode,
			    struct phy_device *);
};

struct phylink *phylink_create(struct net_device *, struct device_node *,
	phy_interface_t iface, const struct phylink_mac_ops *ops);
void phylink_destroy(struct phylink *);

int phylink_connect_phy(struct phylink *, struct phy_device *);
int phylink_of_phy_connect(struct phylink *, struct device_node *);
void phylink_disconnect_phy(struct phylink *);

void phylink_mac_change(struct phylink *, bool up);

void phylink_start(struct phylink *);
void phylink_stop(struct phylink *);

void phylink_ethtool_get_wol(struct phylink *, struct ethtool_wolinfo *);
int phylink_ethtool_set_wol(struct phylink *, struct ethtool_wolinfo *);
                
int phylink_ethtool_ksettings_get(struct phylink *,
				  struct ethtool_link_ksettings *);
int phylink_ethtool_ksettings_set(struct phylink *,
				  const struct ethtool_link_ksettings *);
int phylink_ethtool_nway_reset(struct phylink *);
void phylink_ethtool_get_pauseparam(struct phylink *,
				    struct ethtool_pauseparam *);
int phylink_ethtool_set_pauseparam(struct phylink *,
				   struct ethtool_pauseparam *);
int phylink_init_eee(struct phylink *, bool);
int phylink_get_eee_err(struct phylink *);
int phylink_ethtool_get_eee(struct phylink *, struct ethtool_eee *);
int phylink_ethtool_set_eee(struct phylink *, struct ethtool_eee *);
int phylink_mii_ioctl(struct phylink *, struct ifreq *, int);

int phylink_set_link(struct phylink *pl, unsigned int mode, u8 port,
		     const unsigned long *support);
void phylink_disable(struct phylink *pl);
void phylink_enable(struct phylink *pl);
struct phylink *phylink_lookup_by_netdev(struct net_device *ndev);

#define phylink_zero(bm) \
	bitmap_zero(bm, __ETHTOOL_LINK_MODE_MASK_NBITS)
#define __phylink_do_bit(op, bm, mode) \
	op(ETHTOOL_LINK_MODE_ ## mode ## _BIT, bm)

#define phylink_set(bm, mode)	__phylink_do_bit(__set_bit, bm, mode)
#define phylink_clear(bm, mode)	__phylink_do_bit(__clear_bit, bm, mode)
#define phylink_test(bm, mode)	__phylink_do_bit(test_bit, bm, mode)

void phylink_set_port_modes(unsigned long *bits);

#endif