1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright(c) 2007 Atheros Corporation. All rights reserved. |
4 | * |
5 | * Derived from Intel e1000 driver |
6 | * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. |
7 | */ |
8 | |
9 | #include <linux/netdevice.h> |
10 | |
11 | #include "atl1e.h" |
12 | |
13 | /* This is the only thing that needs to be changed to adjust the |
14 | * maximum number of ports that the driver can manage. |
15 | */ |
16 | |
17 | #define ATL1E_MAX_NIC 32 |
18 | |
19 | #define OPTION_UNSET -1 |
20 | #define OPTION_DISABLED 0 |
21 | #define OPTION_ENABLED 1 |
22 | |
23 | /* All parameters are treated the same, as an integer array of values. |
24 | * This macro just reduces the need to repeat the same declaration code |
25 | * over and over (plus this helps to avoid typo bugs). |
26 | */ |
27 | #define ATL1E_PARAM_INIT { [0 ... ATL1E_MAX_NIC] = OPTION_UNSET } |
28 | |
29 | #define ATL1E_PARAM(x, desc) \ |
30 | static int x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \ |
31 | static unsigned int num_##x; \ |
32 | module_param_array_named(x, x, int, &num_##x, 0); \ |
33 | MODULE_PARM_DESC(x, desc); |
34 | |
35 | /* Transmit Memory count |
36 | * |
37 | * Valid Range: 64-2048 |
38 | * |
39 | * Default Value: 128 |
40 | */ |
41 | #define ATL1E_MIN_TX_DESC_CNT 32 |
42 | #define ATL1E_MAX_TX_DESC_CNT 1020 |
43 | #define ATL1E_DEFAULT_TX_DESC_CNT 128 |
44 | ATL1E_PARAM(tx_desc_cnt, "Transmit description count" ); |
45 | |
46 | /* Receive Memory Block Count |
47 | * |
48 | * Valid Range: 16-512 |
49 | * |
50 | * Default Value: 128 |
51 | */ |
52 | #define ATL1E_MIN_RX_MEM_SIZE 8 /* 8KB */ |
53 | #define ATL1E_MAX_RX_MEM_SIZE 1024 /* 1MB */ |
54 | #define ATL1E_DEFAULT_RX_MEM_SIZE 256 /* 128KB */ |
55 | ATL1E_PARAM(rx_mem_size, "memory size of rx buffer(KB)" ); |
56 | |
57 | /* User Specified MediaType Override |
58 | * |
59 | * Valid Range: 0-5 |
60 | * - 0 - auto-negotiate at all supported speeds |
61 | * - 1 - only link at 100Mbps Full Duplex |
62 | * - 2 - only link at 100Mbps Half Duplex |
63 | * - 3 - only link at 10Mbps Full Duplex |
64 | * - 4 - only link at 10Mbps Half Duplex |
65 | * Default Value: 0 |
66 | */ |
67 | |
68 | ATL1E_PARAM(media_type, "MediaType Select" ); |
69 | |
70 | /* Interrupt Moderate Timer in units of 2 us |
71 | * |
72 | * Valid Range: 10-65535 |
73 | * |
74 | * Default Value: 45000(90ms) |
75 | */ |
76 | #define INT_MOD_DEFAULT_CNT 100 /* 200us */ |
77 | #define INT_MOD_MAX_CNT 65000 |
78 | #define INT_MOD_MIN_CNT 50 |
79 | ATL1E_PARAM(int_mod_timer, "Interrupt Moderator Timer" ); |
80 | |
81 | #define AUTONEG_ADV_DEFAULT 0x2F |
82 | #define AUTONEG_ADV_MASK 0x2F |
83 | #define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL |
84 | |
85 | #define FLASH_VENDOR_DEFAULT 0 |
86 | #define FLASH_VENDOR_MIN 0 |
87 | #define FLASH_VENDOR_MAX 2 |
88 | |
89 | struct atl1e_option { |
90 | enum { enable_option, range_option, list_option } type; |
91 | char *name; |
92 | char *err; |
93 | int def; |
94 | union { |
95 | struct { /* range_option info */ |
96 | int min; |
97 | int max; |
98 | } r; |
99 | struct { /* list_option info */ |
100 | int nr; |
101 | struct atl1e_opt_list { int i; char *str; } *p; |
102 | } l; |
103 | } arg; |
104 | }; |
105 | |
106 | static int atl1e_validate_option(int *value, struct atl1e_option *opt, |
107 | struct atl1e_adapter *adapter) |
108 | { |
109 | if (*value == OPTION_UNSET) { |
110 | *value = opt->def; |
111 | return 0; |
112 | } |
113 | |
114 | switch (opt->type) { |
115 | case enable_option: |
116 | switch (*value) { |
117 | case OPTION_ENABLED: |
118 | netdev_info(dev: adapter->netdev, |
119 | format: "%s Enabled\n" , opt->name); |
120 | return 0; |
121 | case OPTION_DISABLED: |
122 | netdev_info(dev: adapter->netdev, |
123 | format: "%s Disabled\n" , opt->name); |
124 | return 0; |
125 | } |
126 | break; |
127 | case range_option: |
128 | if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { |
129 | netdev_info(dev: adapter->netdev, format: "%s set to %i\n" , |
130 | opt->name, *value); |
131 | return 0; |
132 | } |
133 | break; |
134 | case list_option:{ |
135 | int i; |
136 | struct atl1e_opt_list *ent; |
137 | |
138 | for (i = 0; i < opt->arg.l.nr; i++) { |
139 | ent = &opt->arg.l.p[i]; |
140 | if (*value == ent->i) { |
141 | if (ent->str[0] != '\0') |
142 | netdev_info(dev: adapter->netdev, |
143 | format: "%s\n" , ent->str); |
144 | return 0; |
145 | } |
146 | } |
147 | break; |
148 | } |
149 | default: |
150 | BUG(); |
151 | } |
152 | |
153 | netdev_info(dev: adapter->netdev, format: "Invalid %s specified (%i) %s\n" , |
154 | opt->name, *value, opt->err); |
155 | *value = opt->def; |
156 | return -1; |
157 | } |
158 | |
159 | /** |
160 | * atl1e_check_options - Range Checking for Command Line Parameters |
161 | * @adapter: board private structure |
162 | * |
163 | * This routine checks all command line parameters for valid user |
164 | * input. If an invalid value is given, or if no user specified |
165 | * value exists, a default value is used. The final value is stored |
166 | * in a variable in the adapter structure. |
167 | */ |
168 | void atl1e_check_options(struct atl1e_adapter *adapter) |
169 | { |
170 | int bd = adapter->bd_number; |
171 | |
172 | if (bd >= ATL1E_MAX_NIC) { |
173 | netdev_notice(dev: adapter->netdev, |
174 | format: "no configuration for board #%i\n" , bd); |
175 | netdev_notice(dev: adapter->netdev, |
176 | format: "Using defaults for all values\n" ); |
177 | } |
178 | |
179 | { /* Transmit Ring Size */ |
180 | struct atl1e_option opt = { |
181 | .type = range_option, |
182 | .name = "Transmit Ddescription Count" , |
183 | .err = "using default of " |
184 | __MODULE_STRING(ATL1E_DEFAULT_TX_DESC_CNT), |
185 | .def = ATL1E_DEFAULT_TX_DESC_CNT, |
186 | .arg = { .r = { .min = ATL1E_MIN_TX_DESC_CNT, |
187 | .max = ATL1E_MAX_TX_DESC_CNT} } |
188 | }; |
189 | int val; |
190 | if (num_tx_desc_cnt > bd) { |
191 | val = tx_desc_cnt[bd]; |
192 | atl1e_validate_option(value: &val, opt: &opt, adapter); |
193 | adapter->tx_ring.count = (u16) val & 0xFFFC; |
194 | } else |
195 | adapter->tx_ring.count = (u16)opt.def; |
196 | } |
197 | |
198 | { /* Receive Memory Block Count */ |
199 | struct atl1e_option opt = { |
200 | .type = range_option, |
201 | .name = "Memory size of rx buffer(KB)" , |
202 | .err = "using default of " |
203 | __MODULE_STRING(ATL1E_DEFAULT_RX_MEM_SIZE), |
204 | .def = ATL1E_DEFAULT_RX_MEM_SIZE, |
205 | .arg = { .r = { .min = ATL1E_MIN_RX_MEM_SIZE, |
206 | .max = ATL1E_MAX_RX_MEM_SIZE} } |
207 | }; |
208 | int val; |
209 | if (num_rx_mem_size > bd) { |
210 | val = rx_mem_size[bd]; |
211 | atl1e_validate_option(value: &val, opt: &opt, adapter); |
212 | adapter->rx_ring.page_size = (u32)val * 1024; |
213 | } else { |
214 | adapter->rx_ring.page_size = (u32)opt.def * 1024; |
215 | } |
216 | } |
217 | |
218 | { /* Interrupt Moderate Timer */ |
219 | struct atl1e_option opt = { |
220 | .type = range_option, |
221 | .name = "Interrupt Moderate Timer" , |
222 | .err = "using default of " |
223 | __MODULE_STRING(INT_MOD_DEFAULT_CNT), |
224 | .def = INT_MOD_DEFAULT_CNT, |
225 | .arg = { .r = { .min = INT_MOD_MIN_CNT, |
226 | .max = INT_MOD_MAX_CNT} } |
227 | } ; |
228 | int val; |
229 | if (num_int_mod_timer > bd) { |
230 | val = int_mod_timer[bd]; |
231 | atl1e_validate_option(value: &val, opt: &opt, adapter); |
232 | adapter->hw.imt = (u16) val; |
233 | } else |
234 | adapter->hw.imt = (u16)(opt.def); |
235 | } |
236 | |
237 | { /* MediaType */ |
238 | struct atl1e_option opt = { |
239 | .type = range_option, |
240 | .name = "Speed/Duplex Selection" , |
241 | .err = "using default of " |
242 | __MODULE_STRING(MEDIA_TYPE_AUTO_SENSOR), |
243 | .def = MEDIA_TYPE_AUTO_SENSOR, |
244 | .arg = { .r = { .min = MEDIA_TYPE_AUTO_SENSOR, |
245 | .max = MEDIA_TYPE_10M_HALF} } |
246 | } ; |
247 | int val; |
248 | if (num_media_type > bd) { |
249 | val = media_type[bd]; |
250 | atl1e_validate_option(value: &val, opt: &opt, adapter); |
251 | adapter->hw.media_type = (u16) val; |
252 | } else |
253 | adapter->hw.media_type = (u16)(opt.def); |
254 | |
255 | } |
256 | } |
257 | |