2008-04-02 22:00:36 +00:00
|
|
|
/******************************************************************************
|
2007-05-04 00:00:12 +00:00
|
|
|
|
2010-01-26 22:32:22 +00:00
|
|
|
Copyright (c) 2001-2010, Intel Corporation
|
2007-05-04 00:00:12 +00:00
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
|
|
|
|
1. Redistributions of source code must retain the above copyright notice,
|
|
|
|
this list of conditions and the following disclaimer.
|
|
|
|
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
|
|
|
|
3. Neither the name of the Intel Corporation nor the names of its
|
|
|
|
contributors may be used to endorse or promote products derived from
|
|
|
|
this software without specific prior written permission.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
2008-04-02 22:00:36 +00:00
|
|
|
******************************************************************************/
|
|
|
|
/*$FreeBSD$*/
|
2007-05-04 00:00:12 +00:00
|
|
|
|
2007-05-16 00:14:23 +00:00
|
|
|
#include "e1000_api.h"
|
2007-05-04 00:00:12 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* e1000_calculate_checksum - Calculate checksum for buffer
|
2007-05-16 00:14:23 +00:00
|
|
|
* @buffer: pointer to EEPROM
|
|
|
|
* @length: size of EEPROM to calculate a checksum for
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Calculates the checksum for some buffer on a specified length. The
|
|
|
|
* checksum calculated is returned.
|
|
|
|
**/
|
Add support for the new I350 family of 1G interfaces.
- this also includes virtualization support on these devices
Correct some vlan issues we were seeing in test, jumbo frames on vlans
did not work correctly, this was all due to confused logic around HW
filters, the new code should now work for all uses.
Important fix: when mbuf resources are depeleted, it was possible to
completely empty the RX ring, and then the RX engine would stall
forever. This is fixed by a flag being set whenever the refresh code
fails due to an mbuf shortage, also the local timer now makes sure
that all queues get an interrupt when it runs, the interrupt code
will then always call rxeof, and in that routine the first thing done
is now to check the refresh flag and call refresh_mbufs. This has been
verified to fix this type 'hang'. Similar code will follow in the other
drivers.
Finally, sync up shared code for the I350 support.
Thanks to everyone that has been reporting issues, and helping in the
debug/test process!!
2011-02-11 01:00:26 +00:00
|
|
|
u8 e1000_calculate_checksum(u8 *buffer, u32 length)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
u32 i;
|
Add support for the new I350 family of 1G interfaces.
- this also includes virtualization support on these devices
Correct some vlan issues we were seeing in test, jumbo frames on vlans
did not work correctly, this was all due to confused logic around HW
filters, the new code should now work for all uses.
Important fix: when mbuf resources are depeleted, it was possible to
completely empty the RX ring, and then the RX engine would stall
forever. This is fixed by a flag being set whenever the refresh code
fails due to an mbuf shortage, also the local timer now makes sure
that all queues get an interrupt when it runs, the interrupt code
will then always call rxeof, and in that routine the first thing done
is now to check the refresh flag and call refresh_mbufs. This has been
verified to fix this type 'hang'. Similar code will follow in the other
drivers.
Finally, sync up shared code for the I350 support.
Thanks to everyone that has been reporting issues, and helping in the
debug/test process!!
2011-02-11 01:00:26 +00:00
|
|
|
u8 sum = 0;
|
2007-05-04 00:00:12 +00:00
|
|
|
|
|
|
|
DEBUGFUNC("e1000_calculate_checksum");
|
|
|
|
|
|
|
|
if (!buffer)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
sum += buffer[i];
|
|
|
|
|
|
|
|
return (u8) (0 - sum);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* e1000_mng_enable_host_if_generic - Checks host interface is enabled
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
|
|
|
|
*
|
2008-02-29 21:50:11 +00:00
|
|
|
* This function checks whether the HOST IF is enabled for command operation
|
2007-05-04 00:00:12 +00:00
|
|
|
* and also checks whether the previous command is completed. It busy waits
|
|
|
|
* in case of previous command is not completed.
|
|
|
|
**/
|
2008-11-26 23:57:23 +00:00
|
|
|
s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
u32 hicr;
|
|
|
|
s32 ret_val = E1000_SUCCESS;
|
2010-01-26 22:32:22 +00:00
|
|
|
u8 i;
|
2007-05-04 00:00:12 +00:00
|
|
|
|
|
|
|
DEBUGFUNC("e1000_mng_enable_host_if_generic");
|
|
|
|
|
Update to igb and em:
em revision 7.0.0:
- Using driver devclass, seperate legacy (pre-pcie) code
into a seperate source file. This will at least help
protect against regression issues. It compiles along
with em, and is transparent to end use, devices in each
appear to be 'emX'. When using em in a modular form this
also allows the legacy stuff to be defined out.
- Add tx and rx rings as in igb, in the 82574 this becomes
actual multiqueue for the first time (2 queues) while in
other PCIE adapters its just make code cleaner.
- Add RX mbuf handling logic that matches igb, this will
eliminate packet drops due to temporary mbuf shortage.
igb revision 1.9.3:
- Following the ixgbe code, use a new approach in what
was called 'get_buf', the routine now has been made
independent of rxeof, it now does the update to the
engine TDT register, this design allows temporary
mbuf resources to become non-critical, not requiring
a packet to be discarded, instead it just returns and
does not increment the tail pointer.
- With the above change it was also unnecessary to keep
'spare' maps around, since we do not have the discard
issue.
- Performance tweaks and improvements to the code also.
MFC in a week
2010-03-29 23:36:34 +00:00
|
|
|
if (!(hw->mac.arc_subsystem_valid)) {
|
|
|
|
DEBUGOUT("ARC subsystem not valid.\n");
|
|
|
|
ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2007-05-04 00:00:12 +00:00
|
|
|
/* Check that the host interface is enabled. */
|
|
|
|
hicr = E1000_READ_REG(hw, E1000_HICR);
|
|
|
|
if ((hicr & E1000_HICR_EN) == 0) {
|
|
|
|
DEBUGOUT("E1000_HOST_EN bit disabled.\n");
|
|
|
|
ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
/* check the previous command is completed */
|
|
|
|
for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
|
|
|
|
hicr = E1000_READ_REG(hw, E1000_HICR);
|
|
|
|
if (!(hicr & E1000_HICR_C))
|
|
|
|
break;
|
|
|
|
msec_delay_irq(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
|
|
|
|
DEBUGOUT("Previous command timeout failed .\n");
|
|
|
|
ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-02-29 21:50:11 +00:00
|
|
|
* e1000_check_mng_mode_generic - Generic check management mode
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
2008-04-02 22:00:36 +00:00
|
|
|
* Reads the firmware semaphore register and returns TRUE (>0) if
|
|
|
|
* manageability is enabled, else FALSE (0).
|
2007-05-04 00:00:12 +00:00
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
2010-01-26 22:32:22 +00:00
|
|
|
u32 fwsm = E1000_READ_REG(hw, E1000_FWSM);
|
2007-05-04 00:00:12 +00:00
|
|
|
|
|
|
|
DEBUGFUNC("e1000_check_mng_mode_generic");
|
|
|
|
|
|
|
|
|
2008-11-26 23:57:23 +00:00
|
|
|
return (fwsm & E1000_FWSM_MODE_MASK) ==
|
|
|
|
(E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
|
2007-05-04 00:00:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2009-12-08 01:07:44 +00:00
|
|
|
* e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on Tx
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Enables packet filtering on transmit packets if manageability is enabled
|
|
|
|
* and host interface is enabled.
|
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
|
|
|
|
u32 *buffer = (u32 *)&hw->mng_cookie;
|
|
|
|
u32 offset;
|
|
|
|
s32 ret_val, hdr_csum, csum;
|
|
|
|
u8 i, len;
|
|
|
|
|
|
|
|
DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
|
|
|
|
|
2010-01-26 22:32:22 +00:00
|
|
|
hw->mac.tx_pkt_filtering = TRUE;
|
|
|
|
|
2007-05-04 00:00:12 +00:00
|
|
|
/* No manageability, no filtering */
|
2008-04-02 22:00:36 +00:00
|
|
|
if (!hw->mac.ops.check_mng_mode(hw)) {
|
2010-01-26 22:32:22 +00:00
|
|
|
hw->mac.tx_pkt_filtering = FALSE;
|
2007-05-04 00:00:12 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* If we can't read from the host interface for whatever
|
2007-05-04 00:00:12 +00:00
|
|
|
* reason, disable filtering.
|
|
|
|
*/
|
2008-04-02 22:00:36 +00:00
|
|
|
ret_val = hw->mac.ops.mng_enable_host_if(hw);
|
2007-05-04 00:00:12 +00:00
|
|
|
if (ret_val != E1000_SUCCESS) {
|
2010-01-26 22:32:22 +00:00
|
|
|
hw->mac.tx_pkt_filtering = FALSE;
|
2007-05-04 00:00:12 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read in the header. Length and offset are in dwords. */
|
|
|
|
len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
|
|
|
|
offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
|
2009-12-08 01:07:44 +00:00
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
*(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
|
2008-02-29 21:50:11 +00:00
|
|
|
offset + i);
|
2007-05-04 00:00:12 +00:00
|
|
|
hdr_csum = hdr->checksum;
|
|
|
|
hdr->checksum = 0;
|
|
|
|
csum = e1000_calculate_checksum((u8 *)hdr,
|
|
|
|
E1000_MNG_DHCP_COOKIE_LENGTH);
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* If either the checksums or signature don't match, then
|
2007-05-04 00:00:12 +00:00
|
|
|
* the cookie area isn't considered valid, in which case we
|
|
|
|
* take the safe route of assuming Tx filtering is enabled.
|
|
|
|
*/
|
2010-01-26 22:32:22 +00:00
|
|
|
if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
|
|
|
|
hw->mac.tx_pkt_filtering = TRUE;
|
2007-05-04 00:00:12 +00:00
|
|
|
goto out;
|
2010-01-26 22:32:22 +00:00
|
|
|
}
|
2007-05-04 00:00:12 +00:00
|
|
|
|
|
|
|
/* Cookie area is valid, make the final check for filtering. */
|
2010-01-26 22:32:22 +00:00
|
|
|
if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) {
|
|
|
|
hw->mac.tx_pkt_filtering = FALSE;
|
|
|
|
goto out;
|
|
|
|
}
|
2007-05-04 00:00:12 +00:00
|
|
|
|
|
|
|
out:
|
2010-01-26 22:32:22 +00:00
|
|
|
return hw->mac.tx_pkt_filtering;
|
2007-05-04 00:00:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
* @buffer: pointer to the host interface
|
|
|
|
* @length: size of the buffer
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Writes the DHCP information to the host interface.
|
|
|
|
**/
|
2008-11-26 23:57:23 +00:00
|
|
|
s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
|
2007-11-20 21:41:22 +00:00
|
|
|
u16 length)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
struct e1000_host_mng_command_header hdr;
|
|
|
|
s32 ret_val;
|
|
|
|
u32 hicr;
|
|
|
|
|
|
|
|
DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
|
|
|
|
|
|
|
|
hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
|
|
|
|
hdr.command_length = length;
|
|
|
|
hdr.reserved1 = 0;
|
|
|
|
hdr.reserved2 = 0;
|
|
|
|
hdr.checksum = 0;
|
|
|
|
|
|
|
|
/* Enable the host interface */
|
2008-04-02 22:00:36 +00:00
|
|
|
ret_val = hw->mac.ops.mng_enable_host_if(hw);
|
2007-05-04 00:00:12 +00:00
|
|
|
if (ret_val)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* Populate the host interface with the contents of "buffer". */
|
2008-04-02 22:00:36 +00:00
|
|
|
ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
|
2007-05-04 00:00:12 +00:00
|
|
|
sizeof(hdr), &(hdr.checksum));
|
|
|
|
if (ret_val)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* Write the manageability command header */
|
2008-04-02 22:00:36 +00:00
|
|
|
ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
|
2007-05-04 00:00:12 +00:00
|
|
|
if (ret_val)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* Tell the ARC a new command is pending. */
|
|
|
|
hicr = E1000_READ_REG(hw, E1000_HICR);
|
|
|
|
E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
|
|
|
|
|
|
|
|
out:
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* e1000_mng_write_cmd_header_generic - Writes manageability command header
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
* @hdr: pointer to the host interface command header
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* Writes the command header after does the checksum calculation.
|
|
|
|
**/
|
2008-11-26 23:57:23 +00:00
|
|
|
s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
|
|
|
|
struct e1000_host_mng_command_header *hdr)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
u16 i, length = sizeof(struct e1000_host_mng_command_header);
|
|
|
|
|
|
|
|
DEBUGFUNC("e1000_mng_write_cmd_header_generic");
|
|
|
|
|
|
|
|
/* Write the whole command header structure with new checksum. */
|
|
|
|
|
|
|
|
hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
|
|
|
|
|
|
|
|
length >>= 2;
|
|
|
|
/* Write the relevant command block into the ram area. */
|
|
|
|
for (i = 0; i < length; i++) {
|
2007-11-20 21:41:22 +00:00
|
|
|
E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
|
|
|
|
*((u32 *) hdr + i));
|
2007-05-04 00:00:12 +00:00
|
|
|
E1000_WRITE_FLUSH(hw);
|
|
|
|
}
|
|
|
|
|
|
|
|
return E1000_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-02-29 21:50:11 +00:00
|
|
|
* e1000_mng_host_if_write_generic - Write to the manageability host interface
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
* @buffer: pointer to the host interface buffer
|
|
|
|
* @length: size of the buffer
|
|
|
|
* @offset: location in the buffer to write to
|
|
|
|
* @sum: sum of the data (not checksum)
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
|
|
|
* This function writes the buffer content at the offset given on the host if.
|
|
|
|
* It also does alignment considerations to do the writes in most efficient
|
|
|
|
* way. Also fills up the sum of the buffer in *buffer parameter.
|
|
|
|
**/
|
2008-11-26 23:57:23 +00:00
|
|
|
s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
|
2007-11-20 21:41:22 +00:00
|
|
|
u16 length, u16 offset, u8 *sum)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
u8 *tmp;
|
|
|
|
u8 *bufptr = buffer;
|
|
|
|
u32 data = 0;
|
|
|
|
s32 ret_val = E1000_SUCCESS;
|
|
|
|
u16 remaining, i, j, prev_bytes;
|
|
|
|
|
|
|
|
DEBUGFUNC("e1000_mng_host_if_write_generic");
|
|
|
|
|
|
|
|
/* sum = only sum of the data and it is not checksum */
|
|
|
|
|
|
|
|
if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
|
|
|
|
ret_val = -E1000_ERR_PARAM;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = (u8 *)&data;
|
|
|
|
prev_bytes = offset & 0x3;
|
|
|
|
offset >>= 2;
|
|
|
|
|
|
|
|
if (prev_bytes) {
|
|
|
|
data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
|
|
|
|
for (j = prev_bytes; j < sizeof(u32); j++) {
|
|
|
|
*(tmp + j) = *bufptr++;
|
|
|
|
*sum += *(tmp + j);
|
|
|
|
}
|
|
|
|
E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
|
|
|
|
length -= j - prev_bytes;
|
|
|
|
offset++;
|
|
|
|
}
|
|
|
|
|
|
|
|
remaining = length & 0x3;
|
|
|
|
length -= remaining;
|
|
|
|
|
|
|
|
/* Calculate length in DWORDs */
|
|
|
|
length >>= 2;
|
|
|
|
|
2007-11-20 21:41:22 +00:00
|
|
|
/*
|
|
|
|
* The device driver writes the relevant command block into the
|
|
|
|
* ram area.
|
|
|
|
*/
|
2007-05-04 00:00:12 +00:00
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
for (j = 0; j < sizeof(u32); j++) {
|
|
|
|
*(tmp + j) = *bufptr++;
|
|
|
|
*sum += *(tmp + j);
|
|
|
|
}
|
|
|
|
|
2008-11-26 23:57:23 +00:00
|
|
|
E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
|
|
|
|
data);
|
2007-05-04 00:00:12 +00:00
|
|
|
}
|
|
|
|
if (remaining) {
|
|
|
|
for (j = 0; j < sizeof(u32); j++) {
|
|
|
|
if (j < remaining)
|
|
|
|
*(tmp + j) = *bufptr++;
|
|
|
|
else
|
|
|
|
*(tmp + j) = 0;
|
|
|
|
|
|
|
|
*sum += *(tmp + j);
|
|
|
|
}
|
|
|
|
E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2010-01-26 22:32:22 +00:00
|
|
|
* e1000_enable_mng_pass_thru - Check if management passthrough is needed
|
2007-05-16 00:14:23 +00:00
|
|
|
* @hw: pointer to the HW structure
|
2007-05-04 00:00:12 +00:00
|
|
|
*
|
2010-01-26 22:32:22 +00:00
|
|
|
* Verifies the hardware needs to leave interface enabled so that frames can
|
|
|
|
* be directed to and from the management interface.
|
2007-05-04 00:00:12 +00:00
|
|
|
**/
|
2007-11-20 21:41:22 +00:00
|
|
|
bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
|
2007-05-04 00:00:12 +00:00
|
|
|
{
|
|
|
|
u32 manc;
|
|
|
|
u32 fwsm, factps;
|
2007-11-20 21:41:22 +00:00
|
|
|
bool ret_val = FALSE;
|
2007-05-04 00:00:12 +00:00
|
|
|
|
|
|
|
DEBUGFUNC("e1000_enable_mng_pass_thru");
|
|
|
|
|
|
|
|
if (!hw->mac.asf_firmware_present)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
manc = E1000_READ_REG(hw, E1000_MANC);
|
|
|
|
|
2010-01-26 22:32:22 +00:00
|
|
|
if (!(manc & E1000_MANC_RCV_TCO_EN))
|
2007-05-04 00:00:12 +00:00
|
|
|
goto out;
|
|
|
|
|
Update to igb and em:
em revision 7.0.0:
- Using driver devclass, seperate legacy (pre-pcie) code
into a seperate source file. This will at least help
protect against regression issues. It compiles along
with em, and is transparent to end use, devices in each
appear to be 'emX'. When using em in a modular form this
also allows the legacy stuff to be defined out.
- Add tx and rx rings as in igb, in the 82574 this becomes
actual multiqueue for the first time (2 queues) while in
other PCIE adapters its just make code cleaner.
- Add RX mbuf handling logic that matches igb, this will
eliminate packet drops due to temporary mbuf shortage.
igb revision 1.9.3:
- Following the ixgbe code, use a new approach in what
was called 'get_buf', the routine now has been made
independent of rxeof, it now does the update to the
engine TDT register, this design allows temporary
mbuf resources to become non-critical, not requiring
a packet to be discarded, instead it just returns and
does not increment the tail pointer.
- With the above change it was also unnecessary to keep
'spare' maps around, since we do not have the discard
issue.
- Performance tweaks and improvements to the code also.
MFC in a week
2010-03-29 23:36:34 +00:00
|
|
|
if (hw->mac.has_fwsm) {
|
2007-05-04 00:00:12 +00:00
|
|
|
fwsm = E1000_READ_REG(hw, E1000_FWSM);
|
|
|
|
factps = E1000_READ_REG(hw, E1000_FACTPS);
|
|
|
|
|
|
|
|
if (!(factps & E1000_FACTPS_MNGCG) &&
|
|
|
|
((fwsm & E1000_FWSM_MODE_MASK) ==
|
|
|
|
(e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
|
|
|
|
ret_val = TRUE;
|
|
|
|
goto out;
|
|
|
|
}
|
Update to igb and em:
em revision 7.0.0:
- Using driver devclass, seperate legacy (pre-pcie) code
into a seperate source file. This will at least help
protect against regression issues. It compiles along
with em, and is transparent to end use, devices in each
appear to be 'emX'. When using em in a modular form this
also allows the legacy stuff to be defined out.
- Add tx and rx rings as in igb, in the 82574 this becomes
actual multiqueue for the first time (2 queues) while in
other PCIE adapters its just make code cleaner.
- Add RX mbuf handling logic that matches igb, this will
eliminate packet drops due to temporary mbuf shortage.
igb revision 1.9.3:
- Following the ixgbe code, use a new approach in what
was called 'get_buf', the routine now has been made
independent of rxeof, it now does the update to the
engine TDT register, this design allows temporary
mbuf resources to become non-critical, not requiring
a packet to be discarded, instead it just returns and
does not increment the tail pointer.
- With the above change it was also unnecessary to keep
'spare' maps around, since we do not have the discard
issue.
- Performance tweaks and improvements to the code also.
MFC in a week
2010-03-29 23:36:34 +00:00
|
|
|
} else if ((hw->mac.type == e1000_82574) ||
|
|
|
|
(hw->mac.type == e1000_82583)) {
|
|
|
|
u16 data;
|
|
|
|
|
|
|
|
factps = E1000_READ_REG(hw, E1000_FACTPS);
|
|
|
|
e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
|
|
|
|
|
|
|
|
if (!(factps & E1000_FACTPS_MNGCG) &&
|
|
|
|
((data & E1000_NVM_INIT_CTRL2_MNGM) ==
|
|
|
|
(e1000_mng_mode_pt << 13))) {
|
2007-05-04 00:00:12 +00:00
|
|
|
ret_val = TRUE;
|
|
|
|
goto out;
|
|
|
|
}
|
Update to igb and em:
em revision 7.0.0:
- Using driver devclass, seperate legacy (pre-pcie) code
into a seperate source file. This will at least help
protect against regression issues. It compiles along
with em, and is transparent to end use, devices in each
appear to be 'emX'. When using em in a modular form this
also allows the legacy stuff to be defined out.
- Add tx and rx rings as in igb, in the 82574 this becomes
actual multiqueue for the first time (2 queues) while in
other PCIE adapters its just make code cleaner.
- Add RX mbuf handling logic that matches igb, this will
eliminate packet drops due to temporary mbuf shortage.
igb revision 1.9.3:
- Following the ixgbe code, use a new approach in what
was called 'get_buf', the routine now has been made
independent of rxeof, it now does the update to the
engine TDT register, this design allows temporary
mbuf resources to become non-critical, not requiring
a packet to be discarded, instead it just returns and
does not increment the tail pointer.
- With the above change it was also unnecessary to keep
'spare' maps around, since we do not have the discard
issue.
- Performance tweaks and improvements to the code also.
MFC in a week
2010-03-29 23:36:34 +00:00
|
|
|
} else if ((manc & E1000_MANC_SMBUS_EN) &&
|
|
|
|
!(manc & E1000_MANC_ASF_EN)) {
|
|
|
|
ret_val = TRUE;
|
|
|
|
goto out;
|
2007-11-20 21:41:22 +00:00
|
|
|
}
|
2007-05-04 00:00:12 +00:00
|
|
|
|
|
|
|
out:
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
Add support for the new I350 family of 1G interfaces.
- this also includes virtualization support on these devices
Correct some vlan issues we were seeing in test, jumbo frames on vlans
did not work correctly, this was all due to confused logic around HW
filters, the new code should now work for all uses.
Important fix: when mbuf resources are depeleted, it was possible to
completely empty the RX ring, and then the RX engine would stall
forever. This is fixed by a flag being set whenever the refresh code
fails due to an mbuf shortage, also the local timer now makes sure
that all queues get an interrupt when it runs, the interrupt code
will then always call rxeof, and in that routine the first thing done
is now to check the refresh flag and call refresh_mbufs. This has been
verified to fix this type 'hang'. Similar code will follow in the other
drivers.
Finally, sync up shared code for the I350 support.
Thanks to everyone that has been reporting issues, and helping in the
debug/test process!!
2011-02-11 01:00:26 +00:00
|
|
|
/**
|
|
|
|
* e1000_host_interface_command - Writes buffer to host interface
|
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
* @buffer: contains a command to write
|
|
|
|
* @length: the byte length of the buffer, must be multiple of 4 bytes
|
|
|
|
*
|
|
|
|
* Writes a buffer to the Host Interface. Upon success, returns E1000_SUCCESS
|
|
|
|
* else returns E1000_ERR_HOST_INTERFACE_COMMAND.
|
|
|
|
**/
|
|
|
|
s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length)
|
|
|
|
{
|
|
|
|
u32 hicr, i;
|
|
|
|
s32 ret_val = E1000_SUCCESS;
|
|
|
|
|
|
|
|
DEBUGFUNC("e1000_host_interface_command");
|
|
|
|
|
|
|
|
if (!(hw->mac.arc_subsystem_valid)) {
|
|
|
|
DEBUGOUT("Hardware doesn't support host interface command.\n");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hw->mac.asf_firmware_present) {
|
|
|
|
DEBUGOUT("Firmware is not present.\n");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (length == 0 || length & 0x3 ||
|
|
|
|
length > E1000_HI_MAX_BLOCK_BYTE_LENGTH) {
|
|
|
|
DEBUGOUT("Buffer length failure.\n");
|
|
|
|
ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check that the host interface is enabled. */
|
|
|
|
hicr = E1000_READ_REG(hw, E1000_HICR);
|
|
|
|
if ((hicr & E1000_HICR_EN) == 0) {
|
|
|
|
DEBUGOUT("E1000_HOST_EN bit disabled.\n");
|
|
|
|
ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculate length in DWORDs */
|
|
|
|
length >>= 2;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The device driver writes the relevant command block
|
|
|
|
* into the ram area.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
E1000_WRITE_REG_ARRAY_DWORD(hw,
|
|
|
|
E1000_HOST_IF,
|
|
|
|
i,
|
|
|
|
*((u32 *)buffer + i));
|
|
|
|
|
|
|
|
/* Setting this bit tells the ARC that a new command is pending. */
|
|
|
|
E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
|
|
|
|
|
|
|
|
for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
|
|
|
|
hicr = E1000_READ_REG(hw, E1000_HICR);
|
|
|
|
if (!(hicr & E1000_HICR_C))
|
|
|
|
break;
|
|
|
|
msec_delay(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check command successful completion. */
|
|
|
|
if (i == E1000_HI_COMMAND_TIMEOUT ||
|
|
|
|
(!(E1000_READ_REG(hw, E1000_HICR) & E1000_HICR_SV))) {
|
|
|
|
DEBUGOUT("Command has failed with no status valid.\n");
|
|
|
|
ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
*((u32 *)buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
|
|
|
|
E1000_HOST_IF,
|
|
|
|
i);
|
|
|
|
|
|
|
|
out:
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|