kni: initial import
[dpdk.git] / lib / librte_eal / linuxapp / kni / ethtool / igb / e1000_manage.c
1 /*******************************************************************************
2
3   Intel(R) Gigabit Ethernet Linux driver
4   Copyright(c) 2007-2012 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   e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
24   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
25
26 *******************************************************************************/
27
28 #include "e1000_api.h"
29
30 /**
31  *  e1000_calculate_checksum - Calculate checksum for buffer
32  *  @buffer: pointer to EEPROM
33  *  @length: size of EEPROM to calculate a checksum for
34  *
35  *  Calculates the checksum for some buffer on a specified length.  The
36  *  checksum calculated is returned.
37  **/
38 u8 e1000_calculate_checksum(u8 *buffer, u32 length)
39 {
40         u32 i;
41         u8 sum = 0;
42
43         DEBUGFUNC("e1000_calculate_checksum");
44
45         if (!buffer)
46                 return 0;
47
48         for (i = 0; i < length; i++)
49                 sum += buffer[i];
50
51         return (u8) (0 - sum);
52 }
53
54 /**
55  *  e1000_mng_enable_host_if_generic - Checks host interface is enabled
56  *  @hw: pointer to the HW structure
57  *
58  *  Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
59  *
60  *  This function checks whether the HOST IF is enabled for command operation
61  *  and also checks whether the previous command is completed.  It busy waits
62  *  in case of previous command is not completed.
63  **/
64 s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
65 {
66         u32 hicr;
67         u8 i;
68
69         DEBUGFUNC("e1000_mng_enable_host_if_generic");
70
71         if (!hw->mac.arc_subsystem_valid) {
72                 DEBUGOUT("ARC subsystem not valid.\n");
73                 return -E1000_ERR_HOST_INTERFACE_COMMAND;
74         }
75
76         /* Check that the host interface is enabled. */
77         hicr = E1000_READ_REG(hw, E1000_HICR);
78         if ((hicr & E1000_HICR_EN) == 0) {
79                 DEBUGOUT("E1000_HOST_EN bit disabled.\n");
80                 return -E1000_ERR_HOST_INTERFACE_COMMAND;
81         }
82         /* check the previous command is completed */
83         for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
84                 hicr = E1000_READ_REG(hw, E1000_HICR);
85                 if (!(hicr & E1000_HICR_C))
86                         break;
87                 msec_delay_irq(1);
88         }
89
90         if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
91                 DEBUGOUT("Previous command timeout failed .\n");
92                 return -E1000_ERR_HOST_INTERFACE_COMMAND;
93         }
94
95         return E1000_SUCCESS;
96 }
97
98 /**
99  *  e1000_check_mng_mode_generic - Generic check management mode
100  *  @hw: pointer to the HW structure
101  *
102  *  Reads the firmware semaphore register and returns true (>0) if
103  *  manageability is enabled, else false (0).
104  **/
105 bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
106 {
107         u32 fwsm = E1000_READ_REG(hw, E1000_FWSM);
108
109         DEBUGFUNC("e1000_check_mng_mode_generic");
110
111
112         return (fwsm & E1000_FWSM_MODE_MASK) ==
113                 (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
114 }
115
116 /**
117  *  e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on Tx
118  *  @hw: pointer to the HW structure
119  *
120  *  Enables packet filtering on transmit packets if manageability is enabled
121  *  and host interface is enabled.
122  **/
123 bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
124 {
125         struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
126         u32 *buffer = (u32 *)&hw->mng_cookie;
127         u32 offset;
128         s32 ret_val, hdr_csum, csum;
129         u8 i, len;
130
131         DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
132
133         hw->mac.tx_pkt_filtering = true;
134
135         /* No manageability, no filtering */
136         if (!hw->mac.ops.check_mng_mode(hw)) {
137                 hw->mac.tx_pkt_filtering = false;
138                 return hw->mac.tx_pkt_filtering;
139         }
140
141         /*
142          * If we can't read from the host interface for whatever
143          * reason, disable filtering.
144          */
145         ret_val = hw->mac.ops.mng_enable_host_if(hw);
146         if (ret_val != E1000_SUCCESS) {
147                 hw->mac.tx_pkt_filtering = false;
148                 return hw->mac.tx_pkt_filtering;
149         }
150
151         /* Read in the header.  Length and offset are in dwords. */
152         len    = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
153         offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
154         for (i = 0; i < len; i++)
155                 *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
156                                                            offset + i);
157         hdr_csum = hdr->checksum;
158         hdr->checksum = 0;
159         csum = e1000_calculate_checksum((u8 *)hdr,
160                                         E1000_MNG_DHCP_COOKIE_LENGTH);
161         /*
162          * If either the checksums or signature don't match, then
163          * the cookie area isn't considered valid, in which case we
164          * take the safe route of assuming Tx filtering is enabled.
165          */
166         if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
167                 hw->mac.tx_pkt_filtering = true;
168                 return hw->mac.tx_pkt_filtering;
169         }
170
171         /* Cookie area is valid, make the final check for filtering. */
172         if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
173                 hw->mac.tx_pkt_filtering = false;
174
175         return hw->mac.tx_pkt_filtering;
176 }
177
178 /**
179  *  e1000_mng_write_cmd_header_generic - Writes manageability command header
180  *  @hw: pointer to the HW structure
181  *  @hdr: pointer to the host interface command header
182  *
183  *  Writes the command header after does the checksum calculation.
184  **/
185 s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
186                                       struct e1000_host_mng_command_header *hdr)
187 {
188         u16 i, length = sizeof(struct e1000_host_mng_command_header);
189
190         DEBUGFUNC("e1000_mng_write_cmd_header_generic");
191
192         /* Write the whole command header structure with new checksum. */
193
194         hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
195
196         length >>= 2;
197         /* Write the relevant command block into the ram area. */
198         for (i = 0; i < length; i++) {
199                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
200                                             *((u32 *) hdr + i));
201                 E1000_WRITE_FLUSH(hw);
202         }
203
204         return E1000_SUCCESS;
205 }
206
207 /**
208  *  e1000_mng_host_if_write_generic - Write to the manageability host interface
209  *  @hw: pointer to the HW structure
210  *  @buffer: pointer to the host interface buffer
211  *  @length: size of the buffer
212  *  @offset: location in the buffer to write to
213  *  @sum: sum of the data (not checksum)
214  *
215  *  This function writes the buffer content at the offset given on the host if.
216  *  It also does alignment considerations to do the writes in most efficient
217  *  way.  Also fills up the sum of the buffer in *buffer parameter.
218  **/
219 s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
220                                     u16 length, u16 offset, u8 *sum)
221 {
222         u8 *tmp;
223         u8 *bufptr = buffer;
224         u32 data = 0;
225         u16 remaining, i, j, prev_bytes;
226
227         DEBUGFUNC("e1000_mng_host_if_write_generic");
228
229         /* sum = only sum of the data and it is not checksum */
230
231         if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH)
232                 return -E1000_ERR_PARAM;
233
234         tmp = (u8 *)&data;
235         prev_bytes = offset & 0x3;
236         offset >>= 2;
237
238         if (prev_bytes) {
239                 data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
240                 for (j = prev_bytes; j < sizeof(u32); j++) {
241                         *(tmp + j) = *bufptr++;
242                         *sum += *(tmp + j);
243                 }
244                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
245                 length -= j - prev_bytes;
246                 offset++;
247         }
248
249         remaining = length & 0x3;
250         length -= remaining;
251
252         /* Calculate length in DWORDs */
253         length >>= 2;
254
255         /*
256          * The device driver writes the relevant command block into the
257          * ram area.
258          */
259         for (i = 0; i < length; i++) {
260                 for (j = 0; j < sizeof(u32); j++) {
261                         *(tmp + j) = *bufptr++;
262                         *sum += *(tmp + j);
263                 }
264
265                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
266                                             data);
267         }
268         if (remaining) {
269                 for (j = 0; j < sizeof(u32); j++) {
270                         if (j < remaining)
271                                 *(tmp + j) = *bufptr++;
272                         else
273                                 *(tmp + j) = 0;
274
275                         *sum += *(tmp + j);
276                 }
277                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
278                                             data);
279         }
280
281         return E1000_SUCCESS;
282 }
283
284 /**
285  *  e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
286  *  @hw: pointer to the HW structure
287  *  @buffer: pointer to the host interface
288  *  @length: size of the buffer
289  *
290  *  Writes the DHCP information to the host interface.
291  **/
292 s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
293                                       u16 length)
294 {
295         struct e1000_host_mng_command_header hdr;
296         s32 ret_val;
297         u32 hicr;
298
299         DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
300
301         hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
302         hdr.command_length = length;
303         hdr.reserved1 = 0;
304         hdr.reserved2 = 0;
305         hdr.checksum = 0;
306
307         /* Enable the host interface */
308         ret_val = hw->mac.ops.mng_enable_host_if(hw);
309         if (ret_val)
310                 return ret_val;
311
312         /* Populate the host interface with the contents of "buffer". */
313         ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
314                                                 sizeof(hdr), &(hdr.checksum));
315         if (ret_val)
316                 return ret_val;
317
318         /* Write the manageability command header */
319         ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
320         if (ret_val)
321                 return ret_val;
322
323         /* Tell the ARC a new command is pending. */
324         hicr = E1000_READ_REG(hw, E1000_HICR);
325         E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
326
327         return E1000_SUCCESS;
328 }
329
330 /**
331  *  e1000_enable_mng_pass_thru - Check if management passthrough is needed
332  *  @hw: pointer to the HW structure
333  *
334  *  Verifies the hardware needs to leave interface enabled so that frames can
335  *  be directed to and from the management interface.
336  **/
337 bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
338 {
339         u32 manc;
340         u32 fwsm, factps;
341
342         DEBUGFUNC("e1000_enable_mng_pass_thru");
343
344         if (!hw->mac.asf_firmware_present)
345                 return false;
346
347         manc = E1000_READ_REG(hw, E1000_MANC);
348
349         if (!(manc & E1000_MANC_RCV_TCO_EN))
350                 return false;
351
352         if (hw->mac.has_fwsm) {
353                 fwsm = E1000_READ_REG(hw, E1000_FWSM);
354                 factps = E1000_READ_REG(hw, E1000_FACTPS);
355
356                 if (!(factps & E1000_FACTPS_MNGCG) &&
357                     ((fwsm & E1000_FWSM_MODE_MASK) ==
358                      (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT)))
359                         return true;
360         } else if ((manc & E1000_MANC_SMBUS_EN) &&
361                    !(manc & E1000_MANC_ASF_EN)) {
362                         return true;
363         }
364
365         return false;
366 }
367
368 /**
369  *  e1000_host_interface_command - Writes buffer to host interface
370  *  @hw: pointer to the HW structure
371  *  @buffer: contains a command to write
372  *  @length: the byte length of the buffer, must be multiple of 4 bytes
373  *
374  *  Writes a buffer to the Host Interface.  Upon success, returns E1000_SUCCESS
375  *  else returns E1000_ERR_HOST_INTERFACE_COMMAND.
376  **/
377 s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length)
378 {
379         u32 hicr, i;
380
381         DEBUGFUNC("e1000_host_interface_command");
382
383         if (!(hw->mac.arc_subsystem_valid)) {
384                 DEBUGOUT("Hardware doesn't support host interface command.\n");
385                 return E1000_SUCCESS;
386         }
387
388         if (!hw->mac.asf_firmware_present) {
389                 DEBUGOUT("Firmware is not present.\n");
390                 return E1000_SUCCESS;
391         }
392
393         if (length == 0 || length & 0x3 ||
394             length > E1000_HI_MAX_BLOCK_BYTE_LENGTH) {
395                 DEBUGOUT("Buffer length failure.\n");
396                 return -E1000_ERR_HOST_INTERFACE_COMMAND;
397         }
398
399         /* Check that the host interface is enabled. */
400         hicr = E1000_READ_REG(hw, E1000_HICR);
401         if ((hicr & E1000_HICR_EN) == 0) {
402                 DEBUGOUT("E1000_HOST_EN bit disabled.\n");
403                 return -E1000_ERR_HOST_INTERFACE_COMMAND;
404         }
405
406         /* Calculate length in DWORDs */
407         length >>= 2;
408
409         /*
410          * The device driver writes the relevant command block
411          * into the ram area.
412          */
413         for (i = 0; i < length; i++)
414                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
415                                             *((u32 *)buffer + i));
416
417         /* Setting this bit tells the ARC that a new command is pending. */
418         E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
419
420         for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
421                 hicr = E1000_READ_REG(hw, E1000_HICR);
422                 if (!(hicr & E1000_HICR_C))
423                         break;
424                 msec_delay(1);
425         }
426
427         /* Check command successful completion. */
428         if (i == E1000_HI_COMMAND_TIMEOUT ||
429             (!(E1000_READ_REG(hw, E1000_HICR) & E1000_HICR_SV))) {
430                 DEBUGOUT("Command has failed with no status valid.\n");
431                 return -E1000_ERR_HOST_INTERFACE_COMMAND;
432         }
433
434         for (i = 0; i < length; i++)
435                 *((u32 *)buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
436                                                                   E1000_HOST_IF,
437                                                                   i);
438
439         return E1000_SUCCESS;
440 }
441