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