Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/aq/aq_media.c
96295 views
1
/*
2
* aQuantia Corporation Network Driver
3
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
*
9
* (1) Redistributions of source code must retain the above
10
* copyright notice, this list of conditions and the following
11
* disclaimer.
12
*
13
* (2) Redistributions in binary form must reproduce the above
14
* copyright notice, this list of conditions and the following
15
* disclaimer in the documentation and/or other materials provided
16
* with the distribution.
17
*
18
* (3)The name of the author may not be used to endorse or promote
19
* products derived from this software without specific prior
20
* written permission.
21
*
22
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
23
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
26
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
28
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
*/
34
35
#include <sys/cdefs.h>
36
__FBSDID("$FreeBSD$");
37
38
#include <sys/param.h>
39
#include <sys/bitstring.h>
40
#include <sys/kernel.h>
41
#include <sys/socket.h>
42
#include <net/ethernet.h>
43
#include <net/if.h>
44
#include <net/if_media.h>
45
#include <net/if_var.h>
46
#include <net/if_dl.h>
47
#include <net/iflib.h>
48
49
#include "aq_device.h"
50
51
#include "aq_fw.h"
52
#include "aq_dbg.h"
53
54
#define AQ_HW_SUPPORT_SPEED(softc, s) ((softc)->link_speeds & s)
55
56
void
57
aq_mediastatus_update(aq_dev_t *aq_dev, uint32_t link_speed,
58
const struct aq_hw_fc_info *fc_neg)
59
{
60
struct aq_hw *hw = &aq_dev->hw;
61
62
aq_dev->media_active = 0;
63
if (fc_neg->fc_rx)
64
aq_dev->media_active |= IFM_ETH_RXPAUSE;
65
if (fc_neg->fc_tx)
66
aq_dev->media_active |= IFM_ETH_TXPAUSE;
67
68
switch(link_speed) {
69
case 100:
70
aq_dev->media_active |= IFM_100_TX | IFM_FDX;
71
break;
72
case 1000:
73
aq_dev->media_active |= IFM_1000_T | IFM_FDX;
74
break;
75
case 2500:
76
aq_dev->media_active |= IFM_2500_T | IFM_FDX;
77
break;
78
case 5000:
79
aq_dev->media_active |= IFM_5000_T | IFM_FDX;
80
break;
81
case 10000:
82
aq_dev->media_active |= IFM_10G_T | IFM_FDX;
83
break;
84
case 0:
85
default:
86
aq_dev->media_active |= IFM_NONE;
87
break;
88
}
89
90
if (hw->link_rate == aq_fw_speed_auto)
91
aq_dev->media_active |= IFM_AUTO;
92
}
93
94
void
95
aq_mediastatus(if_t ifp, struct ifmediareq *ifmr)
96
{
97
aq_dev_t *aq_dev = iflib_get_softc(if_getsoftc(ifp));
98
99
ifmr->ifm_active = IFM_ETHER;
100
ifmr->ifm_status = IFM_AVALID;
101
102
if (aq_dev->linkup)
103
ifmr->ifm_status |= IFM_ACTIVE;
104
105
ifmr->ifm_active |= aq_dev->media_active;
106
}
107
108
int
109
aq_mediachange(if_t ifp)
110
{
111
aq_dev_t *aq_dev = iflib_get_softc(if_getsoftc(ifp));
112
struct aq_hw *hw = &aq_dev->hw;
113
int old_media_rate = if_getbaudrate(ifp);
114
int old_link_speed = hw->link_rate;
115
struct ifmedia *ifm = iflib_get_media(aq_dev->ctx);
116
int user_media = IFM_SUBTYPE(ifm->ifm_media);
117
uint64_t media_rate;
118
119
AQ_DBG_ENTERA("media 0x%x", user_media);
120
121
if (!(ifm->ifm_media & IFM_ETHER)) {
122
device_printf(aq_dev->dev,
123
"%s(): aq_dev interface - bad media: 0x%X", __FUNCTION__,
124
ifm->ifm_media);
125
return (0); // should never happen
126
}
127
128
switch (user_media) {
129
case IFM_AUTO: // auto-select media
130
hw->link_rate = aq_fw_speed_auto;
131
media_rate = -1;
132
break;
133
134
case IFM_NONE: // disable media
135
media_rate = 0;
136
hw->link_rate = 0;
137
iflib_link_state_change(aq_dev->ctx, LINK_STATE_DOWN, 0);
138
break;
139
140
case IFM_100_TX:
141
hw->link_rate = aq_fw_100M;
142
media_rate = 100 * 1000;
143
break;
144
145
case IFM_1000_T:
146
hw->link_rate = aq_fw_1G;
147
media_rate = 1000 * 1000;
148
break;
149
150
case IFM_2500_T:
151
hw->link_rate = aq_fw_2G5;
152
media_rate = 2500 * 1000;
153
break;
154
155
case IFM_5000_T:
156
hw->link_rate = aq_fw_5G;
157
media_rate = 5000 * 1000;
158
break;
159
160
case IFM_10G_T:
161
hw->link_rate = aq_fw_10G;
162
media_rate = 10000 * 1000;
163
break;
164
165
default: // should never happen
166
aq_log_error("unknown media: 0x%X", user_media);
167
return (0);
168
}
169
hw->fc.fc_rx = (ifm->ifm_media & IFM_ETH_RXPAUSE) ? 1 : 0;
170
hw->fc.fc_tx = (ifm->ifm_media & IFM_ETH_TXPAUSE) ? 1 : 0;
171
172
/* In down state just remember new link speed */
173
if (!(if_getflags(ifp) & IFF_UP))
174
return (0);
175
176
if ((media_rate != old_media_rate) ||
177
(hw->link_rate != old_link_speed)) {
178
// re-initialize hardware with new parameters
179
aq_hw_set_link_speed(hw, hw->link_rate);
180
}
181
182
AQ_DBG_EXIT(0);
183
return (0);
184
}
185
186
static void
187
aq_add_media_types(aq_dev_t *aq_dev, int media_link_speed)
188
{
189
ifmedia_add(aq_dev->media, IFM_ETHER | media_link_speed | IFM_FDX, 0,
190
NULL);
191
ifmedia_add(aq_dev->media, IFM_ETHER | media_link_speed | IFM_FDX |
192
IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE, 0, NULL);
193
ifmedia_add(aq_dev->media, IFM_ETHER | media_link_speed | IFM_FDX |
194
IFM_ETH_RXPAUSE, 0, NULL);
195
ifmedia_add(aq_dev->media, IFM_ETHER | media_link_speed | IFM_FDX |
196
IFM_ETH_TXPAUSE, 0, NULL);
197
}
198
void
199
aq_initmedia(aq_dev_t *aq_dev)
200
{
201
AQ_DBG_ENTER();
202
203
// ifconfig eth0 none
204
ifmedia_add(aq_dev->media, IFM_ETHER | IFM_NONE, 0, NULL);
205
206
// ifconfig eth0 auto
207
aq_add_media_types(aq_dev, IFM_AUTO);
208
209
if (AQ_HW_SUPPORT_SPEED(aq_dev, AQ_LINK_100M))
210
aq_add_media_types(aq_dev, IFM_100_TX);
211
if (AQ_HW_SUPPORT_SPEED(aq_dev, AQ_LINK_1G))
212
aq_add_media_types(aq_dev, IFM_1000_T);
213
if (AQ_HW_SUPPORT_SPEED(aq_dev, AQ_LINK_2G5))
214
aq_add_media_types(aq_dev, IFM_2500_T);
215
if (AQ_HW_SUPPORT_SPEED(aq_dev, AQ_LINK_5G))
216
aq_add_media_types(aq_dev, IFM_5000_T);
217
if (AQ_HW_SUPPORT_SPEED(aq_dev, AQ_LINK_10G))
218
aq_add_media_types(aq_dev, IFM_10G_T);
219
220
// link is initially autoselect
221
ifmedia_set(aq_dev->media,
222
IFM_ETHER | IFM_AUTO | IFM_FDX | IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE);
223
224
AQ_DBG_EXIT(0);
225
}
226
227