aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/e1000e/manage.c
diff options
context:
space:
mode:
authorBruce Allan <bruce.w.allan@intel.com>2011-12-21 04:47:10 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2012-01-26 22:00:19 -0500
commitfe2ddfb510f9d305a6654c7538c5c8faf326a16c (patch)
treef18e0d3839909b56ba6760d83ffa700ed9e6e960 /drivers/net/ethernet/intel/e1000e/manage.c
parentc8243ee0488d9bc12995ca7ea02f651db820622e (diff)
e1000e: split lib.c into three more-appropriate files
The generic lib.c file contains code relative to the various MACs, NVM and Manageability supported by the driver. This patch splits the file into three which are specific to those areas similar to how the PHY-specific code is in phy.c and code specific to the 80003es2lan, 8257x, and ichX MAC families are in their own files. The generic code that is applicable to all MAC/PHY parts supported by the driver remains in netdev.c, param.c and ethtool.c files. No change in functionality, just moving code around for ease of maintenance, with some whitespace and other checkpatch cleanups. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/e1000e/manage.c')
-rw-r--r--drivers/net/ethernet/intel/e1000e/manage.c377
1 files changed, 377 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/e1000e/manage.c b/drivers/net/ethernet/intel/e1000e/manage.c
new file mode 100644
index 000000000000..3dae2655ec70
--- /dev/null
+++ b/drivers/net/ethernet/intel/e1000e/manage.c
@@ -0,0 +1,377 @@
1/*******************************************************************************
2
3 Intel PRO/1000 Linux driver
4 Copyright(c) 1999 - 2011 Intel Corporation.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms and conditions of the GNU General Public License,
8 version 2, as published by the Free Software Foundation.
9
10 This program is distributed in the hope it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 more details.
14
15 You should have received a copy of the GNU General Public License along with
16 this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18
19 The full GNU General Public License is included in this distribution in
20 the file called "COPYING".
21
22 Contact Information:
23 Linux NICS <linux.nics@intel.com>
24 e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
25 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
26
27*******************************************************************************/
28
29#include "e1000.h"
30
31enum e1000_mng_mode {
32 e1000_mng_mode_none = 0,
33 e1000_mng_mode_asf,
34 e1000_mng_mode_pt,
35 e1000_mng_mode_ipmi,
36 e1000_mng_mode_host_if_only
37};
38
39#define E1000_FACTPS_MNGCG 0x20000000
40
41/* Intel(R) Active Management Technology signature */
42#define E1000_IAMT_SIGNATURE 0x544D4149
43
44/**
45 * e1000_calculate_checksum - Calculate checksum for buffer
46 * @buffer: pointer to EEPROM
47 * @length: size of EEPROM to calculate a checksum for
48 *
49 * Calculates the checksum for some buffer on a specified length. The
50 * checksum calculated is returned.
51 **/
52static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
53{
54 u32 i;
55 u8 sum = 0;
56
57 if (!buffer)
58 return 0;
59
60 for (i = 0; i < length; i++)
61 sum += buffer[i];
62
63 return (u8)(0 - sum);
64}
65
66/**
67 * e1000_mng_enable_host_if - Checks host interface is enabled
68 * @hw: pointer to the HW structure
69 *
70 * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
71 *
72 * This function checks whether the HOST IF is enabled for command operation
73 * and also checks whether the previous command is completed. It busy waits
74 * in case of previous command is not completed.
75 **/
76static s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
77{
78 u32 hicr;
79 u8 i;
80
81 if (!(hw->mac.arc_subsystem_valid)) {
82 e_dbg("ARC subsystem not valid.\n");
83 return -E1000_ERR_HOST_INTERFACE_COMMAND;
84 }
85
86 /* Check that the host interface is enabled. */
87 hicr = er32(HICR);
88 if ((hicr & E1000_HICR_EN) == 0) {
89 e_dbg("E1000_HOST_EN bit disabled.\n");
90 return -E1000_ERR_HOST_INTERFACE_COMMAND;
91 }
92 /* check the previous command is completed */
93 for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
94 hicr = er32(HICR);
95 if (!(hicr & E1000_HICR_C))
96 break;
97 mdelay(1);
98 }
99
100 if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
101 e_dbg("Previous command timeout failed .\n");
102 return -E1000_ERR_HOST_INTERFACE_COMMAND;
103 }
104
105 return 0;
106}
107
108/**
109 * e1000e_check_mng_mode_generic - check management mode
110 * @hw: pointer to the HW structure
111 *
112 * Reads the firmware semaphore register and returns true (>0) if
113 * manageability is enabled, else false (0).
114 **/
115bool e1000e_check_mng_mode_generic(struct e1000_hw *hw)
116{
117 u32 fwsm = er32(FWSM);
118
119 return (fwsm & E1000_FWSM_MODE_MASK) ==
120 (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
121}
122
123/**
124 * e1000e_enable_tx_pkt_filtering - Enable packet filtering on Tx
125 * @hw: pointer to the HW structure
126 *
127 * Enables packet filtering on transmit packets if manageability is enabled
128 * and host interface is enabled.
129 **/
130bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
131{
132 struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
133 u32 *buffer = (u32 *)&hw->mng_cookie;
134 u32 offset;
135 s32 ret_val, hdr_csum, csum;
136 u8 i, len;
137
138 hw->mac.tx_pkt_filtering = true;
139
140 /* No manageability, no filtering */
141 if (!e1000e_check_mng_mode(hw)) {
142 hw->mac.tx_pkt_filtering = false;
143 goto out;
144 }
145
146 /*
147 * If we can't read from the host interface for whatever
148 * reason, disable filtering.
149 */
150 ret_val = e1000_mng_enable_host_if(hw);
151 if (ret_val) {
152 hw->mac.tx_pkt_filtering = false;
153 goto out;
154 }
155
156 /* Read in the header. Length and offset are in dwords. */
157 len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
158 offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
159 for (i = 0; i < len; i++)
160 *(buffer + i) = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF,
161 offset + i);
162 hdr_csum = hdr->checksum;
163 hdr->checksum = 0;
164 csum = e1000_calculate_checksum((u8 *)hdr,
165 E1000_MNG_DHCP_COOKIE_LENGTH);
166 /*
167 * If either the checksums or signature don't match, then
168 * the cookie area isn't considered valid, in which case we
169 * take the safe route of assuming Tx filtering is enabled.
170 */
171 if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
172 hw->mac.tx_pkt_filtering = true;
173 goto out;
174 }
175
176 /* Cookie area is valid, make the final check for filtering. */
177 if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) {
178 hw->mac.tx_pkt_filtering = false;
179 goto out;
180 }
181
182out:
183 return hw->mac.tx_pkt_filtering;
184}
185
186/**
187 * e1000_mng_write_cmd_header - Writes manageability command header
188 * @hw: pointer to the HW structure
189 * @hdr: pointer to the host interface command header
190 *
191 * Writes the command header after does the checksum calculation.
192 **/
193static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
194 struct e1000_host_mng_command_header *hdr)
195{
196 u16 i, length = sizeof(struct e1000_host_mng_command_header);
197
198 /* Write the whole command header structure with new checksum. */
199
200 hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
201
202 length >>= 2;
203 /* Write the relevant command block into the ram area. */
204 for (i = 0; i < length; i++) {
205 E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, i, *((u32 *)hdr + i));
206 e1e_flush();
207 }
208
209 return 0;
210}
211
212/**
213 * e1000_mng_host_if_write - Write to the manageability host interface
214 * @hw: pointer to the HW structure
215 * @buffer: pointer to the host interface buffer
216 * @length: size of the buffer
217 * @offset: location in the buffer to write to
218 * @sum: sum of the data (not checksum)
219 *
220 * This function writes the buffer content at the offset given on the host if.
221 * It also does alignment considerations to do the writes in most efficient
222 * way. Also fills up the sum of the buffer in *buffer parameter.
223 **/
224static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer,
225 u16 length, u16 offset, u8 *sum)
226{
227 u8 *tmp;
228 u8 *bufptr = buffer;
229 u32 data = 0;
230 u16 remaining, i, j, prev_bytes;
231
232 /* sum = only sum of the data and it is not checksum */
233
234 if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH)
235 return -E1000_ERR_PARAM;
236
237 tmp = (u8 *)&data;
238 prev_bytes = offset & 0x3;
239 offset >>= 2;
240
241 if (prev_bytes) {
242 data = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset);
243 for (j = prev_bytes; j < sizeof(u32); j++) {
244 *(tmp + j) = *bufptr++;
245 *sum += *(tmp + j);
246 }
247 E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset, data);
248 length -= j - prev_bytes;
249 offset++;
250 }
251
252 remaining = length & 0x3;
253 length -= remaining;
254
255 /* Calculate length in DWORDs */
256 length >>= 2;
257
258 /*
259 * The device driver writes the relevant command block into the
260 * ram area.
261 */
262 for (i = 0; i < length; i++) {
263 for (j = 0; j < sizeof(u32); j++) {
264 *(tmp + j) = *bufptr++;
265 *sum += *(tmp + j);
266 }
267
268 E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data);
269 }
270 if (remaining) {
271 for (j = 0; j < sizeof(u32); j++) {
272 if (j < remaining)
273 *(tmp + j) = *bufptr++;
274 else
275 *(tmp + j) = 0;
276
277 *sum += *(tmp + j);
278 }
279 E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data);
280 }
281
282 return 0;
283}
284
285/**
286 * e1000e_mng_write_dhcp_info - Writes DHCP info to host interface
287 * @hw: pointer to the HW structure
288 * @buffer: pointer to the host interface
289 * @length: size of the buffer
290 *
291 * Writes the DHCP information to the host interface.
292 **/
293s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length)
294{
295 struct e1000_host_mng_command_header hdr;
296 s32 ret_val;
297 u32 hicr;
298
299 hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
300 hdr.command_length = length;
301 hdr.reserved1 = 0;
302 hdr.reserved2 = 0;
303 hdr.checksum = 0;
304
305 /* Enable the host interface */
306 ret_val = e1000_mng_enable_host_if(hw);
307 if (ret_val)
308 return ret_val;
309
310 /* Populate the host interface with the contents of "buffer". */
311 ret_val = e1000_mng_host_if_write(hw, buffer, length,
312 sizeof(hdr), &(hdr.checksum));
313 if (ret_val)
314 return ret_val;
315
316 /* Write the manageability command header */
317 ret_val = e1000_mng_write_cmd_header(hw, &hdr);
318 if (ret_val)
319 return ret_val;
320
321 /* Tell the ARC a new command is pending. */
322 hicr = er32(HICR);
323 ew32(HICR, hicr | E1000_HICR_C);
324
325 return 0;
326}
327
328/**
329 * e1000e_enable_mng_pass_thru - Check if management passthrough is needed
330 * @hw: pointer to the HW structure
331 *
332 * Verifies the hardware needs to leave interface enabled so that frames can
333 * be directed to and from the management interface.
334 **/
335bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
336{
337 u32 manc;
338 u32 fwsm, factps;
339 bool ret_val = false;
340
341 manc = er32(MANC);
342
343 if (!(manc & E1000_MANC_RCV_TCO_EN))
344 goto out;
345
346 if (hw->mac.has_fwsm) {
347 fwsm = er32(FWSM);
348 factps = er32(FACTPS);
349
350 if (!(factps & E1000_FACTPS_MNGCG) &&
351 ((fwsm & E1000_FWSM_MODE_MASK) ==
352 (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
353 ret_val = true;
354 goto out;
355 }
356 } else if ((hw->mac.type == e1000_82574) ||
357 (hw->mac.type == e1000_82583)) {
358 u16 data;
359
360 factps = er32(FACTPS);
361 e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
362
363 if (!(factps & E1000_FACTPS_MNGCG) &&
364 ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
365 (e1000_mng_mode_pt << 13))) {
366 ret_val = true;
367 goto out;
368 }
369 } else if ((manc & E1000_MANC_SMBUS_EN) &&
370 !(manc & E1000_MANC_ASF_EN)) {
371 ret_val = true;
372 goto out;
373 }
374
375out:
376 return ret_val;
377}