ipro1000: Upgrade to FreeBSD 12.
Thanks to AGMS for helping test on real hardware!
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel drivers network ipro1000 ;
|
||||
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_network compat ]
|
||||
: true ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_iflib compat ] : true ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_network compat ] : true ;
|
||||
UsePrivateHeaders net system ;
|
||||
UsePrivateKernelHeaders ;
|
||||
|
||||
@@ -12,6 +12,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) dev e1000 ] ;
|
||||
SubDirCcFlags [ FDefines _KERNEL=1 FBSD_DRIVER=1 _XOPEN_SOURCE ] ;
|
||||
|
||||
KernelAddon ipro1000 :
|
||||
glue.c
|
||||
e1000_80003es2lan.c
|
||||
e1000_82540.c
|
||||
e1000_82541.c
|
||||
@@ -29,10 +30,8 @@ KernelAddon ipro1000 :
|
||||
e1000_osdep.c
|
||||
e1000_phy.c
|
||||
e1000_vf.c
|
||||
if_lem.c
|
||||
em_txrx.c
|
||||
if_em.c
|
||||
if_igb.c
|
||||
|
||||
glue.c
|
||||
: libfreebsd_network.a
|
||||
igb_txrx.c
|
||||
: freebsd_iflib.a libfreebsd_network.a
|
||||
;
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
$FreeBSD: releng/12.0/sys/dev/e1000/LICENSE 203049 2010-01-26 22:32:22Z jfv $
|
||||
|
||||
Copyright (c) 2001-2010, Intel Corporation
|
||||
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.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_80003es2lan.c 333345 2018-05-08 01:39:45Z mmacy $*/
|
||||
|
||||
/* 80003ES2LAN Gigabit Ethernet Controller (Copper)
|
||||
* 80003ES2LAN Gigabit Ethernet Controller (Serdes)
|
||||
@@ -59,7 +60,6 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw);
|
||||
static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw);
|
||||
static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw);
|
||||
static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw);
|
||||
static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask);
|
||||
static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex);
|
||||
static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw);
|
||||
static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw);
|
||||
@@ -68,7 +68,6 @@ static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
|
||||
static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
|
||||
u16 data);
|
||||
static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw);
|
||||
static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask);
|
||||
static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw);
|
||||
static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw);
|
||||
|
||||
@@ -299,7 +298,7 @@ static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw)
|
||||
DEBUGFUNC("e1000_acquire_phy_80003es2lan");
|
||||
|
||||
mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
|
||||
return e1000_acquire_swfw_sync_80003es2lan(hw, mask);
|
||||
return e1000_acquire_swfw_sync(hw, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -315,7 +314,7 @@ static void e1000_release_phy_80003es2lan(struct e1000_hw *hw)
|
||||
DEBUGFUNC("e1000_release_phy_80003es2lan");
|
||||
|
||||
mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
|
||||
e1000_release_swfw_sync_80003es2lan(hw, mask);
|
||||
e1000_release_swfw_sync(hw, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -333,7 +332,7 @@ static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw)
|
||||
|
||||
mask = E1000_SWFW_CSR_SM;
|
||||
|
||||
return e1000_acquire_swfw_sync_80003es2lan(hw, mask);
|
||||
return e1000_acquire_swfw_sync(hw, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -350,7 +349,7 @@ static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw)
|
||||
|
||||
mask = E1000_SWFW_CSR_SM;
|
||||
|
||||
e1000_release_swfw_sync_80003es2lan(hw, mask);
|
||||
e1000_release_swfw_sync(hw, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -365,14 +364,14 @@ static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw)
|
||||
|
||||
DEBUGFUNC("e1000_acquire_nvm_80003es2lan");
|
||||
|
||||
ret_val = e1000_acquire_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM);
|
||||
ret_val = e1000_acquire_swfw_sync(hw, E1000_SWFW_EEP_SM);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
ret_val = e1000_acquire_nvm_generic(hw);
|
||||
|
||||
if (ret_val)
|
||||
e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM);
|
||||
e1000_release_swfw_sync(hw, E1000_SWFW_EEP_SM);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
@@ -388,78 +387,7 @@ static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw)
|
||||
DEBUGFUNC("e1000_release_nvm_80003es2lan");
|
||||
|
||||
e1000_release_nvm_generic(hw);
|
||||
e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_acquire_swfw_sync_80003es2lan - Acquire SW/FW semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
* @mask: specifies which semaphore to acquire
|
||||
*
|
||||
* Acquire the SW/FW semaphore to access the PHY or NVM. The mask
|
||||
* will also specify which port we're acquiring the lock for.
|
||||
**/
|
||||
static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
|
||||
{
|
||||
u32 swfw_sync;
|
||||
u32 swmask = mask;
|
||||
u32 fwmask = mask << 16;
|
||||
s32 i = 0;
|
||||
s32 timeout = 50;
|
||||
|
||||
DEBUGFUNC("e1000_acquire_swfw_sync_80003es2lan");
|
||||
|
||||
while (i < timeout) {
|
||||
if (e1000_get_hw_semaphore_generic(hw))
|
||||
return -E1000_ERR_SWFW_SYNC;
|
||||
|
||||
swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
|
||||
if (!(swfw_sync & (fwmask | swmask)))
|
||||
break;
|
||||
|
||||
/* Firmware currently using resource (fwmask)
|
||||
* or other software thread using resource (swmask)
|
||||
*/
|
||||
e1000_put_hw_semaphore_generic(hw);
|
||||
msec_delay_irq(5);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == timeout) {
|
||||
DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
|
||||
return -E1000_ERR_SWFW_SYNC;
|
||||
}
|
||||
|
||||
swfw_sync |= swmask;
|
||||
E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
|
||||
|
||||
e1000_put_hw_semaphore_generic(hw);
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_release_swfw_sync_80003es2lan - Release SW/FW semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
* @mask: specifies which semaphore to acquire
|
||||
*
|
||||
* Release the SW/FW semaphore used to access the PHY or NVM. The mask
|
||||
* will also specify which port we're releasing the lock for.
|
||||
**/
|
||||
static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
|
||||
{
|
||||
u32 swfw_sync;
|
||||
|
||||
DEBUGFUNC("e1000_release_swfw_sync_80003es2lan");
|
||||
|
||||
while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS)
|
||||
; /* Empty */
|
||||
|
||||
swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
|
||||
swfw_sync &= ~mask;
|
||||
E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
|
||||
|
||||
e1000_put_hw_semaphore_generic(hw);
|
||||
e1000_release_swfw_sync(hw, E1000_SWFW_EEP_SM);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_80003es2lan.h 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
#ifndef _E1000_80003ES2LAN_H_
|
||||
#define _E1000_80003ES2LAN_H_
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_82540.c 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
/*
|
||||
* 82540EM Gigabit Ethernet Controller
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_82541.c 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
/*
|
||||
* 82541EI Gigabit Ethernet Controller
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_82541.h 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
#ifndef _E1000_82541_H_
|
||||
#define _E1000_82541_H_
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_82542.c 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
/*
|
||||
* 82542 Gigabit Ethernet Controller
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_82543.c 327231 2017-12-27 03:23:21Z eadler $*/
|
||||
|
||||
/*
|
||||
* 82543GC Gigabit Ethernet Controller (Fiber)
|
||||
@@ -1309,7 +1310,7 @@ static s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw)
|
||||
* turn it on. For compatibility with a TBI link
|
||||
* partner, we will store bad packets. Some
|
||||
* frames have an additional byte on the end and
|
||||
* will look like CRC errors to to the hardware.
|
||||
* will look like CRC errors to the hardware.
|
||||
*/
|
||||
if (!e1000_tbi_sbp_enabled_82543(hw)) {
|
||||
e1000_set_tbi_sbp_82543(hw, TRUE);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_82543.h 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
#ifndef _E1000_82543_H_
|
||||
#define _E1000_82543_H_
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_82571.c 333421 2018-05-09 17:48:52Z mmacy $*/
|
||||
|
||||
/* 82571EB Gigabit Ethernet Controller
|
||||
* 82571EB Gigabit Ethernet Controller (Copper)
|
||||
@@ -70,11 +71,8 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw);
|
||||
static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw);
|
||||
static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data);
|
||||
static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw);
|
||||
static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw);
|
||||
static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw);
|
||||
static s32 e1000_get_phy_id_82571(struct e1000_hw *hw);
|
||||
static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw);
|
||||
static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw);
|
||||
static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw);
|
||||
static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw);
|
||||
static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw,
|
||||
@@ -125,8 +123,8 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
|
||||
phy->ops.get_cable_length = e1000_get_cable_length_igp_2;
|
||||
phy->ops.read_reg = e1000_read_phy_reg_igp;
|
||||
phy->ops.write_reg = e1000_write_phy_reg_igp;
|
||||
phy->ops.acquire = e1000_get_hw_semaphore_82571;
|
||||
phy->ops.release = e1000_put_hw_semaphore_82571;
|
||||
phy->ops.acquire = e1000_get_hw_semaphore;
|
||||
phy->ops.release = e1000_put_hw_semaphore;
|
||||
break;
|
||||
case e1000_82573:
|
||||
phy->type = e1000_phy_m88;
|
||||
@@ -138,12 +136,11 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
|
||||
phy->ops.get_cable_length = e1000_get_cable_length_m88;
|
||||
phy->ops.read_reg = e1000_read_phy_reg_m88;
|
||||
phy->ops.write_reg = e1000_write_phy_reg_m88;
|
||||
phy->ops.acquire = e1000_get_hw_semaphore_82571;
|
||||
phy->ops.release = e1000_put_hw_semaphore_82571;
|
||||
phy->ops.acquire = e1000_get_hw_semaphore;
|
||||
phy->ops.release = e1000_put_hw_semaphore;
|
||||
break;
|
||||
case e1000_82574:
|
||||
case e1000_82583:
|
||||
E1000_MUTEX_INIT(&hw->dev_spec._82571.swflag_mutex);
|
||||
|
||||
phy->type = e1000_phy_bm;
|
||||
phy->ops.get_cfg_done = e1000_get_cfg_done_generic;
|
||||
@@ -506,99 +503,21 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_get_hw_semaphore_82571 - Acquire hardware semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Acquire the HW semaphore to access the PHY or NVM
|
||||
**/
|
||||
static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
|
||||
{
|
||||
u32 swsm;
|
||||
s32 sw_timeout = hw->nvm.word_size + 1;
|
||||
s32 fw_timeout = hw->nvm.word_size + 1;
|
||||
s32 i = 0;
|
||||
|
||||
DEBUGFUNC("e1000_get_hw_semaphore_82571");
|
||||
|
||||
/* If we have timedout 3 times on trying to acquire
|
||||
* the inter-port SMBI semaphore, there is old code
|
||||
* operating on the other port, and it is not
|
||||
* releasing SMBI. Modify the number of times that
|
||||
* we try for the semaphore to interwork with this
|
||||
* older code.
|
||||
*/
|
||||
if (hw->dev_spec._82571.smb_counter > 2)
|
||||
sw_timeout = 1;
|
||||
|
||||
/* Get the SW semaphore */
|
||||
while (i < sw_timeout) {
|
||||
swsm = E1000_READ_REG(hw, E1000_SWSM);
|
||||
if (!(swsm & E1000_SWSM_SMBI))
|
||||
break;
|
||||
|
||||
usec_delay(50);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == sw_timeout) {
|
||||
DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
|
||||
hw->dev_spec._82571.smb_counter++;
|
||||
}
|
||||
/* Get the FW semaphore. */
|
||||
for (i = 0; i < fw_timeout; i++) {
|
||||
swsm = E1000_READ_REG(hw, E1000_SWSM);
|
||||
E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
|
||||
|
||||
/* Semaphore acquired if bit latched */
|
||||
if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI)
|
||||
break;
|
||||
|
||||
usec_delay(50);
|
||||
}
|
||||
|
||||
if (i == fw_timeout) {
|
||||
/* Release semaphores */
|
||||
e1000_put_hw_semaphore_82571(hw);
|
||||
DEBUGOUT("Driver can't access the NVM\n");
|
||||
return -E1000_ERR_NVM;
|
||||
}
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_put_hw_semaphore_82571 - Release hardware semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Release hardware semaphore used to access the PHY or NVM
|
||||
**/
|
||||
static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw)
|
||||
{
|
||||
u32 swsm;
|
||||
|
||||
DEBUGFUNC("e1000_put_hw_semaphore_generic");
|
||||
|
||||
swsm = E1000_READ_REG(hw, E1000_SWSM);
|
||||
|
||||
swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
|
||||
|
||||
E1000_WRITE_REG(hw, E1000_SWSM, swsm);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_get_hw_semaphore_82573 - Acquire hardware semaphore
|
||||
* e1000_get_hw_semaphore_82574 - Acquire hardware semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Acquire the HW semaphore during reset.
|
||||
*
|
||||
**/
|
||||
static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw)
|
||||
static s32
|
||||
e1000_get_hw_semaphore_82574(struct e1000_hw *hw)
|
||||
{
|
||||
u32 extcnf_ctrl;
|
||||
s32 i = 0;
|
||||
|
||||
/* XXX assert that mutex is held */
|
||||
DEBUGFUNC("e1000_get_hw_semaphore_82573");
|
||||
|
||||
ASSERT_CTX_LOCK_HELD(hw);
|
||||
extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
|
||||
do {
|
||||
extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
|
||||
@@ -614,7 +533,7 @@ static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw)
|
||||
|
||||
if (i == MDIO_OWNERSHIP_TIMEOUT) {
|
||||
/* Release semaphores */
|
||||
e1000_put_hw_semaphore_82573(hw);
|
||||
e1000_put_hw_semaphore_82574(hw);
|
||||
DEBUGOUT("Driver can't access the PHY\n");
|
||||
return -E1000_ERR_PHY;
|
||||
}
|
||||
@@ -623,58 +542,24 @@ static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw)
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_put_hw_semaphore_82573 - Release hardware semaphore
|
||||
* e1000_put_hw_semaphore_82574 - Release hardware semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Release hardware semaphore used during reset.
|
||||
*
|
||||
**/
|
||||
static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw)
|
||||
static void
|
||||
e1000_put_hw_semaphore_82574(struct e1000_hw *hw)
|
||||
{
|
||||
u32 extcnf_ctrl;
|
||||
|
||||
DEBUGFUNC("e1000_put_hw_semaphore_82573");
|
||||
DEBUGFUNC("e1000_put_hw_semaphore_82574");
|
||||
|
||||
extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
|
||||
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
|
||||
E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_get_hw_semaphore_82574 - Acquire hardware semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Acquire the HW semaphore to access the PHY or NVM.
|
||||
*
|
||||
**/
|
||||
static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val;
|
||||
|
||||
DEBUGFUNC("e1000_get_hw_semaphore_82574");
|
||||
|
||||
E1000_MUTEX_LOCK(&hw->dev_spec._82571.swflag_mutex);
|
||||
ret_val = e1000_get_hw_semaphore_82573(hw);
|
||||
if (ret_val)
|
||||
E1000_MUTEX_UNLOCK(&hw->dev_spec._82571.swflag_mutex);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_put_hw_semaphore_82574 - Release hardware semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Release hardware semaphore used to access the PHY or NVM
|
||||
*
|
||||
**/
|
||||
static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw)
|
||||
{
|
||||
DEBUGFUNC("e1000_put_hw_semaphore_82574");
|
||||
|
||||
e1000_put_hw_semaphore_82573(hw);
|
||||
E1000_MUTEX_UNLOCK(&hw->dev_spec._82571.swflag_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_set_d0_lplu_state_82574 - Set Low Power Linkup D0 state
|
||||
* @hw: pointer to the HW structure
|
||||
@@ -746,7 +631,7 @@ static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw)
|
||||
|
||||
DEBUGFUNC("e1000_acquire_nvm_82571");
|
||||
|
||||
ret_val = e1000_get_hw_semaphore_82571(hw);
|
||||
ret_val = e1000_get_hw_semaphore(hw);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
@@ -759,7 +644,7 @@ static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw)
|
||||
}
|
||||
|
||||
if (ret_val)
|
||||
e1000_put_hw_semaphore_82571(hw);
|
||||
e1000_put_hw_semaphore(hw);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
@@ -775,7 +660,7 @@ static void e1000_release_nvm_82571(struct e1000_hw *hw)
|
||||
DEBUGFUNC("e1000_release_nvm_82571");
|
||||
|
||||
e1000_release_nvm_generic(hw);
|
||||
e1000_put_hw_semaphore_82571(hw);
|
||||
e1000_put_hw_semaphore(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1092,8 +977,6 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
|
||||
*/
|
||||
switch (hw->mac.type) {
|
||||
case e1000_82573:
|
||||
ret_val = e1000_get_hw_semaphore_82573(hw);
|
||||
break;
|
||||
case e1000_82574:
|
||||
case e1000_82583:
|
||||
ret_val = e1000_get_hw_semaphore_82574(hw);
|
||||
@@ -1110,10 +993,6 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
|
||||
/* Must release MDIO ownership and mutex after MAC reset. */
|
||||
switch (hw->mac.type) {
|
||||
case e1000_82573:
|
||||
/* Release mutex only if the hw semaphore is acquired */
|
||||
if (!ret_val)
|
||||
e1000_put_hw_semaphore_82573(hw);
|
||||
break;
|
||||
case e1000_82574:
|
||||
case e1000_82583:
|
||||
/* Release mutex only if the hw semaphore is acquired */
|
||||
@@ -1121,6 +1000,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
|
||||
e1000_put_hw_semaphore_82574(hw);
|
||||
break;
|
||||
default:
|
||||
/* we didn't get the semaphore no need to put it */
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_82571.h 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
#ifndef _E1000_82571_H_
|
||||
#define _E1000_82571_H_
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_82575.c 333345 2018-05-08 01:39:45Z mmacy $*/
|
||||
|
||||
/*
|
||||
* 82575EB Gigabit Network Connection
|
||||
@@ -79,11 +80,9 @@ static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data);
|
||||
static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw,
|
||||
u32 offset, u16 data);
|
||||
static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw);
|
||||
static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask);
|
||||
static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
|
||||
u16 *speed, u16 *duplex);
|
||||
static s32 e1000_get_phy_id_82575(struct e1000_hw *hw);
|
||||
static void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask);
|
||||
static bool e1000_sgmii_active_82575(struct e1000_hw *hw);
|
||||
static s32 e1000_reset_init_script_82575(struct e1000_hw *hw);
|
||||
static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw);
|
||||
@@ -101,7 +100,6 @@ static s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw,
|
||||
u16 offset);
|
||||
static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw);
|
||||
static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw);
|
||||
static void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value);
|
||||
static void e1000_clear_vfta_i350(struct e1000_hw *hw);
|
||||
|
||||
static void e1000_i2c_start(struct e1000_hw *hw);
|
||||
@@ -512,12 +510,8 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw)
|
||||
/* link info */
|
||||
mac->ops.get_link_up_info = e1000_get_link_up_info_82575;
|
||||
/* acquire SW_FW sync */
|
||||
mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_82575;
|
||||
mac->ops.release_swfw_sync = e1000_release_swfw_sync_82575;
|
||||
if (mac->type >= e1000_i210) {
|
||||
mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_i210;
|
||||
mac->ops.release_swfw_sync = e1000_release_swfw_sync_i210;
|
||||
}
|
||||
mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync;
|
||||
mac->ops.release_swfw_sync = e1000_release_swfw_sync;
|
||||
|
||||
/* set lan id for port to determine which phy lock to use */
|
||||
hw->mac.ops.set_lan_id(hw);
|
||||
@@ -989,7 +983,7 @@ static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw)
|
||||
|
||||
DEBUGFUNC("e1000_acquire_nvm_82575");
|
||||
|
||||
ret_val = e1000_acquire_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
|
||||
ret_val = e1000_acquire_swfw_sync(hw, E1000_SWFW_EEP_SM);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
@@ -1020,7 +1014,7 @@ static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw)
|
||||
|
||||
ret_val = e1000_acquire_nvm_generic(hw);
|
||||
if (ret_val)
|
||||
e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
|
||||
e1000_release_swfw_sync(hw, E1000_SWFW_EEP_SM);
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
@@ -1039,83 +1033,7 @@ static void e1000_release_nvm_82575(struct e1000_hw *hw)
|
||||
|
||||
e1000_release_nvm_generic(hw);
|
||||
|
||||
e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_acquire_swfw_sync_82575 - Acquire SW/FW semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
* @mask: specifies which semaphore to acquire
|
||||
*
|
||||
* Acquire the SW/FW semaphore to access the PHY or NVM. The mask
|
||||
* will also specify which port we're acquiring the lock for.
|
||||
**/
|
||||
static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask)
|
||||
{
|
||||
u32 swfw_sync;
|
||||
u32 swmask = mask;
|
||||
u32 fwmask = mask << 16;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
s32 i = 0, timeout = 200;
|
||||
|
||||
DEBUGFUNC("e1000_acquire_swfw_sync_82575");
|
||||
|
||||
while (i < timeout) {
|
||||
if (e1000_get_hw_semaphore_generic(hw)) {
|
||||
ret_val = -E1000_ERR_SWFW_SYNC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
|
||||
if (!(swfw_sync & (fwmask | swmask)))
|
||||
break;
|
||||
|
||||
/*
|
||||
* Firmware currently using resource (fwmask)
|
||||
* or other software thread using resource (swmask)
|
||||
*/
|
||||
e1000_put_hw_semaphore_generic(hw);
|
||||
msec_delay_irq(5);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == timeout) {
|
||||
DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
|
||||
ret_val = -E1000_ERR_SWFW_SYNC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
swfw_sync |= swmask;
|
||||
E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
|
||||
|
||||
e1000_put_hw_semaphore_generic(hw);
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_release_swfw_sync_82575 - Release SW/FW semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
* @mask: specifies which semaphore to acquire
|
||||
*
|
||||
* Release the SW/FW semaphore used to access the PHY or NVM. The mask
|
||||
* will also specify which port we're releasing the lock for.
|
||||
**/
|
||||
static void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask)
|
||||
{
|
||||
u32 swfw_sync;
|
||||
|
||||
DEBUGFUNC("e1000_release_swfw_sync_82575");
|
||||
|
||||
while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS)
|
||||
; /* Empty */
|
||||
|
||||
swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
|
||||
swfw_sync &= ~mask;
|
||||
E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
|
||||
|
||||
e1000_put_hw_semaphore_generic(hw);
|
||||
e1000_release_swfw_sync(hw, E1000_SWFW_EEP_SM);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1679,7 +1597,7 @@ static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw)
|
||||
case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
|
||||
/* disable PCS autoneg and support parallel detect only */
|
||||
pcs_autoneg = FALSE;
|
||||
/* fall through to default case */
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
if (hw->mac.type == e1000_82575 ||
|
||||
hw->mac.type == e1000_82576) {
|
||||
@@ -1806,6 +1724,7 @@ static s32 e1000_get_media_type_82575(struct e1000_hw *hw)
|
||||
break;
|
||||
}
|
||||
/* fall through for I2C based SGMII */
|
||||
/* FALLTHROUGH */
|
||||
case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES:
|
||||
/* read media type from SFP EEPROM */
|
||||
ret_val = e1000_set_sfp_media_type_82575(hw);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_82575.h 327865 2018-01-12 06:37:53Z eadler $*/
|
||||
|
||||
#ifndef _E1000_82575_H_
|
||||
#define _E1000_82575_H_
|
||||
@@ -384,7 +385,7 @@ struct e1000_adv_tx_context_desc {
|
||||
#define E1000_ETQF_FILTER_ENABLE (1 << 26)
|
||||
#define E1000_ETQF_IMM_INT (1 << 29)
|
||||
#define E1000_ETQF_1588 (1 << 30)
|
||||
#define E1000_ETQF_QUEUE_ENABLE (1 << 31)
|
||||
#define E1000_ETQF_QUEUE_ENABLE (1U << 31)
|
||||
/*
|
||||
* ETQF filter list: one static filter per filter consumer. This is
|
||||
* to avoid filter collisions later. Add new filters
|
||||
@@ -411,7 +412,7 @@ struct e1000_adv_tx_context_desc {
|
||||
#define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */
|
||||
#define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8
|
||||
#define E1000_DTXSWC_LLE_SHIFT 16
|
||||
#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31) /* global VF LB enable */
|
||||
#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1U << 31) /* global VF LB enable */
|
||||
|
||||
/* Easy defines for setting default pool, would normally be left a zero */
|
||||
#define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7
|
||||
@@ -493,6 +494,7 @@ enum e1000_promisc_type {
|
||||
void e1000_vfta_set_vf(struct e1000_hw *, u16, bool);
|
||||
void e1000_rlpml_set_vf(struct e1000_hw *, u16);
|
||||
s32 e1000_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type type);
|
||||
void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value);
|
||||
u16 e1000_rxpbs_adjust_82580(u32 data);
|
||||
s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data);
|
||||
s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_api.c 327312 2017-12-28 21:26:40Z sbruno $*/
|
||||
|
||||
#include "e1000_api.h"
|
||||
|
||||
@@ -310,6 +311,16 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
|
||||
case E1000_DEV_ID_PCH_SPT_I219_V5:
|
||||
mac->type = e1000_pch_spt;
|
||||
break;
|
||||
case E1000_DEV_ID_PCH_CNP_I219_LM6:
|
||||
case E1000_DEV_ID_PCH_CNP_I219_V6:
|
||||
case E1000_DEV_ID_PCH_CNP_I219_LM7:
|
||||
case E1000_DEV_ID_PCH_CNP_I219_V7:
|
||||
case E1000_DEV_ID_PCH_ICP_I219_LM8:
|
||||
case E1000_DEV_ID_PCH_ICP_I219_V8:
|
||||
case E1000_DEV_ID_PCH_ICP_I219_LM9:
|
||||
case E1000_DEV_ID_PCH_ICP_I219_V9:
|
||||
mac->type = e1000_pch_cnp;
|
||||
break;
|
||||
case E1000_DEV_ID_82575EB_COPPER:
|
||||
case E1000_DEV_ID_82575EB_FIBER_SERDES:
|
||||
case E1000_DEV_ID_82575GB_QUAD_COPPER:
|
||||
@@ -461,6 +472,7 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
|
||||
case e1000_pch2lan:
|
||||
case e1000_pch_lpt:
|
||||
case e1000_pch_spt:
|
||||
case e1000_pch_cnp:
|
||||
e1000_init_function_pointers_ich8lan(hw);
|
||||
break;
|
||||
case e1000_82575:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_api.h 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
#ifndef _E1000_API_H_
|
||||
#define _E1000_API_H_
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_defines.h 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
#ifndef _E1000_DEFINES_H_
|
||||
#define _E1000_DEFINES_H_
|
||||
@@ -469,6 +470,8 @@
|
||||
|
||||
#define ETHERNET_FCS_SIZE 4
|
||||
#define MAX_JUMBO_FRAME_SIZE 0x3F00
|
||||
/* The datasheet maximum supported RX size is 9.5KB (9728 bytes) */
|
||||
#define MAX_RX_JUMBO_FRAME_SIZE 0x2600
|
||||
#define E1000_TX_PTR_GAP 0x1F
|
||||
|
||||
/* Extended Configuration Control and Size */
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_hw.h 333345 2018-05-08 01:39:45Z mmacy $*/
|
||||
|
||||
#ifndef _E1000_HW_H_
|
||||
#define _E1000_HW_H_
|
||||
@@ -146,6 +147,14 @@ struct e1000_hw;
|
||||
#define E1000_DEV_ID_PCH_SPT_I219_V4 0x15D8
|
||||
#define E1000_DEV_ID_PCH_SPT_I219_LM5 0x15E3
|
||||
#define E1000_DEV_ID_PCH_SPT_I219_V5 0x15D6
|
||||
#define E1000_DEV_ID_PCH_CNP_I219_LM6 0x15BD
|
||||
#define E1000_DEV_ID_PCH_CNP_I219_V6 0x15BE
|
||||
#define E1000_DEV_ID_PCH_CNP_I219_LM7 0x15BB
|
||||
#define E1000_DEV_ID_PCH_CNP_I219_V7 0x15BC
|
||||
#define E1000_DEV_ID_PCH_ICP_I219_LM8 0x15DF
|
||||
#define E1000_DEV_ID_PCH_ICP_I219_V8 0x15E0
|
||||
#define E1000_DEV_ID_PCH_ICP_I219_LM9 0x15E1
|
||||
#define E1000_DEV_ID_PCH_ICP_I219_V9 0x15E2
|
||||
#define E1000_DEV_ID_82576 0x10C9
|
||||
#define E1000_DEV_ID_82576_FIBER 0x10E6
|
||||
#define E1000_DEV_ID_82576_SERDES 0x10E7
|
||||
@@ -232,6 +241,7 @@ enum e1000_mac_type {
|
||||
e1000_pch2lan,
|
||||
e1000_pch_lpt,
|
||||
e1000_pch_spt,
|
||||
e1000_pch_cnp,
|
||||
e1000_82575,
|
||||
e1000_82576,
|
||||
e1000_82580,
|
||||
@@ -934,7 +944,6 @@ struct e1000_dev_spec_82543 {
|
||||
struct e1000_dev_spec_82571 {
|
||||
bool laa_is_present;
|
||||
u32 smb_counter;
|
||||
E1000_MUTEX swflag_mutex;
|
||||
};
|
||||
|
||||
struct e1000_dev_spec_80003es2lan {
|
||||
@@ -958,8 +967,6 @@ enum e1000_ulp_state {
|
||||
struct e1000_dev_spec_ich8lan {
|
||||
bool kmrn_lock_loss_workaround_enabled;
|
||||
struct e1000_shadow_ram shadow_ram[E1000_SHADOW_RAM_WORDS];
|
||||
E1000_MUTEX nvm_mutex;
|
||||
E1000_MUTEX swflag_mutex;
|
||||
bool nvm_k1_enabled;
|
||||
bool disable_k1_off;
|
||||
bool eee_disable;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,14 +31,13 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_i210.c 333345 2018-05-08 01:39:45Z mmacy $*/
|
||||
|
||||
#include "e1000_api.h"
|
||||
|
||||
|
||||
static s32 e1000_acquire_nvm_i210(struct e1000_hw *hw);
|
||||
static void e1000_release_nvm_i210(struct e1000_hw *hw);
|
||||
static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw);
|
||||
static s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
|
||||
u16 *data);
|
||||
static s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw);
|
||||
@@ -58,7 +58,7 @@ static s32 e1000_acquire_nvm_i210(struct e1000_hw *hw)
|
||||
|
||||
DEBUGFUNC("e1000_acquire_nvm_i210");
|
||||
|
||||
ret_val = e1000_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
|
||||
ret_val = e1000_acquire_swfw_sync(hw, E1000_SWFW_EEP_SM);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
@@ -74,152 +74,7 @@ static void e1000_release_nvm_i210(struct e1000_hw *hw)
|
||||
{
|
||||
DEBUGFUNC("e1000_release_nvm_i210");
|
||||
|
||||
e1000_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
* @mask: specifies which semaphore to acquire
|
||||
*
|
||||
* Acquire the SW/FW semaphore to access the PHY or NVM. The mask
|
||||
* will also specify which port we're acquiring the lock for.
|
||||
**/
|
||||
s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
|
||||
{
|
||||
u32 swfw_sync;
|
||||
u32 swmask = mask;
|
||||
u32 fwmask = mask << 16;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
|
||||
|
||||
DEBUGFUNC("e1000_acquire_swfw_sync_i210");
|
||||
|
||||
while (i < timeout) {
|
||||
if (e1000_get_hw_semaphore_i210(hw)) {
|
||||
ret_val = -E1000_ERR_SWFW_SYNC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
|
||||
if (!(swfw_sync & (fwmask | swmask)))
|
||||
break;
|
||||
|
||||
/*
|
||||
* Firmware currently using resource (fwmask)
|
||||
* or other software thread using resource (swmask)
|
||||
*/
|
||||
e1000_put_hw_semaphore_generic(hw);
|
||||
msec_delay_irq(5);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == timeout) {
|
||||
DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
|
||||
ret_val = -E1000_ERR_SWFW_SYNC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
swfw_sync |= swmask;
|
||||
E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
|
||||
|
||||
e1000_put_hw_semaphore_generic(hw);
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_release_swfw_sync_i210 - Release SW/FW semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
* @mask: specifies which semaphore to acquire
|
||||
*
|
||||
* Release the SW/FW semaphore used to access the PHY or NVM. The mask
|
||||
* will also specify which port we're releasing the lock for.
|
||||
**/
|
||||
void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
|
||||
{
|
||||
u32 swfw_sync;
|
||||
|
||||
DEBUGFUNC("e1000_release_swfw_sync_i210");
|
||||
|
||||
while (e1000_get_hw_semaphore_i210(hw) != E1000_SUCCESS)
|
||||
; /* Empty */
|
||||
|
||||
swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
|
||||
swfw_sync &= ~mask;
|
||||
E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
|
||||
|
||||
e1000_put_hw_semaphore_generic(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_get_hw_semaphore_i210 - Acquire hardware semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Acquire the HW semaphore to access the PHY or NVM
|
||||
**/
|
||||
static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw)
|
||||
{
|
||||
u32 swsm;
|
||||
s32 timeout = hw->nvm.word_size + 1;
|
||||
s32 i = 0;
|
||||
|
||||
DEBUGFUNC("e1000_get_hw_semaphore_i210");
|
||||
|
||||
/* Get the SW semaphore */
|
||||
while (i < timeout) {
|
||||
swsm = E1000_READ_REG(hw, E1000_SWSM);
|
||||
if (!(swsm & E1000_SWSM_SMBI))
|
||||
break;
|
||||
|
||||
usec_delay(50);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == timeout) {
|
||||
/* In rare circumstances, the SW semaphore may already be held
|
||||
* unintentionally. Clear the semaphore once before giving up.
|
||||
*/
|
||||
if (hw->dev_spec._82575.clear_semaphore_once) {
|
||||
hw->dev_spec._82575.clear_semaphore_once = FALSE;
|
||||
e1000_put_hw_semaphore_generic(hw);
|
||||
for (i = 0; i < timeout; i++) {
|
||||
swsm = E1000_READ_REG(hw, E1000_SWSM);
|
||||
if (!(swsm & E1000_SWSM_SMBI))
|
||||
break;
|
||||
|
||||
usec_delay(50);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we do not have the semaphore here, we have to give up. */
|
||||
if (i == timeout) {
|
||||
DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
|
||||
return -E1000_ERR_NVM;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the FW semaphore. */
|
||||
for (i = 0; i < timeout; i++) {
|
||||
swsm = E1000_READ_REG(hw, E1000_SWSM);
|
||||
E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
|
||||
|
||||
/* Semaphore acquired if bit latched */
|
||||
if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI)
|
||||
break;
|
||||
|
||||
usec_delay(50);
|
||||
}
|
||||
|
||||
if (i == timeout) {
|
||||
/* Release semaphores */
|
||||
e1000_put_hw_semaphore_generic(hw);
|
||||
DEBUGOUT("Driver can't access the NVM\n");
|
||||
return -E1000_ERR_NVM;
|
||||
}
|
||||
|
||||
return E1000_SUCCESS;
|
||||
e1000_release_swfw_sync(hw, E1000_SWFW_EEP_SM);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_i210.h 333345 2018-05-08 01:39:45Z mmacy $*/
|
||||
|
||||
#ifndef _E1000_I210_H_
|
||||
#define _E1000_I210_H_
|
||||
@@ -43,8 +44,6 @@ s32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset,
|
||||
u16 words, u16 *data);
|
||||
s32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset,
|
||||
u16 words, u16 *data);
|
||||
s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
|
||||
void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
|
||||
s32 e1000_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr,
|
||||
u16 *data);
|
||||
s32 e1000_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_ich8lan.c 333345 2018-05-08 01:39:45Z mmacy $*/
|
||||
|
||||
/* 82562G 10/100 Network Connection
|
||||
* 82562G-2 10/100 Network Connection
|
||||
@@ -243,8 +244,7 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
|
||||
if (ret_val)
|
||||
return FALSE;
|
||||
out:
|
||||
if ((hw->mac.type == e1000_pch_lpt) ||
|
||||
(hw->mac.type == e1000_pch_spt)) {
|
||||
if (hw->mac.type >= e1000_pch_lpt) {
|
||||
/* Only unforce SMBus if ME is not active */
|
||||
if (!(E1000_READ_REG(hw, E1000_FWSM) &
|
||||
E1000_ICH_FWSM_FW_VALID)) {
|
||||
@@ -345,6 +345,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
|
||||
switch (hw->mac.type) {
|
||||
case e1000_pch_lpt:
|
||||
case e1000_pch_spt:
|
||||
case e1000_pch_cnp:
|
||||
if (e1000_phy_is_accessible_pchlan(hw))
|
||||
break;
|
||||
|
||||
@@ -493,6 +494,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
|
||||
case e1000_pch2lan:
|
||||
case e1000_pch_lpt:
|
||||
case e1000_pch_spt:
|
||||
case e1000_pch_cnp:
|
||||
/* In case the PHY needs to be in mdio slow mode,
|
||||
* set slow mode and try to get the PHY id again.
|
||||
*/
|
||||
@@ -641,7 +643,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
|
||||
|
||||
nvm->type = e1000_nvm_flash_sw;
|
||||
|
||||
if (hw->mac.type == e1000_pch_spt) {
|
||||
if (hw->mac.type >= e1000_pch_spt) {
|
||||
/* in SPT, gfpreg doesn't exist. NVM size is taken from the
|
||||
* STRAP register. This is because in SPT the GbE Flash region
|
||||
* is no longer accessed through the flash registers. Instead,
|
||||
@@ -695,13 +697,10 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
|
||||
dev_spec->shadow_ram[i].value = 0xFFFF;
|
||||
}
|
||||
|
||||
E1000_MUTEX_INIT(&dev_spec->nvm_mutex);
|
||||
E1000_MUTEX_INIT(&dev_spec->swflag_mutex);
|
||||
|
||||
/* Function Pointers */
|
||||
nvm->ops.acquire = e1000_acquire_nvm_ich8lan;
|
||||
nvm->ops.release = e1000_release_nvm_ich8lan;
|
||||
if (hw->mac.type == e1000_pch_spt) {
|
||||
if (hw->mac.type >= e1000_pch_spt) {
|
||||
nvm->ops.read = e1000_read_nvm_spt;
|
||||
nvm->ops.update = e1000_update_nvm_checksum_spt;
|
||||
} else {
|
||||
@@ -794,6 +793,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
|
||||
/* fall-through */
|
||||
case e1000_pch_lpt:
|
||||
case e1000_pch_spt:
|
||||
case e1000_pch_cnp:
|
||||
/* multicast address update for pch2 */
|
||||
mac->ops.update_mc_addr_list =
|
||||
e1000_update_mc_addr_list_pch2lan;
|
||||
@@ -815,8 +815,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((mac->type == e1000_pch_lpt) ||
|
||||
(mac->type == e1000_pch_spt)) {
|
||||
if (mac->type >= e1000_pch_lpt) {
|
||||
mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES;
|
||||
mac->ops.rar_set = e1000_rar_set_pch_lpt;
|
||||
mac->ops.setup_physical_interface = e1000_setup_copper_link_pch_lpt;
|
||||
@@ -1498,24 +1497,24 @@ s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force)
|
||||
ret_val = e1000_read_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, &phy_reg);
|
||||
if (ret_val)
|
||||
goto release;
|
||||
phy_reg &= ~(I218_ULP_CONFIG1_IND |
|
||||
I218_ULP_CONFIG1_STICKY_ULP |
|
||||
I218_ULP_CONFIG1_RESET_TO_SMBUS |
|
||||
I218_ULP_CONFIG1_WOL_HOST |
|
||||
I218_ULP_CONFIG1_INBAND_EXIT |
|
||||
I218_ULP_CONFIG1_EN_ULP_LANPHYPC |
|
||||
I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST |
|
||||
I218_ULP_CONFIG1_DISABLE_SMB_PERST);
|
||||
e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
|
||||
phy_reg &= ~(I218_ULP_CONFIG1_IND |
|
||||
I218_ULP_CONFIG1_STICKY_ULP |
|
||||
I218_ULP_CONFIG1_RESET_TO_SMBUS |
|
||||
I218_ULP_CONFIG1_WOL_HOST |
|
||||
I218_ULP_CONFIG1_INBAND_EXIT |
|
||||
I218_ULP_CONFIG1_EN_ULP_LANPHYPC |
|
||||
I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST |
|
||||
I218_ULP_CONFIG1_DISABLE_SMB_PERST);
|
||||
e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
|
||||
|
||||
/* Commit ULP changes by starting auto ULP configuration */
|
||||
phy_reg |= I218_ULP_CONFIG1_START;
|
||||
e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
|
||||
/* Commit ULP changes by starting auto ULP configuration */
|
||||
phy_reg |= I218_ULP_CONFIG1_START;
|
||||
e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
|
||||
|
||||
/* Clear Disable SMBus Release on PERST# in MAC */
|
||||
mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM7);
|
||||
mac_reg &= ~E1000_FEXTNVM7_DISABLE_SMB_PERST;
|
||||
E1000_WRITE_REG(hw, E1000_FEXTNVM7, mac_reg);
|
||||
/* Clear Disable SMBus Release on PERST# in MAC */
|
||||
mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM7);
|
||||
mac_reg &= ~E1000_FEXTNVM7_DISABLE_SMB_PERST;
|
||||
E1000_WRITE_REG(hw, E1000_FEXTNVM7, mac_reg);
|
||||
|
||||
release:
|
||||
hw->phy.ops.release(hw);
|
||||
@@ -1558,13 +1557,13 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
|
||||
if (!mac->get_link_status)
|
||||
return E1000_SUCCESS;
|
||||
|
||||
/* First we want to see if the MII Status Register reports
|
||||
* link. If so, then we want to get the current speed/duplex
|
||||
* of the PHY.
|
||||
*/
|
||||
ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
/* First we want to see if the MII Status Register reports
|
||||
* link. If so, then we want to get the current speed/duplex
|
||||
* of the PHY.
|
||||
*/
|
||||
ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
if (hw->mac.type == e1000_pchlan) {
|
||||
ret_val = e1000_k1_gig_workaround_hv(hw, link);
|
||||
@@ -1576,9 +1575,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
|
||||
* aggressive resulting in many collisions. To avoid this, increase
|
||||
* the IPG and reduce Rx latency in the PHY.
|
||||
*/
|
||||
if (((hw->mac.type == e1000_pch2lan) ||
|
||||
(hw->mac.type == e1000_pch_lpt) ||
|
||||
(hw->mac.type == e1000_pch_spt)) && link) {
|
||||
if ((hw->mac.type >= e1000_pch2lan) && link) {
|
||||
u16 speed, duplex;
|
||||
|
||||
e1000_get_speed_and_duplex_copper_generic(hw, &speed, &duplex);
|
||||
@@ -1589,7 +1586,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
|
||||
tipg_reg |= 0xFF;
|
||||
/* Reduce Rx latency in analog PHY */
|
||||
emi_val = 0;
|
||||
} else if (hw->mac.type == e1000_pch_spt &&
|
||||
} else if (hw->mac.type >= e1000_pch_spt &&
|
||||
duplex == FULL_DUPLEX && speed != SPEED_1000) {
|
||||
tipg_reg |= 0xC;
|
||||
emi_val = 1;
|
||||
@@ -1611,8 +1608,8 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
|
||||
emi_addr = I217_RX_CONFIG;
|
||||
ret_val = e1000_write_emi_reg_locked(hw, emi_addr, emi_val);
|
||||
|
||||
if (hw->mac.type == e1000_pch_lpt ||
|
||||
hw->mac.type == e1000_pch_spt) {
|
||||
|
||||
if (hw->mac.type >= e1000_pch_lpt) {
|
||||
u16 phy_reg;
|
||||
|
||||
hw->phy.ops.read_reg_locked(hw, I217_PLL_CLOCK_GATE_REG,
|
||||
@@ -1641,7 +1638,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
if (hw->mac.type == e1000_pch_spt) {
|
||||
if (hw->mac.type >= e1000_pch_spt) {
|
||||
u16 data;
|
||||
u16 ptr_gap;
|
||||
|
||||
@@ -1690,8 +1687,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
|
||||
* on power up.
|
||||
* Set the Beacon Duration for I217 to 8 usec
|
||||
*/
|
||||
if ((hw->mac.type == e1000_pch_lpt) ||
|
||||
(hw->mac.type == e1000_pch_spt)) {
|
||||
if (hw->mac.type >= e1000_pch_lpt) {
|
||||
u32 mac_reg;
|
||||
|
||||
mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM4);
|
||||
@@ -1709,8 +1705,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
}
|
||||
if ((hw->mac.type == e1000_pch_lpt) ||
|
||||
(hw->mac.type == e1000_pch_spt)) {
|
||||
if (hw->mac.type >= e1000_pch_lpt) {
|
||||
/* Set platform power management values for
|
||||
* Latency Tolerance Reporting (LTR)
|
||||
* Optimized Buffer Flush/Fill (OBFF)
|
||||
@@ -1723,15 +1718,20 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
|
||||
/* Clear link partner's EEE ability */
|
||||
hw->dev_spec.ich8lan.eee_lp_ability = 0;
|
||||
|
||||
/* FEXTNVM6 K1-off workaround */
|
||||
if (hw->mac.type == e1000_pch_spt) {
|
||||
u32 pcieanacfg = E1000_READ_REG(hw, E1000_PCIEANACFG);
|
||||
if (hw->mac.type >= e1000_pch_lpt) {
|
||||
u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
|
||||
|
||||
if ((pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE) &&
|
||||
(hw->dev_spec.ich8lan.disable_k1_off == FALSE))
|
||||
fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE;
|
||||
else
|
||||
if (hw->mac.type == e1000_pch_spt) {
|
||||
/* FEXTNVM6 K1-off workaround - for SPT only */
|
||||
u32 pcieanacfg = E1000_READ_REG(hw, E1000_PCIEANACFG);
|
||||
|
||||
if (pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE)
|
||||
fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE;
|
||||
else
|
||||
fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE;
|
||||
}
|
||||
|
||||
if (hw->dev_spec.ich8lan.disable_k1_off == TRUE)
|
||||
fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE;
|
||||
|
||||
E1000_WRITE_REG(hw, E1000_FEXTNVM6, fextnvm6);
|
||||
@@ -1831,6 +1831,7 @@ void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw)
|
||||
case e1000_pch2lan:
|
||||
case e1000_pch_lpt:
|
||||
case e1000_pch_spt:
|
||||
case e1000_pch_cnp:
|
||||
hw->phy.ops.init_params = e1000_init_phy_params_pchlan;
|
||||
break;
|
||||
default:
|
||||
@@ -1848,7 +1849,7 @@ static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw)
|
||||
{
|
||||
DEBUGFUNC("e1000_acquire_nvm_ich8lan");
|
||||
|
||||
E1000_MUTEX_LOCK(&hw->dev_spec.ich8lan.nvm_mutex);
|
||||
ASSERT_CTX_LOCK_HELD(hw);
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
@@ -1863,9 +1864,7 @@ static void e1000_release_nvm_ich8lan(struct e1000_hw *hw)
|
||||
{
|
||||
DEBUGFUNC("e1000_release_nvm_ich8lan");
|
||||
|
||||
E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.nvm_mutex);
|
||||
|
||||
return;
|
||||
ASSERT_CTX_LOCK_HELD(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1882,7 +1881,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
|
||||
|
||||
DEBUGFUNC("e1000_acquire_swflag_ich8lan");
|
||||
|
||||
E1000_MUTEX_LOCK(&hw->dev_spec.ich8lan.swflag_mutex);
|
||||
ASSERT_CTX_LOCK_HELD(hw);
|
||||
|
||||
while (timeout) {
|
||||
extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
|
||||
@@ -1923,9 +1922,6 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret_val)
|
||||
E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.swflag_mutex);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
@@ -1950,10 +1946,6 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
|
||||
} else {
|
||||
DEBUGOUT("Semaphore unexpectedly released by sw/fw/hw\n");
|
||||
}
|
||||
|
||||
E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.swflag_mutex);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2295,6 +2287,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
|
||||
case e1000_pch2lan:
|
||||
case e1000_pch_lpt:
|
||||
case e1000_pch_spt:
|
||||
case e1000_pch_cnp:
|
||||
sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
|
||||
break;
|
||||
default:
|
||||
@@ -2655,6 +2648,8 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
|
||||
e1000_phy_sw_reset_generic(hw);
|
||||
ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL,
|
||||
0x3140);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3412,6 +3407,7 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
|
||||
|
||||
switch (hw->mac.type) {
|
||||
case e1000_pch_spt:
|
||||
case e1000_pch_cnp:
|
||||
bank1_offset = nvm->flash_bank_size;
|
||||
act_offset = E1000_ICH_NVM_SIG_WORD;
|
||||
|
||||
@@ -3671,7 +3667,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
|
||||
/* Clear FCERR and DAEL in hw status by writing 1 */
|
||||
hsfsts.hsf_status.flcerr = 1;
|
||||
hsfsts.hsf_status.dael = 1;
|
||||
if (hw->mac.type == e1000_pch_spt)
|
||||
if (hw->mac.type >= e1000_pch_spt)
|
||||
E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
|
||||
hsfsts.regval & 0xFFFF);
|
||||
else
|
||||
@@ -3691,7 +3687,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
|
||||
* Begin by setting Flash Cycle Done.
|
||||
*/
|
||||
hsfsts.hsf_status.flcdone = 1;
|
||||
if (hw->mac.type == e1000_pch_spt)
|
||||
if (hw->mac.type >= e1000_pch_spt)
|
||||
E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
|
||||
hsfsts.regval & 0xFFFF);
|
||||
else
|
||||
@@ -3718,7 +3714,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
|
||||
* now set the Flash Cycle Done.
|
||||
*/
|
||||
hsfsts.hsf_status.flcdone = 1;
|
||||
if (hw->mac.type == e1000_pch_spt)
|
||||
if (hw->mac.type >= e1000_pch_spt)
|
||||
E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
|
||||
hsfsts.regval & 0xFFFF);
|
||||
else
|
||||
@@ -3748,13 +3744,13 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
|
||||
DEBUGFUNC("e1000_flash_cycle_ich8lan");
|
||||
|
||||
/* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
|
||||
if (hw->mac.type == e1000_pch_spt)
|
||||
if (hw->mac.type >= e1000_pch_spt)
|
||||
hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
|
||||
else
|
||||
hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
|
||||
hsflctl.hsf_ctrl.flcgo = 1;
|
||||
|
||||
if (hw->mac.type == e1000_pch_spt)
|
||||
if (hw->mac.type >= e1000_pch_spt)
|
||||
E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
|
||||
hsflctl.regval << 16);
|
||||
else
|
||||
@@ -3837,7 +3833,7 @@ static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
|
||||
/* In SPT, only 32 bits access is supported,
|
||||
* so this function should not be called.
|
||||
*/
|
||||
if (hw->mac.type == e1000_pch_spt)
|
||||
if (hw->mac.type >= e1000_pch_spt)
|
||||
return -E1000_ERR_NVM;
|
||||
else
|
||||
ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
|
||||
@@ -3946,7 +3942,7 @@ static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
|
||||
DEBUGFUNC("e1000_read_flash_data_ich8lan");
|
||||
|
||||
if (offset > ICH_FLASH_LINEAR_ADDR_MASK ||
|
||||
hw->mac.type != e1000_pch_spt)
|
||||
hw->mac.type < e1000_pch_spt)
|
||||
return -E1000_ERR_NVM;
|
||||
flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
|
||||
hw->nvm.flash_base_addr);
|
||||
@@ -4387,6 +4383,7 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
|
||||
switch (hw->mac.type) {
|
||||
case e1000_pch_lpt:
|
||||
case e1000_pch_spt:
|
||||
case e1000_pch_cnp:
|
||||
word = NVM_COMPAT;
|
||||
valid_csum_mask = NVM_COMPAT_VALID_CSUM;
|
||||
break;
|
||||
@@ -4434,7 +4431,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
|
||||
|
||||
DEBUGFUNC("e1000_write_ich8_data");
|
||||
|
||||
if (hw->mac.type == e1000_pch_spt) {
|
||||
if (hw->mac.type >= e1000_pch_spt) {
|
||||
if (size != 4 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
|
||||
return -E1000_ERR_NVM;
|
||||
} else {
|
||||
@@ -4454,7 +4451,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
|
||||
/* In SPT, This register is in Lan memory space, not
|
||||
* flash. Therefore, only 32 bit access is supported
|
||||
*/
|
||||
if (hw->mac.type == e1000_pch_spt)
|
||||
if (hw->mac.type >= e1000_pch_spt)
|
||||
hsflctl.regval =
|
||||
E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
|
||||
else
|
||||
@@ -4468,7 +4465,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
|
||||
* not flash. Therefore, only 32 bit access is
|
||||
* supported
|
||||
*/
|
||||
if (hw->mac.type == e1000_pch_spt)
|
||||
if (hw->mac.type >= e1000_pch_spt)
|
||||
E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
|
||||
hsflctl.regval << 16);
|
||||
else
|
||||
@@ -4530,7 +4527,7 @@ static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
|
||||
|
||||
DEBUGFUNC("e1000_write_flash_data32_ich8lan");
|
||||
|
||||
if (hw->mac.type == e1000_pch_spt) {
|
||||
if (hw->mac.type >= e1000_pch_spt) {
|
||||
if (offset > ICH_FLASH_LINEAR_ADDR_MASK)
|
||||
return -E1000_ERR_NVM;
|
||||
}
|
||||
@@ -4546,7 +4543,7 @@ static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
|
||||
/* In SPT, This register is in Lan memory space, not
|
||||
* flash. Therefore, only 32 bit access is supported
|
||||
*/
|
||||
if (hw->mac.type == e1000_pch_spt)
|
||||
if (hw->mac.type >= e1000_pch_spt)
|
||||
hsflctl.regval = E1000_READ_FLASH_REG(hw,
|
||||
ICH_FLASH_HSFSTS)
|
||||
>> 16;
|
||||
@@ -4561,7 +4558,7 @@ static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
|
||||
* not flash. Therefore, only 32 bit access is
|
||||
* supported
|
||||
*/
|
||||
if (hw->mac.type == e1000_pch_spt)
|
||||
if (hw->mac.type >= e1000_pch_spt)
|
||||
E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
|
||||
hsflctl.regval << 16);
|
||||
else
|
||||
@@ -4763,7 +4760,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
|
||||
/* Write a value 11 (block Erase) in Flash
|
||||
* Cycle field in hw flash control
|
||||
*/
|
||||
if (hw->mac.type == e1000_pch_spt)
|
||||
if (hw->mac.type >= e1000_pch_spt)
|
||||
hsflctl.regval =
|
||||
E1000_READ_FLASH_REG(hw,
|
||||
ICH_FLASH_HSFSTS)>>16;
|
||||
@@ -4773,7 +4770,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
|
||||
ICH_FLASH_HSFCTL);
|
||||
|
||||
hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
|
||||
if (hw->mac.type == e1000_pch_spt)
|
||||
if (hw->mac.type >= e1000_pch_spt)
|
||||
E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
|
||||
hsflctl.regval << 16);
|
||||
else
|
||||
@@ -5023,8 +5020,6 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
|
||||
E1000_WRITE_REG(hw, E1000_FEXTNVM3, reg);
|
||||
}
|
||||
|
||||
if (!ret_val)
|
||||
E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.swflag_mutex);
|
||||
|
||||
if (ctrl & E1000_CTRL_PHY_RST) {
|
||||
ret_val = hw->phy.ops.get_cfg_done(hw);
|
||||
@@ -5193,7 +5188,7 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
|
||||
/* Device Status */
|
||||
if (hw->mac.type == e1000_ich8lan) {
|
||||
reg = E1000_READ_REG(hw, E1000_STATUS);
|
||||
reg &= ~(1 << 31);
|
||||
reg &= ~(1U << 31);
|
||||
E1000_WRITE_REG(hw, E1000_STATUS, reg);
|
||||
}
|
||||
|
||||
@@ -5211,8 +5206,7 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
|
||||
E1000_WRITE_REG(hw, E1000_RFCTL, reg);
|
||||
|
||||
/* Enable ECC on Lynxpoint */
|
||||
if ((hw->mac.type == e1000_pch_lpt) ||
|
||||
(hw->mac.type == e1000_pch_spt)) {
|
||||
if (hw->mac.type >= e1000_pch_lpt) {
|
||||
reg = E1000_READ_REG(hw, E1000_PBECCSTS);
|
||||
reg |= E1000_PBECCSTS_ECC_ENABLE;
|
||||
E1000_WRITE_REG(hw, E1000_PBECCSTS, reg);
|
||||
@@ -5645,7 +5639,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
|
||||
(device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
|
||||
(device_id == E1000_DEV_ID_PCH_I218_LM3) ||
|
||||
(device_id == E1000_DEV_ID_PCH_I218_V3) ||
|
||||
(hw->mac.type == e1000_pch_spt)) {
|
||||
(hw->mac.type >= e1000_pch_spt)) {
|
||||
u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
|
||||
|
||||
E1000_WRITE_REG(hw, E1000_FEXTNVM6,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_ich8lan.h 327312 2017-12-28 21:26:40Z sbruno $*/
|
||||
|
||||
#ifndef _E1000_ICH8LAN_H_
|
||||
#define _E1000_ICH8LAN_H_
|
||||
@@ -123,7 +124,8 @@
|
||||
#define NVM_SIZE_MULTIPLIER 4096 /*multiplier for NVMS field*/
|
||||
#define E1000_FLASH_BASE_ADDR 0xE000 /*offset of NVM access regs*/
|
||||
#define E1000_CTRL_EXT_NVMVS 0x3 /*NVM valid sector */
|
||||
#define E1000_TARC0_CB_MULTIQ_3_REQ (1 << 28 | 1 << 29)
|
||||
#define E1000_TARC0_CB_MULTIQ_3_REQ 0x30000000
|
||||
#define E1000_TARC0_CB_MULTIQ_2_REQ 0x20000000
|
||||
#define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL
|
||||
|
||||
#define E1000_ICH_RAR_ENTRIES 7
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_mac.c 333631 2018-05-15 13:30:59Z sbruno $*/
|
||||
|
||||
#include "e1000_api.h"
|
||||
|
||||
@@ -1706,76 +1707,6 @@ s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw E1000_UNUSED
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_get_hw_semaphore_generic - Acquire hardware semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Acquire the HW semaphore to access the PHY or NVM
|
||||
**/
|
||||
s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw)
|
||||
{
|
||||
u32 swsm;
|
||||
s32 timeout = hw->nvm.word_size + 1;
|
||||
s32 i = 0;
|
||||
|
||||
DEBUGFUNC("e1000_get_hw_semaphore_generic");
|
||||
|
||||
/* Get the SW semaphore */
|
||||
while (i < timeout) {
|
||||
swsm = E1000_READ_REG(hw, E1000_SWSM);
|
||||
if (!(swsm & E1000_SWSM_SMBI))
|
||||
break;
|
||||
|
||||
usec_delay(50);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == timeout) {
|
||||
DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
|
||||
return -E1000_ERR_NVM;
|
||||
}
|
||||
|
||||
/* Get the FW semaphore. */
|
||||
for (i = 0; i < timeout; i++) {
|
||||
swsm = E1000_READ_REG(hw, E1000_SWSM);
|
||||
E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
|
||||
|
||||
/* Semaphore acquired if bit latched */
|
||||
if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI)
|
||||
break;
|
||||
|
||||
usec_delay(50);
|
||||
}
|
||||
|
||||
if (i == timeout) {
|
||||
/* Release semaphores */
|
||||
e1000_put_hw_semaphore_generic(hw);
|
||||
DEBUGOUT("Driver can't access the NVM\n");
|
||||
return -E1000_ERR_NVM;
|
||||
}
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_put_hw_semaphore_generic - Release hardware semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Release hardware semaphore used to access the PHY or NVM
|
||||
**/
|
||||
void e1000_put_hw_semaphore_generic(struct e1000_hw *hw)
|
||||
{
|
||||
u32 swsm;
|
||||
|
||||
DEBUGFUNC("e1000_put_hw_semaphore_generic");
|
||||
|
||||
swsm = E1000_READ_REG(hw, E1000_SWSM);
|
||||
|
||||
swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
|
||||
|
||||
E1000_WRITE_REG(hw, E1000_SWSM, swsm);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_get_auto_rd_done_generic - Check for auto read completion
|
||||
* @hw: pointer to the HW structure
|
||||
@@ -2251,3 +2182,181 @@ s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg,
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_get_hw_semaphore - Acquire hardware semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Acquire the HW semaphore to access the PHY or NVM
|
||||
**/
|
||||
s32 e1000_get_hw_semaphore(struct e1000_hw *hw)
|
||||
{
|
||||
u32 swsm;
|
||||
s32 fw_timeout = hw->nvm.word_size + 1;
|
||||
s32 sw_timeout = hw->nvm.word_size + 1;
|
||||
s32 i = 0;
|
||||
|
||||
DEBUGFUNC("e1000_get_hw_semaphore");
|
||||
|
||||
/* _82571 */
|
||||
/* If we have timedout 3 times on trying to acquire
|
||||
* the inter-port SMBI semaphore, there is old code
|
||||
* operating on the other port, and it is not
|
||||
* releasing SMBI. Modify the number of times that
|
||||
* we try for the semaphore to interwork with this
|
||||
* older code.
|
||||
*/
|
||||
if (hw->dev_spec._82571.smb_counter > 2)
|
||||
sw_timeout = 1;
|
||||
|
||||
|
||||
/* Get the SW semaphore */
|
||||
while (i < sw_timeout) {
|
||||
swsm = E1000_READ_REG(hw, E1000_SWSM);
|
||||
if (!(swsm & E1000_SWSM_SMBI))
|
||||
break;
|
||||
|
||||
usec_delay(50);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == sw_timeout) {
|
||||
DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
|
||||
hw->dev_spec._82571.smb_counter++;
|
||||
}
|
||||
|
||||
/* In rare circumstances, the SW semaphore may already be held
|
||||
* unintentionally. Clear the semaphore once before giving up.
|
||||
*/
|
||||
if (hw->dev_spec._82575.clear_semaphore_once) {
|
||||
hw->dev_spec._82575.clear_semaphore_once = FALSE;
|
||||
e1000_put_hw_semaphore(hw);
|
||||
for (i = 0; i < fw_timeout; i++) {
|
||||
swsm = E1000_READ_REG(hw, E1000_SWSM);
|
||||
if (!(swsm & E1000_SWSM_SMBI))
|
||||
break;
|
||||
|
||||
usec_delay(50);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the FW semaphore. */
|
||||
for (i = 0; i < fw_timeout; i++) {
|
||||
swsm = E1000_READ_REG(hw, E1000_SWSM);
|
||||
E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
|
||||
|
||||
/* Semaphore acquired if bit latched */
|
||||
if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI)
|
||||
break;
|
||||
|
||||
usec_delay(50);
|
||||
}
|
||||
|
||||
if (i == fw_timeout) {
|
||||
/* Release semaphores */
|
||||
e1000_put_hw_semaphore(hw);
|
||||
DEBUGOUT("Driver can't access the NVM\n");
|
||||
return -E1000_ERR_NVM;
|
||||
}
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_put_hw_semaphore - Release hardware semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Release hardware semaphore used to access the PHY or NVM
|
||||
**/
|
||||
void e1000_put_hw_semaphore(struct e1000_hw *hw)
|
||||
{
|
||||
u32 swsm;
|
||||
|
||||
DEBUGFUNC("e1000_put_hw_semaphore");
|
||||
|
||||
swsm = E1000_READ_REG(hw, E1000_SWSM);
|
||||
|
||||
swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
|
||||
|
||||
E1000_WRITE_REG(hw, E1000_SWSM, swsm);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* e1000_acquire_swfw_sync - Acquire SW/FW semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
* @mask: specifies which semaphore to acquire
|
||||
*
|
||||
* Acquire the SW/FW semaphore to access the PHY or NVM. The mask
|
||||
* will also specify which port we're acquiring the lock for.
|
||||
**/
|
||||
s32
|
||||
e1000_acquire_swfw_sync(struct e1000_hw *hw, u16 mask)
|
||||
{
|
||||
u32 swfw_sync;
|
||||
u32 swmask = mask;
|
||||
u32 fwmask = mask << 16;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
s32 i = 0, timeout = 200;
|
||||
|
||||
DEBUGFUNC("e1000_acquire_swfw_sync");
|
||||
ASSERT_NO_LOCKS();
|
||||
while (i < timeout) {
|
||||
if (e1000_get_hw_semaphore(hw)) {
|
||||
ret_val = -E1000_ERR_SWFW_SYNC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
|
||||
if (!(swfw_sync & (fwmask | swmask)))
|
||||
break;
|
||||
|
||||
/*
|
||||
* Firmware currently using resource (fwmask)
|
||||
* or other software thread using resource (swmask)
|
||||
*/
|
||||
e1000_put_hw_semaphore(hw);
|
||||
msec_delay_irq(5);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == timeout) {
|
||||
DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
|
||||
ret_val = -E1000_ERR_SWFW_SYNC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
swfw_sync |= swmask;
|
||||
E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
|
||||
|
||||
e1000_put_hw_semaphore(hw);
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_release_swfw_sync - Release SW/FW semaphore
|
||||
* @hw: pointer to the HW structure
|
||||
* @mask: specifies which semaphore to acquire
|
||||
*
|
||||
* Release the SW/FW semaphore used to access the PHY or NVM. The mask
|
||||
* will also specify which port we're releasing the lock for.
|
||||
**/
|
||||
void
|
||||
e1000_release_swfw_sync(struct e1000_hw *hw, u16 mask)
|
||||
{
|
||||
u32 swfw_sync;
|
||||
|
||||
DEBUGFUNC("e1000_release_swfw_sync");
|
||||
|
||||
while (e1000_get_hw_semaphore(hw) != E1000_SUCCESS)
|
||||
; /* Empty */
|
||||
|
||||
swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
|
||||
swfw_sync &= ~mask;
|
||||
E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
|
||||
|
||||
e1000_put_hw_semaphore(hw);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_mac.h 333345 2018-05-08 01:39:45Z mmacy $*/
|
||||
|
||||
#ifndef _E1000_MAC_H_
|
||||
#define _E1000_MAC_H_
|
||||
@@ -60,7 +61,6 @@ s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw);
|
||||
s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw);
|
||||
void e1000_set_lan_id_single_port(struct e1000_hw *hw);
|
||||
void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw);
|
||||
s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw);
|
||||
s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
|
||||
u16 *duplex);
|
||||
s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw,
|
||||
@@ -85,11 +85,15 @@ void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw);
|
||||
void e1000_clear_vfta_generic(struct e1000_hw *hw);
|
||||
void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count);
|
||||
void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw);
|
||||
void e1000_put_hw_semaphore_generic(struct e1000_hw *hw);
|
||||
s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw);
|
||||
void e1000_reset_adaptive_generic(struct e1000_hw *hw);
|
||||
void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop);
|
||||
void e1000_update_adaptive_generic(struct e1000_hw *hw);
|
||||
void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value);
|
||||
|
||||
s32 e1000_get_hw_semaphore(struct e1000_hw *hw);
|
||||
void e1000_put_hw_semaphore(struct e1000_hw *hw);
|
||||
s32 e1000_acquire_swfw_sync(struct e1000_hw *hw, u16 mask);
|
||||
void e1000_release_swfw_sync(struct e1000_hw *hw, u16 mask);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_manage.c 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
#include "e1000_api.h"
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_manage.h 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
#ifndef _E1000_MANAGE_H_
|
||||
#define _E1000_MANAGE_H_
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_mbx.c 330803 2018-03-12 17:05:53Z tsoome $*/
|
||||
|
||||
#include "e1000_mbx.h"
|
||||
|
||||
@@ -778,6 +779,7 @@ s32 e1000_init_mbx_params_pf(struct e1000_hw *hw)
|
||||
mbx->stats.reqs = 0;
|
||||
mbx->stats.acks = 0;
|
||||
mbx->stats.rsts = 0;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_mbx.h 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
#ifndef _E1000_MBX_H_
|
||||
#define _E1000_MBX_H_
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_nvm.c 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
#include "e1000_api.h"
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_nvm.h 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
#ifndef _E1000_NVM_H_
|
||||
#define _E1000_NVM_H_
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_osdep.c 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
#include "e1000_api.h"
|
||||
|
||||
|
||||
@@ -1,36 +1,37 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
||||
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,
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
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.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_osdep.h 333345 2018-05-08 01:39:45Z mmacy $*/
|
||||
|
||||
|
||||
#ifndef _FREEBSD_OS_H_
|
||||
@@ -39,6 +40,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/mbuf.h>
|
||||
@@ -47,6 +49,15 @@
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/sx.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/iflib.h>
|
||||
|
||||
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <machine/resource.h>
|
||||
@@ -58,11 +69,40 @@
|
||||
|
||||
|
||||
#define ASSERT(x) if(!(x)) panic("EM: x")
|
||||
#define us_scale(x) max(1, (x/(1000000/hz)))
|
||||
static inline int
|
||||
ms_scale(int x) {
|
||||
if (hz == 1000) {
|
||||
return (x);
|
||||
} else if (hz > 1000) {
|
||||
return (x*(hz/1000));
|
||||
} else {
|
||||
return (max(1, x/(1000/hz)));
|
||||
}
|
||||
}
|
||||
|
||||
#define usec_delay(x) DELAY(x)
|
||||
static inline void
|
||||
safe_pause_us(int x) {
|
||||
if (cold) {
|
||||
DELAY(x);
|
||||
} else {
|
||||
pause("e1000_delay", max(1, x/(1000000/hz)));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
safe_pause_ms(int x) {
|
||||
if (cold) {
|
||||
DELAY(x*1000);
|
||||
} else {
|
||||
pause("e1000_delay", ms_scale(x));
|
||||
}
|
||||
}
|
||||
|
||||
#define usec_delay(x) safe_pause_us(x)
|
||||
#define usec_delay_irq(x) usec_delay(x)
|
||||
#define msec_delay(x) DELAY(1000*(x))
|
||||
#define msec_delay_irq(x) DELAY(1000*(x))
|
||||
#define msec_delay(x) safe_pause_ms(x)
|
||||
#define msec_delay_irq(x) msec_delay(x)
|
||||
|
||||
/* Enable/disable debugging statements in shared code */
|
||||
#define DBG 0
|
||||
@@ -81,16 +121,6 @@
|
||||
#define CMD_MEM_WRT_INVALIDATE 0x0010 /* BIT_4 */
|
||||
#define PCI_COMMAND_REGISTER PCIR_COMMAND
|
||||
|
||||
/* Mutex used in the shared code */
|
||||
#define E1000_MUTEX struct mtx
|
||||
#define E1000_MUTEX_INIT(mutex) mtx_init((mutex), #mutex, \
|
||||
MTX_NETWORK_LOCK, \
|
||||
MTX_DEF | MTX_DUPOK)
|
||||
#define E1000_MUTEX_DESTROY(mutex) mtx_destroy(mutex)
|
||||
#define E1000_MUTEX_LOCK(mutex) mtx_lock(mutex)
|
||||
#define E1000_MUTEX_TRYLOCK(mutex) mtx_trylock(mutex)
|
||||
#define E1000_MUTEX_UNLOCK(mutex) mtx_unlock(mutex)
|
||||
|
||||
typedef uint64_t u64;
|
||||
typedef uint32_t u32;
|
||||
typedef uint16_t u16;
|
||||
@@ -116,6 +146,12 @@ typedef int8_t s8;
|
||||
#endif
|
||||
#endif /*__FreeBSD_version < 800000 */
|
||||
|
||||
#ifdef INVARIANTS
|
||||
#define ASSERT_CTX_LOCK_HELD(hw) sx_assert(iflib_ctx_lock_get(((struct e1000_osdep *)hw->back)->ctx), SX_XLOCKED)
|
||||
#else
|
||||
#define ASSERT_CTX_LOCK_HELD(hw)
|
||||
#endif
|
||||
|
||||
#if defined(__i386__) || defined(__amd64__)
|
||||
static __inline
|
||||
void prefetch(void *x)
|
||||
@@ -134,7 +170,8 @@ struct e1000_osdep
|
||||
bus_space_handle_t io_bus_space_handle;
|
||||
bus_space_tag_t flash_bus_space_tag;
|
||||
bus_space_handle_t flash_bus_space_handle;
|
||||
struct device *dev;
|
||||
device_t dev;
|
||||
if_ctx_t ctx;
|
||||
};
|
||||
|
||||
#define E1000_REGISTER(hw, reg) (((hw)->mac.type >= e1000_82543) \
|
||||
@@ -216,5 +253,22 @@ struct e1000_osdep
|
||||
bus_space_write_2(((struct e1000_osdep *)(hw)->back)->flash_bus_space_tag, \
|
||||
((struct e1000_osdep *)(hw)->back)->flash_bus_space_handle, reg, value)
|
||||
|
||||
|
||||
#if 0
|
||||
#include <sys/proc.h>
|
||||
|
||||
#define ASSERT_NO_LOCKS() \
|
||||
do { \
|
||||
int unknown_locks = curthread->td_locks - mtx_owned(&Giant); \
|
||||
if (unknown_locks > 0) { \
|
||||
WITNESS_WARN(WARN_GIANTOK|WARN_SLEEPOK|WARN_PANIC, NULL, "unexpected non-sleepable lock"); \
|
||||
} \
|
||||
MPASS(curthread->td_rw_rlocks == 0); \
|
||||
MPASS(curthread->td_lk_slocks == 0); \
|
||||
} while (0)
|
||||
#else
|
||||
#define ASSERT_NO_LOCKS()
|
||||
#endif
|
||||
|
||||
#endif /* _FREEBSD_OS_H_ */
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_phy.c 330803 2018-03-12 17:05:53Z tsoome $*/
|
||||
|
||||
#include "e1000_api.h"
|
||||
|
||||
@@ -1297,6 +1298,7 @@ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
|
||||
phy_data |= M88E1000_PSCR_AUTO_X_1000T;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 0:
|
||||
default:
|
||||
phy_data |= M88E1000_PSCR_AUTO_X_MODE;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_phy.h 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
#ifndef _E1000_PHY_H_
|
||||
#define _E1000_PHY_H_
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_regs.h 327865 2018-01-12 06:37:53Z eadler $*/
|
||||
|
||||
#ifndef _E1000_REGS_H_
|
||||
#define _E1000_REGS_H_
|
||||
@@ -214,7 +215,7 @@
|
||||
/* QAV Tx mode control register bitfields masks */
|
||||
#define E1000_TQAVCC_IDLE_SLOPE 0xFFFF /* Idle slope */
|
||||
#define E1000_TQAVCC_KEEP_CREDITS (1 << 30) /* Keep credits opt enable */
|
||||
#define E1000_TQAVCC_QUEUE_MODE (1 << 31) /* SP vs. SR Tx mode */
|
||||
#define E1000_TQAVCC_QUEUE_MODE (1U << 31) /* SP vs. SR Tx mode */
|
||||
|
||||
/* Good transmitted packets counter registers */
|
||||
#define E1000_PQGPTC(_n) (0x010014 + (0x100 * (_n)))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_vf.c 330803 2018-03-12 17:05:53Z tsoome $*/
|
||||
|
||||
|
||||
#include "e1000_api.h"
|
||||
@@ -487,8 +488,10 @@ s32 e1000_promisc_set_vf(struct e1000_hw *hw, enum e1000_promisc_type type)
|
||||
break;
|
||||
case e1000_promisc_enabled:
|
||||
msgbuf |= E1000_VF_SET_PROMISC_MULTICAST;
|
||||
/* FALLTHROUGH */
|
||||
case e1000_promisc_unicast:
|
||||
msgbuf |= E1000_VF_SET_PROMISC_UNICAST;
|
||||
/* FALLTHROUGH */
|
||||
case e1000_promisc_disabled:
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
All rights reserved.
|
||||
@@ -30,7 +31,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/e1000_vf.h 326022 2017-11-20 19:36:21Z pfg $*/
|
||||
|
||||
#ifndef _E1000_VF_H_
|
||||
#define _E1000_VF_H_
|
||||
|
||||
@@ -0,0 +1,809 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Nicole Graziano <nicole@nextbsd.org>
|
||||
* Copyright (c) 2017 Matthew Macy <mmacy@mattmacy.io>
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
/* $FreeBSD: releng/12.0/sys/dev/e1000/em_txrx.c 340366 2018-11-12 16:28:07Z shurd $ */
|
||||
#include "if_em.h"
|
||||
|
||||
#ifdef RSS
|
||||
#include <net/rss_config.h>
|
||||
#include <netinet/in_rss.h>
|
||||
#endif
|
||||
|
||||
#ifdef VERBOSE_DEBUG
|
||||
#define DPRINTF device_printf
|
||||
#else
|
||||
#define DPRINTF(...)
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
* Local Function prototypes
|
||||
*********************************************************************/
|
||||
static int em_tso_setup(struct adapter *adapter, if_pkt_info_t pi, u32 *txd_upper,
|
||||
u32 *txd_lower);
|
||||
static int em_transmit_checksum_setup(struct adapter *adapter, if_pkt_info_t pi,
|
||||
u32 *txd_upper, u32 *txd_lower);
|
||||
static int em_isc_txd_encap(void *arg, if_pkt_info_t pi);
|
||||
static void em_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx);
|
||||
static int em_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear);
|
||||
static void em_isc_rxd_refill(void *arg, if_rxd_update_t iru);
|
||||
static void em_isc_rxd_flush(void *arg, uint16_t rxqid, uint8_t flid __unused,
|
||||
qidx_t pidx);
|
||||
static int em_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx,
|
||||
qidx_t budget);
|
||||
static int em_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri);
|
||||
|
||||
static void lem_isc_rxd_refill(void *arg, if_rxd_update_t iru);
|
||||
|
||||
static int lem_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx,
|
||||
qidx_t budget);
|
||||
static int lem_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri);
|
||||
|
||||
static void lem_receive_checksum(int status, int errors, if_rxd_info_t ri);
|
||||
static void em_receive_checksum(uint32_t status, if_rxd_info_t ri);
|
||||
static int em_determine_rsstype(u32 pkt_info);
|
||||
extern int em_intr(void *arg);
|
||||
|
||||
struct if_txrx em_txrx = {
|
||||
.ift_txd_encap = em_isc_txd_encap,
|
||||
.ift_txd_flush = em_isc_txd_flush,
|
||||
.ift_txd_credits_update = em_isc_txd_credits_update,
|
||||
.ift_rxd_available = em_isc_rxd_available,
|
||||
.ift_rxd_pkt_get = em_isc_rxd_pkt_get,
|
||||
.ift_rxd_refill = em_isc_rxd_refill,
|
||||
.ift_rxd_flush = em_isc_rxd_flush,
|
||||
.ift_legacy_intr = em_intr
|
||||
};
|
||||
|
||||
struct if_txrx lem_txrx = {
|
||||
.ift_txd_encap = em_isc_txd_encap,
|
||||
.ift_txd_flush = em_isc_txd_flush,
|
||||
.ift_txd_credits_update = em_isc_txd_credits_update,
|
||||
.ift_rxd_available = lem_isc_rxd_available,
|
||||
.ift_rxd_pkt_get = lem_isc_rxd_pkt_get,
|
||||
.ift_rxd_refill = lem_isc_rxd_refill,
|
||||
.ift_rxd_flush = em_isc_rxd_flush,
|
||||
.ift_legacy_intr = em_intr
|
||||
};
|
||||
|
||||
extern if_shared_ctx_t em_sctx;
|
||||
|
||||
void
|
||||
em_dump_rs(struct adapter *adapter)
|
||||
{
|
||||
if_softc_ctx_t scctx = adapter->shared;
|
||||
struct em_tx_queue *que;
|
||||
struct tx_ring *txr;
|
||||
qidx_t i, ntxd, qid, cur;
|
||||
int16_t rs_cidx;
|
||||
uint8_t status;
|
||||
|
||||
printf("\n");
|
||||
ntxd = scctx->isc_ntxd[0];
|
||||
for (qid = 0; qid < adapter->tx_num_queues; qid++) {
|
||||
que = &adapter->tx_queues[qid];
|
||||
txr = &que->txr;
|
||||
rs_cidx = txr->tx_rs_cidx;
|
||||
if (rs_cidx != txr->tx_rs_pidx) {
|
||||
cur = txr->tx_rsq[rs_cidx];
|
||||
status = txr->tx_base[cur].upper.fields.status;
|
||||
if (!(status & E1000_TXD_STAT_DD))
|
||||
printf("qid[%d]->tx_rsq[%d]: %d clear ", qid, rs_cidx, cur);
|
||||
} else {
|
||||
rs_cidx = (rs_cidx-1)&(ntxd-1);
|
||||
cur = txr->tx_rsq[rs_cidx];
|
||||
printf("qid[%d]->tx_rsq[rs_cidx-1=%d]: %d ", qid, rs_cidx, cur);
|
||||
}
|
||||
printf("cidx_prev=%d rs_pidx=%d ",txr->tx_cidx_processed, txr->tx_rs_pidx);
|
||||
for (i = 0; i < ntxd; i++) {
|
||||
if (txr->tx_base[i].upper.fields.status & E1000_TXD_STAT_DD)
|
||||
printf("%d set ", i);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* Setup work for hardware segmentation offload (TSO) on
|
||||
* adapters using advanced tx descriptors
|
||||
*
|
||||
**********************************************************************/
|
||||
static int
|
||||
em_tso_setup(struct adapter *adapter, if_pkt_info_t pi, u32 *txd_upper, u32 *txd_lower)
|
||||
{
|
||||
if_softc_ctx_t scctx = adapter->shared;
|
||||
struct em_tx_queue *que = &adapter->tx_queues[pi->ipi_qsidx];
|
||||
struct tx_ring *txr = &que->txr;
|
||||
struct e1000_context_desc *TXD;
|
||||
int cur, hdr_len;
|
||||
|
||||
hdr_len = pi->ipi_ehdrlen + pi->ipi_ip_hlen + pi->ipi_tcp_hlen;
|
||||
*txd_lower = (E1000_TXD_CMD_DEXT | /* Extended descr type */
|
||||
E1000_TXD_DTYP_D | /* Data descr type */
|
||||
E1000_TXD_CMD_TSE); /* Do TSE on this packet */
|
||||
|
||||
/* IP and/or TCP header checksum calculation and insertion. */
|
||||
*txd_upper = (E1000_TXD_POPTS_IXSM | E1000_TXD_POPTS_TXSM) << 8;
|
||||
|
||||
cur = pi->ipi_pidx;
|
||||
TXD = (struct e1000_context_desc *)&txr->tx_base[cur];
|
||||
|
||||
/*
|
||||
* Start offset for header checksum calculation.
|
||||
* End offset for header checksum calculation.
|
||||
* Offset of place put the checksum.
|
||||
*/
|
||||
TXD->lower_setup.ip_fields.ipcss = pi->ipi_ehdrlen;
|
||||
TXD->lower_setup.ip_fields.ipcse =
|
||||
htole16(pi->ipi_ehdrlen + pi->ipi_ip_hlen - 1);
|
||||
TXD->lower_setup.ip_fields.ipcso = pi->ipi_ehdrlen + offsetof(struct ip, ip_sum);
|
||||
|
||||
/*
|
||||
* Start offset for payload checksum calculation.
|
||||
* End offset for payload checksum calculation.
|
||||
* Offset of place to put the checksum.
|
||||
*/
|
||||
TXD->upper_setup.tcp_fields.tucss = pi->ipi_ehdrlen + pi->ipi_ip_hlen;
|
||||
TXD->upper_setup.tcp_fields.tucse = 0;
|
||||
TXD->upper_setup.tcp_fields.tucso =
|
||||
pi->ipi_ehdrlen + pi->ipi_ip_hlen + offsetof(struct tcphdr, th_sum);
|
||||
|
||||
/*
|
||||
* Payload size per packet w/o any headers.
|
||||
* Length of all headers up to payload.
|
||||
*/
|
||||
TXD->tcp_seg_setup.fields.mss = htole16(pi->ipi_tso_segsz);
|
||||
TXD->tcp_seg_setup.fields.hdr_len = hdr_len;
|
||||
|
||||
TXD->cmd_and_length = htole32(adapter->txd_cmd |
|
||||
E1000_TXD_CMD_DEXT | /* Extended descr */
|
||||
E1000_TXD_CMD_TSE | /* TSE context */
|
||||
E1000_TXD_CMD_IP | /* Do IP csum */
|
||||
E1000_TXD_CMD_TCP | /* Do TCP checksum */
|
||||
(pi->ipi_len - hdr_len)); /* Total len */
|
||||
txr->tx_tso = TRUE;
|
||||
|
||||
if (++cur == scctx->isc_ntxd[0]) {
|
||||
cur = 0;
|
||||
}
|
||||
DPRINTF(iflib_get_dev(adapter->ctx), "%s: pidx: %d cur: %d\n", __FUNCTION__, pi->ipi_pidx, cur);
|
||||
return (cur);
|
||||
}
|
||||
|
||||
#define TSO_WORKAROUND 4
|
||||
#define DONT_FORCE_CTX 1
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* The offload context is protocol specific (TCP/UDP) and thus
|
||||
* only needs to be set when the protocol changes. The occasion
|
||||
* of a context change can be a performance detriment, and
|
||||
* might be better just disabled. The reason arises in the way
|
||||
* in which the controller supports pipelined requests from the
|
||||
* Tx data DMA. Up to four requests can be pipelined, and they may
|
||||
* belong to the same packet or to multiple packets. However all
|
||||
* requests for one packet are issued before a request is issued
|
||||
* for a subsequent packet and if a request for the next packet
|
||||
* requires a context change, that request will be stalled
|
||||
* until the previous request completes. This means setting up
|
||||
* a new context effectively disables pipelined Tx data DMA which
|
||||
* in turn greatly slow down performance to send small sized
|
||||
* frames.
|
||||
**********************************************************************/
|
||||
|
||||
static int
|
||||
em_transmit_checksum_setup(struct adapter *adapter, if_pkt_info_t pi, u32 *txd_upper, u32 *txd_lower)
|
||||
{
|
||||
struct e1000_context_desc *TXD = NULL;
|
||||
if_softc_ctx_t scctx = adapter->shared;
|
||||
struct em_tx_queue *que = &adapter->tx_queues[pi->ipi_qsidx];
|
||||
struct tx_ring *txr = &que->txr;
|
||||
int csum_flags = pi->ipi_csum_flags;
|
||||
int cur, hdr_len;
|
||||
u32 cmd;
|
||||
|
||||
cur = pi->ipi_pidx;
|
||||
hdr_len = pi->ipi_ehdrlen + pi->ipi_ip_hlen;
|
||||
cmd = adapter->txd_cmd;
|
||||
|
||||
/*
|
||||
* The 82574L can only remember the *last* context used
|
||||
* regardless of queue that it was use for. We cannot reuse
|
||||
* contexts on this hardware platform and must generate a new
|
||||
* context every time. 82574L hardware spec, section 7.2.6,
|
||||
* second note.
|
||||
*/
|
||||
if (DONT_FORCE_CTX &&
|
||||
adapter->tx_num_queues == 1 &&
|
||||
txr->csum_lhlen == pi->ipi_ehdrlen &&
|
||||
txr->csum_iphlen == pi->ipi_ip_hlen &&
|
||||
txr->csum_flags == csum_flags) {
|
||||
/*
|
||||
* Same csum offload context as the previous packets;
|
||||
* just return.
|
||||
*/
|
||||
*txd_upper = txr->csum_txd_upper;
|
||||
*txd_lower = txr->csum_txd_lower;
|
||||
return (cur);
|
||||
}
|
||||
|
||||
TXD = (struct e1000_context_desc *)&txr->tx_base[cur];
|
||||
if (csum_flags & CSUM_IP) {
|
||||
*txd_upper |= E1000_TXD_POPTS_IXSM << 8;
|
||||
/*
|
||||
* Start offset for header checksum calculation.
|
||||
* End offset for header checksum calculation.
|
||||
* Offset of place to put the checksum.
|
||||
*/
|
||||
TXD->lower_setup.ip_fields.ipcss = pi->ipi_ehdrlen;
|
||||
TXD->lower_setup.ip_fields.ipcse = htole16(hdr_len);
|
||||
TXD->lower_setup.ip_fields.ipcso = pi->ipi_ehdrlen + offsetof(struct ip, ip_sum);
|
||||
cmd |= E1000_TXD_CMD_IP;
|
||||
}
|
||||
|
||||
if (csum_flags & (CSUM_TCP|CSUM_UDP)) {
|
||||
uint8_t tucso;
|
||||
|
||||
*txd_upper |= E1000_TXD_POPTS_TXSM << 8;
|
||||
*txd_lower = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
|
||||
|
||||
if (csum_flags & CSUM_TCP) {
|
||||
tucso = hdr_len + offsetof(struct tcphdr, th_sum);
|
||||
cmd |= E1000_TXD_CMD_TCP;
|
||||
} else
|
||||
tucso = hdr_len + offsetof(struct udphdr, uh_sum);
|
||||
TXD->upper_setup.tcp_fields.tucss = hdr_len;
|
||||
TXD->upper_setup.tcp_fields.tucse = htole16(0);
|
||||
TXD->upper_setup.tcp_fields.tucso = tucso;
|
||||
}
|
||||
|
||||
txr->csum_lhlen = pi->ipi_ehdrlen;
|
||||
txr->csum_iphlen = pi->ipi_ip_hlen;
|
||||
txr->csum_flags = csum_flags;
|
||||
txr->csum_txd_upper = *txd_upper;
|
||||
txr->csum_txd_lower = *txd_lower;
|
||||
|
||||
TXD->tcp_seg_setup.data = htole32(0);
|
||||
TXD->cmd_and_length =
|
||||
htole32(E1000_TXD_CMD_IFCS | E1000_TXD_CMD_DEXT | cmd);
|
||||
|
||||
if (++cur == scctx->isc_ntxd[0]) {
|
||||
cur = 0;
|
||||
}
|
||||
DPRINTF(iflib_get_dev(adapter->ctx), "checksum_setup csum_flags=%x txd_upper=%x txd_lower=%x hdr_len=%d cmd=%x\n",
|
||||
csum_flags, *txd_upper, *txd_lower, hdr_len, cmd);
|
||||
return (cur);
|
||||
}
|
||||
|
||||
static int
|
||||
em_isc_txd_encap(void *arg, if_pkt_info_t pi)
|
||||
{
|
||||
struct adapter *sc = arg;
|
||||
if_softc_ctx_t scctx = sc->shared;
|
||||
struct em_tx_queue *que = &sc->tx_queues[pi->ipi_qsidx];
|
||||
struct tx_ring *txr = &que->txr;
|
||||
bus_dma_segment_t *segs = pi->ipi_segs;
|
||||
int nsegs = pi->ipi_nsegs;
|
||||
int csum_flags = pi->ipi_csum_flags;
|
||||
int i, j, first, pidx_last;
|
||||
u32 txd_flags, txd_upper = 0, txd_lower = 0;
|
||||
|
||||
struct e1000_tx_desc *ctxd = NULL;
|
||||
bool do_tso, tso_desc;
|
||||
qidx_t ntxd;
|
||||
|
||||
txd_flags = pi->ipi_flags & IPI_TX_INTR ? E1000_TXD_CMD_RS : 0;
|
||||
i = first = pi->ipi_pidx;
|
||||
do_tso = (csum_flags & CSUM_TSO);
|
||||
tso_desc = FALSE;
|
||||
ntxd = scctx->isc_ntxd[0];
|
||||
/*
|
||||
* TSO Hardware workaround, if this packet is not
|
||||
* TSO, and is only a single descriptor long, and
|
||||
* it follows a TSO burst, then we need to add a
|
||||
* sentinel descriptor to prevent premature writeback.
|
||||
*/
|
||||
if ((!do_tso) && (txr->tx_tso == TRUE)) {
|
||||
if (nsegs == 1)
|
||||
tso_desc = TRUE;
|
||||
txr->tx_tso = FALSE;
|
||||
}
|
||||
|
||||
/* Do hardware assists */
|
||||
if (do_tso) {
|
||||
i = em_tso_setup(sc, pi, &txd_upper, &txd_lower);
|
||||
tso_desc = TRUE;
|
||||
} else if (csum_flags & EM_CSUM_OFFLOAD) {
|
||||
i = em_transmit_checksum_setup(sc, pi, &txd_upper, &txd_lower);
|
||||
}
|
||||
|
||||
if (pi->ipi_mflags & M_VLANTAG) {
|
||||
/* Set the vlan id. */
|
||||
txd_upper |= htole16(pi->ipi_vtag) << 16;
|
||||
/* Tell hardware to add tag */
|
||||
txd_lower |= htole32(E1000_TXD_CMD_VLE);
|
||||
}
|
||||
|
||||
DPRINTF(iflib_get_dev(sc->ctx), "encap: set up tx: nsegs=%d first=%d i=%d\n", nsegs, first, i);
|
||||
/* XXX adapter->pcix_82544 -- lem_fill_descriptors */
|
||||
|
||||
/* Set up our transmit descriptors */
|
||||
for (j = 0; j < nsegs; j++) {
|
||||
bus_size_t seg_len;
|
||||
bus_addr_t seg_addr;
|
||||
uint32_t cmd;
|
||||
|
||||
ctxd = &txr->tx_base[i];
|
||||
seg_addr = segs[j].ds_addr;
|
||||
seg_len = segs[j].ds_len;
|
||||
cmd = E1000_TXD_CMD_IFCS | sc->txd_cmd;
|
||||
|
||||
/*
|
||||
* TSO Workaround:
|
||||
* If this is the last descriptor, we want to
|
||||
* split it so we have a small final sentinel
|
||||
*/
|
||||
if (tso_desc && (j == (nsegs - 1)) && (seg_len > 8)) {
|
||||
seg_len -= TSO_WORKAROUND;
|
||||
ctxd->buffer_addr = htole64(seg_addr);
|
||||
ctxd->lower.data = htole32(cmd | txd_lower | seg_len);
|
||||
ctxd->upper.data = htole32(txd_upper);
|
||||
|
||||
if (++i == scctx->isc_ntxd[0])
|
||||
i = 0;
|
||||
|
||||
/* Now make the sentinel */
|
||||
ctxd = &txr->tx_base[i];
|
||||
ctxd->buffer_addr = htole64(seg_addr + seg_len);
|
||||
ctxd->lower.data = htole32(cmd | txd_lower | TSO_WORKAROUND);
|
||||
ctxd->upper.data = htole32(txd_upper);
|
||||
pidx_last = i;
|
||||
if (++i == scctx->isc_ntxd[0])
|
||||
i = 0;
|
||||
DPRINTF(iflib_get_dev(sc->ctx), "TSO path pidx_last=%d i=%d ntxd[0]=%d\n", pidx_last, i, scctx->isc_ntxd[0]);
|
||||
} else {
|
||||
ctxd->buffer_addr = htole64(seg_addr);
|
||||
ctxd->lower.data = htole32(cmd | txd_lower | seg_len);
|
||||
ctxd->upper.data = htole32(txd_upper);
|
||||
pidx_last = i;
|
||||
if (++i == scctx->isc_ntxd[0])
|
||||
i = 0;
|
||||
DPRINTF(iflib_get_dev(sc->ctx), "pidx_last=%d i=%d ntxd[0]=%d\n", pidx_last, i, scctx->isc_ntxd[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Last Descriptor of Packet
|
||||
* needs End Of Packet (EOP)
|
||||
* and Report Status (RS)
|
||||
*/
|
||||
if (txd_flags && nsegs) {
|
||||
txr->tx_rsq[txr->tx_rs_pidx] = pidx_last;
|
||||
DPRINTF(iflib_get_dev(sc->ctx), "setting to RS on %d rs_pidx %d first: %d\n", pidx_last, txr->tx_rs_pidx, first);
|
||||
txr->tx_rs_pidx = (txr->tx_rs_pidx+1) & (ntxd-1);
|
||||
MPASS(txr->tx_rs_pidx != txr->tx_rs_cidx);
|
||||
}
|
||||
ctxd->lower.data |= htole32(E1000_TXD_CMD_EOP | txd_flags);
|
||||
DPRINTF(iflib_get_dev(sc->ctx), "tx_buffers[%d]->eop = %d ipi_new_pidx=%d\n", first, pidx_last, i);
|
||||
pi->ipi_new_pidx = i;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
em_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx)
|
||||
{
|
||||
struct adapter *adapter = arg;
|
||||
struct em_tx_queue *que = &adapter->tx_queues[txqid];
|
||||
struct tx_ring *txr = &que->txr;
|
||||
|
||||
E1000_WRITE_REG(&adapter->hw, E1000_TDT(txr->me), pidx);
|
||||
}
|
||||
|
||||
static int
|
||||
em_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear)
|
||||
{
|
||||
struct adapter *adapter = arg;
|
||||
if_softc_ctx_t scctx = adapter->shared;
|
||||
struct em_tx_queue *que = &adapter->tx_queues[txqid];
|
||||
struct tx_ring *txr = &que->txr;
|
||||
|
||||
qidx_t processed = 0;
|
||||
int updated;
|
||||
qidx_t cur, prev, ntxd, rs_cidx;
|
||||
int32_t delta;
|
||||
uint8_t status;
|
||||
|
||||
rs_cidx = txr->tx_rs_cidx;
|
||||
if (rs_cidx == txr->tx_rs_pidx)
|
||||
return (0);
|
||||
cur = txr->tx_rsq[rs_cidx];
|
||||
MPASS(cur != QIDX_INVALID);
|
||||
status = txr->tx_base[cur].upper.fields.status;
|
||||
updated = !!(status & E1000_TXD_STAT_DD);
|
||||
|
||||
if (!updated)
|
||||
return (0);
|
||||
|
||||
/* If clear is false just let caller know that there
|
||||
* are descriptors to reclaim */
|
||||
if (!clear)
|
||||
return (1);
|
||||
|
||||
prev = txr->tx_cidx_processed;
|
||||
ntxd = scctx->isc_ntxd[0];
|
||||
do {
|
||||
delta = (int32_t)cur - (int32_t)prev;
|
||||
/*
|
||||
* XXX This appears to be a hack for first-packet.
|
||||
* A correct fix would prevent prev == cur in the first place.
|
||||
*/
|
||||
MPASS(prev == 0 || delta != 0);
|
||||
if (prev == 0 && cur == 0)
|
||||
delta += 1;
|
||||
if (delta < 0)
|
||||
delta += ntxd;
|
||||
DPRINTF(iflib_get_dev(adapter->ctx),
|
||||
"%s: cidx_processed=%u cur=%u clear=%d delta=%d\n",
|
||||
__FUNCTION__, prev, cur, clear, delta);
|
||||
|
||||
processed += delta;
|
||||
prev = cur;
|
||||
rs_cidx = (rs_cidx + 1) & (ntxd-1);
|
||||
if (rs_cidx == txr->tx_rs_pidx)
|
||||
break;
|
||||
cur = txr->tx_rsq[rs_cidx];
|
||||
MPASS(cur != QIDX_INVALID);
|
||||
status = txr->tx_base[cur].upper.fields.status;
|
||||
} while ((status & E1000_TXD_STAT_DD));
|
||||
|
||||
txr->tx_rs_cidx = rs_cidx;
|
||||
txr->tx_cidx_processed = prev;
|
||||
return(processed);
|
||||
}
|
||||
|
||||
static void
|
||||
lem_isc_rxd_refill(void *arg, if_rxd_update_t iru)
|
||||
{
|
||||
struct adapter *sc = arg;
|
||||
if_softc_ctx_t scctx = sc->shared;
|
||||
struct em_rx_queue *que = &sc->rx_queues[iru->iru_qsidx];
|
||||
struct rx_ring *rxr = &que->rxr;
|
||||
struct e1000_rx_desc *rxd;
|
||||
uint64_t *paddrs;
|
||||
uint32_t next_pidx, pidx;
|
||||
uint16_t count;
|
||||
int i;
|
||||
|
||||
paddrs = iru->iru_paddrs;
|
||||
pidx = iru->iru_pidx;
|
||||
count = iru->iru_count;
|
||||
|
||||
for (i = 0, next_pidx = pidx; i < count; i++) {
|
||||
rxd = (struct e1000_rx_desc *)&rxr->rx_base[next_pidx];
|
||||
rxd->buffer_addr = htole64(paddrs[i]);
|
||||
/* status bits must be cleared */
|
||||
rxd->status = 0;
|
||||
|
||||
if (++next_pidx == scctx->isc_nrxd[0])
|
||||
next_pidx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
em_isc_rxd_refill(void *arg, if_rxd_update_t iru)
|
||||
{
|
||||
struct adapter *sc = arg;
|
||||
if_softc_ctx_t scctx = sc->shared;
|
||||
uint16_t rxqid = iru->iru_qsidx;
|
||||
struct em_rx_queue *que = &sc->rx_queues[rxqid];
|
||||
struct rx_ring *rxr = &que->rxr;
|
||||
union e1000_rx_desc_extended *rxd;
|
||||
uint64_t *paddrs;
|
||||
uint32_t next_pidx, pidx;
|
||||
uint16_t count;
|
||||
int i;
|
||||
|
||||
paddrs = iru->iru_paddrs;
|
||||
pidx = iru->iru_pidx;
|
||||
count = iru->iru_count;
|
||||
|
||||
for (i = 0, next_pidx = pidx; i < count; i++) {
|
||||
rxd = &rxr->rx_base[next_pidx];
|
||||
rxd->read.buffer_addr = htole64(paddrs[i]);
|
||||
/* DD bits must be cleared */
|
||||
rxd->wb.upper.status_error = 0;
|
||||
|
||||
if (++next_pidx == scctx->isc_nrxd[0])
|
||||
next_pidx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
em_isc_rxd_flush(void *arg, uint16_t rxqid, uint8_t flid __unused, qidx_t pidx)
|
||||
{
|
||||
struct adapter *sc = arg;
|
||||
struct em_rx_queue *que = &sc->rx_queues[rxqid];
|
||||
struct rx_ring *rxr = &que->rxr;
|
||||
|
||||
E1000_WRITE_REG(&sc->hw, E1000_RDT(rxr->me), pidx);
|
||||
}
|
||||
|
||||
static int
|
||||
lem_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx, qidx_t budget)
|
||||
{
|
||||
struct adapter *sc = arg;
|
||||
if_softc_ctx_t scctx = sc->shared;
|
||||
struct em_rx_queue *que = &sc->rx_queues[rxqid];
|
||||
struct rx_ring *rxr = &que->rxr;
|
||||
struct e1000_rx_desc *rxd;
|
||||
u32 staterr = 0;
|
||||
int cnt, i;
|
||||
|
||||
for (cnt = 0, i = idx; cnt < scctx->isc_nrxd[0] && cnt <= budget;) {
|
||||
rxd = (struct e1000_rx_desc *)&rxr->rx_base[i];
|
||||
staterr = rxd->status;
|
||||
|
||||
if ((staterr & E1000_RXD_STAT_DD) == 0)
|
||||
break;
|
||||
if (++i == scctx->isc_nrxd[0])
|
||||
i = 0;
|
||||
if (staterr & E1000_RXD_STAT_EOP)
|
||||
cnt++;
|
||||
}
|
||||
return (cnt);
|
||||
}
|
||||
|
||||
static int
|
||||
em_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx, qidx_t budget)
|
||||
{
|
||||
struct adapter *sc = arg;
|
||||
if_softc_ctx_t scctx = sc->shared;
|
||||
struct em_rx_queue *que = &sc->rx_queues[rxqid];
|
||||
struct rx_ring *rxr = &que->rxr;
|
||||
union e1000_rx_desc_extended *rxd;
|
||||
u32 staterr = 0;
|
||||
int cnt, i;
|
||||
|
||||
for (cnt = 0, i = idx; cnt < scctx->isc_nrxd[0] && cnt <= budget;) {
|
||||
rxd = &rxr->rx_base[i];
|
||||
staterr = le32toh(rxd->wb.upper.status_error);
|
||||
|
||||
if ((staterr & E1000_RXD_STAT_DD) == 0)
|
||||
break;
|
||||
if (++i == scctx->isc_nrxd[0])
|
||||
i = 0;
|
||||
if (staterr & E1000_RXD_STAT_EOP)
|
||||
cnt++;
|
||||
}
|
||||
return (cnt);
|
||||
}
|
||||
|
||||
static int
|
||||
lem_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri)
|
||||
{
|
||||
struct adapter *adapter = arg;
|
||||
if_softc_ctx_t scctx = adapter->shared;
|
||||
struct em_rx_queue *que = &adapter->rx_queues[ri->iri_qsidx];
|
||||
struct rx_ring *rxr = &que->rxr;
|
||||
struct e1000_rx_desc *rxd;
|
||||
u16 len;
|
||||
u32 status, errors;
|
||||
bool eop;
|
||||
int i, cidx;
|
||||
|
||||
status = errors = i = 0;
|
||||
cidx = ri->iri_cidx;
|
||||
|
||||
do {
|
||||
rxd = (struct e1000_rx_desc *)&rxr->rx_base[cidx];
|
||||
status = rxd->status;
|
||||
errors = rxd->errors;
|
||||
|
||||
/* Error Checking then decrement count */
|
||||
MPASS ((status & E1000_RXD_STAT_DD) != 0);
|
||||
|
||||
len = le16toh(rxd->length);
|
||||
ri->iri_len += len;
|
||||
|
||||
eop = (status & E1000_RXD_STAT_EOP) != 0;
|
||||
|
||||
/* Make sure bad packets are discarded */
|
||||
if (errors & E1000_RXD_ERR_FRAME_ERR_MASK) {
|
||||
adapter->dropped_pkts++;
|
||||
/* XXX fixup if common */
|
||||
return (EBADMSG);
|
||||
}
|
||||
|
||||
ri->iri_frags[i].irf_flid = 0;
|
||||
ri->iri_frags[i].irf_idx = cidx;
|
||||
ri->iri_frags[i].irf_len = len;
|
||||
/* Zero out the receive descriptors status. */
|
||||
rxd->status = 0;
|
||||
|
||||
if (++cidx == scctx->isc_nrxd[0])
|
||||
cidx = 0;
|
||||
i++;
|
||||
} while (!eop);
|
||||
|
||||
/* XXX add a faster way to look this up */
|
||||
if (adapter->hw.mac.type >= e1000_82543 && !(status & E1000_RXD_STAT_IXSM))
|
||||
lem_receive_checksum(status, errors, ri);
|
||||
|
||||
if (status & E1000_RXD_STAT_VP) {
|
||||
ri->iri_vtag = le16toh(rxd->special);
|
||||
ri->iri_flags |= M_VLANTAG;
|
||||
}
|
||||
|
||||
ri->iri_nfrags = i;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
em_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri)
|
||||
{
|
||||
struct adapter *adapter = arg;
|
||||
if_softc_ctx_t scctx = adapter->shared;
|
||||
struct em_rx_queue *que = &adapter->rx_queues[ri->iri_qsidx];
|
||||
struct rx_ring *rxr = &que->rxr;
|
||||
union e1000_rx_desc_extended *rxd;
|
||||
|
||||
u16 len;
|
||||
u32 pkt_info;
|
||||
u32 staterr = 0;
|
||||
bool eop;
|
||||
int i, cidx, vtag;
|
||||
|
||||
i = vtag = 0;
|
||||
cidx = ri->iri_cidx;
|
||||
|
||||
do {
|
||||
rxd = &rxr->rx_base[cidx];
|
||||
staterr = le32toh(rxd->wb.upper.status_error);
|
||||
pkt_info = le32toh(rxd->wb.lower.mrq);
|
||||
|
||||
/* Error Checking then decrement count */
|
||||
MPASS ((staterr & E1000_RXD_STAT_DD) != 0);
|
||||
|
||||
len = le16toh(rxd->wb.upper.length);
|
||||
ri->iri_len += len;
|
||||
|
||||
eop = (staterr & E1000_RXD_STAT_EOP) != 0;
|
||||
|
||||
/* Make sure bad packets are discarded */
|
||||
if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) {
|
||||
adapter->dropped_pkts++;
|
||||
return EBADMSG;
|
||||
}
|
||||
|
||||
ri->iri_frags[i].irf_flid = 0;
|
||||
ri->iri_frags[i].irf_idx = cidx;
|
||||
ri->iri_frags[i].irf_len = len;
|
||||
/* Zero out the receive descriptors status. */
|
||||
rxd->wb.upper.status_error &= htole32(~0xFF);
|
||||
|
||||
if (++cidx == scctx->isc_nrxd[0])
|
||||
cidx = 0;
|
||||
i++;
|
||||
} while (!eop);
|
||||
|
||||
/* XXX add a faster way to look this up */
|
||||
if (adapter->hw.mac.type >= e1000_82543)
|
||||
em_receive_checksum(staterr, ri);
|
||||
|
||||
if (staterr & E1000_RXD_STAT_VP) {
|
||||
vtag = le16toh(rxd->wb.upper.vlan);
|
||||
}
|
||||
|
||||
ri->iri_vtag = vtag;
|
||||
if (vtag)
|
||||
ri->iri_flags |= M_VLANTAG;
|
||||
|
||||
ri->iri_flowid = le32toh(rxd->wb.lower.hi_dword.rss);
|
||||
ri->iri_rsstype = em_determine_rsstype(pkt_info);
|
||||
|
||||
ri->iri_nfrags = i;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Verify that the hardware indicated that the checksum is valid.
|
||||
* Inform the stack about the status of checksum so that stack
|
||||
* doesn't spend time verifying the checksum.
|
||||
*
|
||||
*********************************************************************/
|
||||
static void
|
||||
lem_receive_checksum(int status, int errors, if_rxd_info_t ri)
|
||||
{
|
||||
/* Did it pass? */
|
||||
if (status & E1000_RXD_STAT_IPCS && !(errors & E1000_RXD_ERR_IPE))
|
||||
ri->iri_csum_flags = (CSUM_IP_CHECKED|CSUM_IP_VALID);
|
||||
|
||||
if (status & E1000_RXD_STAT_TCPCS) {
|
||||
/* Did it pass? */
|
||||
if (!(errors & E1000_RXD_ERR_TCPE)) {
|
||||
ri->iri_csum_flags |=
|
||||
(CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
|
||||
ri->iri_csum_data = htons(0xffff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
*
|
||||
* Parse the packet type to determine the appropriate hash
|
||||
*
|
||||
******************************************************************/
|
||||
static int
|
||||
em_determine_rsstype(u32 pkt_info)
|
||||
{
|
||||
switch (pkt_info & E1000_RXDADV_RSSTYPE_MASK) {
|
||||
case E1000_RXDADV_RSSTYPE_IPV4_TCP:
|
||||
return M_HASHTYPE_RSS_TCP_IPV4;
|
||||
case E1000_RXDADV_RSSTYPE_IPV4:
|
||||
return M_HASHTYPE_RSS_IPV4;
|
||||
case E1000_RXDADV_RSSTYPE_IPV6_TCP:
|
||||
return M_HASHTYPE_RSS_TCP_IPV6;
|
||||
case E1000_RXDADV_RSSTYPE_IPV6_EX:
|
||||
return M_HASHTYPE_RSS_IPV6_EX;
|
||||
case E1000_RXDADV_RSSTYPE_IPV6:
|
||||
return M_HASHTYPE_RSS_IPV6;
|
||||
case E1000_RXDADV_RSSTYPE_IPV6_TCP_EX:
|
||||
return M_HASHTYPE_RSS_TCP_IPV6_EX;
|
||||
default:
|
||||
return M_HASHTYPE_OPAQUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
em_receive_checksum(uint32_t status, if_rxd_info_t ri)
|
||||
{
|
||||
ri->iri_csum_flags = 0;
|
||||
|
||||
/* Ignore Checksum bit is set */
|
||||
if (status & E1000_RXD_STAT_IXSM)
|
||||
return;
|
||||
|
||||
/* If the IP checksum exists and there is no IP Checksum error */
|
||||
if ((status & (E1000_RXD_STAT_IPCS | E1000_RXDEXT_STATERR_IPE)) ==
|
||||
E1000_RXD_STAT_IPCS) {
|
||||
ri->iri_csum_flags = (CSUM_IP_CHECKED | CSUM_IP_VALID);
|
||||
}
|
||||
|
||||
/* TCP or UDP checksum */
|
||||
if ((status & (E1000_RXD_STAT_TCPCS | E1000_RXDEXT_STATERR_TCPE)) ==
|
||||
E1000_RXD_STAT_TCPCS) {
|
||||
ri->iri_csum_flags |= (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
|
||||
ri->iri_csum_data = htons(0xffff);
|
||||
}
|
||||
if (status & E1000_RXD_STAT_UDPCS) {
|
||||
ri->iri_csum_flags |= (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
|
||||
ri->iri_csum_data = htons(0xffff);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,36 +1,91 @@
|
||||
/******************************************************************************
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2016 Nicole Graziano <nicole@nextbsd.org>
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
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.
|
||||
/*$FreeBSD: releng/12.0/sys/dev/e1000/if_em.h 339267 2018-10-09 20:16:19Z shurd $*/
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
#ifdef HAVE_KERNEL_OPTION_HEADERS
|
||||
#include "opt_device_polling.h"
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#ifdef DDB
|
||||
#include <sys/types.h>
|
||||
#include <ddb/ddb.h>
|
||||
#endif
|
||||
#if __FreeBSD_version >= 800000
|
||||
#include <sys/buf_ring.h>
|
||||
#endif
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/smp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/eventhandler.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/iflib.h>
|
||||
|
||||
#include <net/if_types.h>
|
||||
#include <net/if_vlan_var.h>
|
||||
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#include <machine/in_cksum.h>
|
||||
#include <dev/led/led.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
|
||||
#include "e1000_api.h"
|
||||
#include "e1000_82571.h"
|
||||
#include "ifdi_if.h"
|
||||
|
||||
|
||||
#ifndef _EM_H_DEFINED_
|
||||
@@ -40,10 +95,10 @@
|
||||
/* Tunables */
|
||||
|
||||
/*
|
||||
* EM_TXD: Maximum number of Transmit Descriptors
|
||||
* EM_MAX_TXD: Maximum number of Transmit Descriptors
|
||||
* Valid Range: 80-256 for 82542 and 82543-based adapters
|
||||
* 80-4096 for others
|
||||
* Default Value: 256
|
||||
* Default Value: 1024
|
||||
* This value is the number of transmit descriptors allocated by the driver.
|
||||
* Increasing this value allows the driver to queue more transmits. Each
|
||||
* descriptor is 16 bytes.
|
||||
@@ -51,19 +106,17 @@
|
||||
* desscriptors should meet the following condition.
|
||||
* (num_tx_desc * sizeof(struct e1000_tx_desc)) % 128 == 0
|
||||
*/
|
||||
#define EM_MIN_TXD 80
|
||||
#define EM_MIN_TXD 128
|
||||
#define EM_MAX_TXD 4096
|
||||
#ifdef EM_MULTIQUEUE
|
||||
#define EM_DEFAULT_TXD 4096
|
||||
#else
|
||||
#define EM_DEFAULT_TXD 1024
|
||||
#endif
|
||||
#define EM_DEFAULT_TXD 1024
|
||||
#define EM_DEFAULT_MULTI_TXD 4096
|
||||
#define IGB_MAX_TXD 4096
|
||||
|
||||
/*
|
||||
* EM_RXD - Maximum number of receive Descriptors
|
||||
* EM_MAX_RXD - Maximum number of receive Descriptors
|
||||
* Valid Range: 80-256 for 82542 and 82543-based adapters
|
||||
* 80-4096 for others
|
||||
* Default Value: 256
|
||||
* Default Value: 1024
|
||||
* This value is the number of receive descriptors allocated by the driver.
|
||||
* Increasing this value allows the driver to buffer more incoming packets.
|
||||
* Each descriptor is 16 bytes. A receive buffer is also allocated for each
|
||||
@@ -72,13 +125,11 @@
|
||||
* desscriptors should meet the following condition.
|
||||
* (num_tx_desc * sizeof(struct e1000_tx_desc)) % 128 == 0
|
||||
*/
|
||||
#define EM_MIN_RXD 80
|
||||
#define EM_MIN_RXD 128
|
||||
#define EM_MAX_RXD 4096
|
||||
#ifdef EM_MULTIQUEUE
|
||||
#define EM_DEFAULT_RXD 4096
|
||||
#else
|
||||
#define EM_DEFAULT_RXD 1024
|
||||
#endif
|
||||
#define EM_DEFAULT_RXD 1024
|
||||
#define EM_DEFAULT_MULTI_RXD 4096
|
||||
#define IGB_MAX_RXD 4096
|
||||
|
||||
/*
|
||||
* EM_TIDV - Transmit Interrupt Delay Value
|
||||
@@ -125,11 +176,7 @@
|
||||
* restoring the network connection. To eliminate the potential
|
||||
* for the hang ensure that EM_RDTR is set to 0.
|
||||
*/
|
||||
#ifdef EM_MULTIQUEUE
|
||||
#define EM_RDTR 64
|
||||
#else
|
||||
#define EM_RDTR 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Receive Interrupt Absolute Delay Timer (Not valid for 82542/82543/82544)
|
||||
@@ -142,22 +189,7 @@
|
||||
* along with EM_RDTR, may improve traffic throughput in specific network
|
||||
* conditions.
|
||||
*/
|
||||
#ifdef EM_MULTIQUEUE
|
||||
#define EM_RADV 128
|
||||
#else
|
||||
#define EM_RADV 64
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This parameter controls the max duration of transmit watchdog.
|
||||
*/
|
||||
#define EM_WATCHDOG (10 * hz)
|
||||
|
||||
/*
|
||||
* This parameter controls when the driver calls the routine to reclaim
|
||||
* transmit descriptors.
|
||||
*/
|
||||
#define EM_TX_CLEANUP_THRESHOLD (adapter->num_tx_desc / 8)
|
||||
|
||||
/*
|
||||
* This parameter controls whether or not autonegotation is enabled.
|
||||
@@ -189,7 +221,7 @@
|
||||
* Micellaneous constants
|
||||
*/
|
||||
#define EM_VENDOR_ID 0x8086
|
||||
#define EM_FLASH 0x0014
|
||||
#define EM_FLASH 0x0014
|
||||
|
||||
#define EM_JUMBO_PBA 0x00000028
|
||||
#define EM_DEFAULT_PBA 0x00000030
|
||||
@@ -204,6 +236,22 @@
|
||||
#define EM_EEPROM_APME 0x400;
|
||||
#define EM_82544_APME 0x0004;
|
||||
|
||||
|
||||
/* Support AutoMediaDetect for Marvell M88 PHY in i354 */
|
||||
#define IGB_MEDIA_RESET (1 << 0)
|
||||
|
||||
/* Define the starting Interrupt rate per Queue */
|
||||
#define IGB_INTS_PER_SEC 8000
|
||||
#define IGB_DEFAULT_ITR ((1000000/IGB_INTS_PER_SEC) << 2)
|
||||
|
||||
#define IGB_LINK_ITR 2000
|
||||
#define I210_LINK_DELAY 1000
|
||||
|
||||
#define IGB_TXPBSIZE 20408
|
||||
#define IGB_HDR_BUF 128
|
||||
#define IGB_PKTTYPE_MASK 0x0000FFF0
|
||||
#define IGB_DMCTLX_DCFLUSH_DIS 0x80000000 /* Disable DMA Coalesce Flush */
|
||||
|
||||
/*
|
||||
* Driver state logic for the detection of a hung state
|
||||
* in hardware. Set TX_HUNG whenever a TX packet is used
|
||||
@@ -221,6 +269,18 @@
|
||||
#define PCICFG_DESC_RING_STATUS 0xe4
|
||||
#define FLUSH_DESC_REQUIRED 0x100
|
||||
|
||||
|
||||
#define IGB_RX_PTHRESH ((hw->mac.type == e1000_i354) ? 12 : \
|
||||
((hw->mac.type <= e1000_82576) ? 16 : 8))
|
||||
#define IGB_RX_HTHRESH 8
|
||||
#define IGB_RX_WTHRESH ((hw->mac.type == e1000_82576 && \
|
||||
(adapter->intr_type == IFLIB_INTR_MSIX)) ? 1 : 4)
|
||||
|
||||
#define IGB_TX_PTHRESH ((hw->mac.type == e1000_i354) ? 20 : 8)
|
||||
#define IGB_TX_HTHRESH 1
|
||||
#define IGB_TX_WTHRESH ((hw->mac.type != e1000_82575 && \
|
||||
(adapter->intr_type == IFLIB_INTR_MSIX) ? 1 : 16)
|
||||
|
||||
/*
|
||||
* TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be
|
||||
* multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will
|
||||
@@ -242,7 +302,8 @@
|
||||
#define EM_BAR_TYPE(v) ((v) & EM_BAR_TYPE_MASK)
|
||||
#define EM_BAR_TYPE_MASK 0x00000001
|
||||
#define EM_BAR_TYPE_MMEM 0x00000000
|
||||
#define EM_BAR_TYPE_FLASH 0x0014
|
||||
#define EM_BAR_TYPE_IO 0x00000001
|
||||
#define EM_BAR_TYPE_FLASH 0x0014
|
||||
#define EM_BAR_MEM_TYPE(v) ((v) & EM_BAR_MEM_TYPE_MASK)
|
||||
#define EM_BAR_MEM_TYPE_MASK 0x00000006
|
||||
#define EM_BAR_MEM_TYPE_32BIT 0x00000000
|
||||
@@ -250,11 +311,9 @@
|
||||
#define EM_MSIX_BAR 3 /* On 82575 */
|
||||
|
||||
/* More backward compatibility */
|
||||
#ifndef __HAIKU__
|
||||
#if __FreeBSD_version < 900000
|
||||
#define SYSCTL_ADD_UQUAD SYSCTL_ADD_QUAD
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Defines for printing debug information */
|
||||
#define DEBUG_INIT 0
|
||||
@@ -273,13 +332,20 @@
|
||||
|
||||
#define EM_MAX_SCATTER 40
|
||||
#define EM_VFTA_SIZE 128
|
||||
#define EM_TSO_SIZE (65535 + sizeof(struct ether_vlan_header))
|
||||
#define EM_TSO_SIZE 65535
|
||||
#define EM_TSO_SEG_SIZE 4096 /* Max dma segment size */
|
||||
#define EM_MSIX_MASK 0x01F00000 /* For 82574 use */
|
||||
#define EM_MSIX_LINK 0x01000000 /* For 82574 use */
|
||||
#define ETH_ZLEN 60
|
||||
#define ETH_ADDR_LEN 6
|
||||
#define CSUM_OFFLOAD 7 /* Offload bits in mbuf flag */
|
||||
#define EM_CSUM_OFFLOAD (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP) /* Offload bits in mbuf flag */
|
||||
#define IGB_CSUM_OFFLOAD (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP | \
|
||||
CSUM_IP_SCTP | CSUM_IP6_UDP | CSUM_IP6_TCP | \
|
||||
CSUM_IP6_SCTP) /* Offload bits in mbuf flag */
|
||||
|
||||
|
||||
#define IGB_PKTTYPE_MASK 0x0000FFF0
|
||||
#define IGB_DMCTLX_DCFLUSH_DIS 0x80000000 /* Disable DMA Coalesce Flush */
|
||||
|
||||
/*
|
||||
* 82574 has a nonstandard address for EIAC
|
||||
@@ -297,19 +363,6 @@
|
||||
#define EM_NVM_MSIX_N_MASK (0x7 << EM_NVM_MSIX_N_SHIFT)
|
||||
#define EM_NVM_MSIX_N_SHIFT 7
|
||||
|
||||
/*
|
||||
* Bus dma allocation structure used by
|
||||
* e1000_dma_malloc and e1000_dma_free.
|
||||
*/
|
||||
struct em_dma_alloc {
|
||||
bus_addr_t dma_paddr;
|
||||
caddr_t dma_vaddr;
|
||||
bus_dma_tag_t dma_tag;
|
||||
bus_dmamap_t dma_map;
|
||||
bus_dma_segment_t dma_seg;
|
||||
int dma_nseg;
|
||||
};
|
||||
|
||||
struct adapter;
|
||||
|
||||
struct em_int_delay_info {
|
||||
@@ -323,35 +376,30 @@ struct em_int_delay_info {
|
||||
*/
|
||||
struct tx_ring {
|
||||
struct adapter *adapter;
|
||||
struct mtx tx_mtx;
|
||||
char mtx_name[16];
|
||||
u32 me;
|
||||
u32 msix;
|
||||
u32 ims;
|
||||
int busy;
|
||||
struct em_dma_alloc txdma;
|
||||
struct e1000_tx_desc *tx_base;
|
||||
struct task tx_task;
|
||||
struct taskqueue *tq;
|
||||
u32 next_avail_desc;
|
||||
u32 next_to_clean;
|
||||
struct em_txbuffer *tx_buffers;
|
||||
volatile u16 tx_avail;
|
||||
u32 tx_tso; /* last tx was tso */
|
||||
u16 last_hw_offload;
|
||||
u8 last_hw_ipcso;
|
||||
u8 last_hw_ipcss;
|
||||
u8 last_hw_tucso;
|
||||
u8 last_hw_tucss;
|
||||
#if __FreeBSD_version >= 800000
|
||||
struct buf_ring *br;
|
||||
#endif
|
||||
uint64_t tx_paddr;
|
||||
qidx_t *tx_rsq;
|
||||
bool tx_tso; /* last tx was tso */
|
||||
uint8_t me;
|
||||
qidx_t tx_rs_cidx;
|
||||
qidx_t tx_rs_pidx;
|
||||
qidx_t tx_cidx_processed;
|
||||
/* Interrupt resources */
|
||||
bus_dma_tag_t txtag;
|
||||
void *tag;
|
||||
struct resource *res;
|
||||
unsigned long tx_irq;
|
||||
unsigned long no_desc_avail;
|
||||
|
||||
/* Saved csum offloading context information */
|
||||
int csum_flags;
|
||||
int csum_lhlen;
|
||||
int csum_iphlen;
|
||||
|
||||
int csum_thlen;
|
||||
int csum_mss;
|
||||
int csum_pktlen;
|
||||
|
||||
uint32_t csum_txd_upper;
|
||||
uint32_t csum_txd_lower; /* last field */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -359,26 +407,15 @@ struct tx_ring {
|
||||
*/
|
||||
struct rx_ring {
|
||||
struct adapter *adapter;
|
||||
struct em_rx_queue *que;
|
||||
u32 me;
|
||||
u32 msix;
|
||||
u32 ims;
|
||||
struct mtx rx_mtx;
|
||||
char mtx_name[16];
|
||||
u32 payload;
|
||||
struct task rx_task;
|
||||
struct taskqueue *tq;
|
||||
union e1000_rx_desc_extended *rx_base;
|
||||
struct em_dma_alloc rxdma;
|
||||
u32 next_to_refresh;
|
||||
u32 next_to_check;
|
||||
struct em_rxbuffer *rx_buffers;
|
||||
struct mbuf *fmp;
|
||||
struct mbuf *lmp;
|
||||
uint64_t rx_paddr;
|
||||
|
||||
/* Interrupt resources */
|
||||
void *tag;
|
||||
struct resource *res;
|
||||
bus_dma_tag_t rxtag;
|
||||
bool discard;
|
||||
|
||||
/* Soft stats */
|
||||
@@ -388,63 +425,68 @@ struct rx_ring {
|
||||
unsigned long rx_bytes;
|
||||
};
|
||||
|
||||
struct em_tx_queue {
|
||||
struct adapter *adapter;
|
||||
u32 msix;
|
||||
u32 eims; /* This queue's EIMS bit */
|
||||
u32 me;
|
||||
struct tx_ring txr;
|
||||
};
|
||||
|
||||
struct em_rx_queue {
|
||||
struct adapter *adapter;
|
||||
u32 me;
|
||||
u32 msix;
|
||||
u32 eims;
|
||||
struct rx_ring rxr;
|
||||
u64 irqs;
|
||||
struct if_irq que_irq;
|
||||
};
|
||||
|
||||
/* Our adapter structure */
|
||||
struct adapter {
|
||||
if_t ifp;
|
||||
struct ifnet *ifp;
|
||||
struct e1000_hw hw;
|
||||
|
||||
if_softc_ctx_t shared;
|
||||
if_ctx_t ctx;
|
||||
#define tx_num_queues shared->isc_ntxqsets
|
||||
#define rx_num_queues shared->isc_nrxqsets
|
||||
#define intr_type shared->isc_intr
|
||||
/* FreeBSD operating-system-specific structures. */
|
||||
struct e1000_osdep osdep;
|
||||
struct device *dev;
|
||||
device_t dev;
|
||||
struct cdev *led_dev;
|
||||
|
||||
struct em_tx_queue *tx_queues;
|
||||
struct em_rx_queue *rx_queues;
|
||||
struct if_irq irq;
|
||||
|
||||
struct resource *memory;
|
||||
struct resource *flash;
|
||||
struct resource *msix_mem;
|
||||
int memrid;
|
||||
struct resource *ioport;
|
||||
int io_rid;
|
||||
|
||||
struct resource *res;
|
||||
void *tag;
|
||||
u32 linkvec;
|
||||
u32 ivars;
|
||||
|
||||
struct ifmedia media;
|
||||
struct callout timer;
|
||||
struct ifmedia *media;
|
||||
int msix;
|
||||
int if_flags;
|
||||
int max_frame_size;
|
||||
int min_frame_size;
|
||||
struct mtx core_mtx;
|
||||
int em_insert_vlan_header;
|
||||
u32 ims;
|
||||
bool in_detach;
|
||||
|
||||
u32 flags;
|
||||
/* Task for FAST handling */
|
||||
struct task link_task;
|
||||
struct task que_task;
|
||||
struct taskqueue *tq; /* private task queue */
|
||||
struct grouptask link_task;
|
||||
|
||||
eventhandler_tag vlan_attach;
|
||||
eventhandler_tag vlan_detach;
|
||||
|
||||
u16 num_vlans;
|
||||
u8 num_queues;
|
||||
|
||||
/*
|
||||
* Transmit rings:
|
||||
* Allocated at run time, an array of rings.
|
||||
*/
|
||||
struct tx_ring *tx_rings;
|
||||
int num_tx_desc;
|
||||
u16 num_vlans;
|
||||
u32 txd_cmd;
|
||||
|
||||
/*
|
||||
* Receive rings:
|
||||
* Allocated at run time, an array of rings.
|
||||
*/
|
||||
struct rx_ring *rx_rings;
|
||||
int num_rx_desc;
|
||||
u32 tx_process_limit;
|
||||
u32 rx_process_limit;
|
||||
u32 rx_mbuf_sz;
|
||||
|
||||
@@ -470,6 +512,11 @@ struct adapter {
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
u32 smartspeed;
|
||||
u32 dmac;
|
||||
int link_mask;
|
||||
|
||||
u64 que_mask;
|
||||
|
||||
|
||||
struct em_int_delay_info tx_int_delay;
|
||||
struct em_int_delay_info tx_abs_int_delay;
|
||||
@@ -487,6 +534,7 @@ struct adapter {
|
||||
unsigned long watchdog_events;
|
||||
|
||||
struct e1000_hw_stats stats;
|
||||
u16 vf_ifp;
|
||||
};
|
||||
|
||||
/********************************************************************************
|
||||
@@ -504,54 +552,7 @@ typedef struct _em_vendor_info_t {
|
||||
unsigned int index;
|
||||
} em_vendor_info_t;
|
||||
|
||||
struct em_txbuffer {
|
||||
int next_eop; /* Index of the desc to watch */
|
||||
struct mbuf *m_head;
|
||||
bus_dmamap_t map; /* bus_dma map for packet */
|
||||
};
|
||||
|
||||
struct em_rxbuffer {
|
||||
int next_eop; /* Index of the desc to watch */
|
||||
struct mbuf *m_head;
|
||||
bus_dmamap_t map; /* bus_dma map for packet */
|
||||
bus_addr_t paddr;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Find the number of unrefreshed RX descriptors
|
||||
*/
|
||||
static inline u16
|
||||
e1000_rx_unrefreshed(struct rx_ring *rxr)
|
||||
{
|
||||
struct adapter *adapter = rxr->adapter;
|
||||
|
||||
if (rxr->next_to_check > rxr->next_to_refresh)
|
||||
return (rxr->next_to_check - rxr->next_to_refresh - 1);
|
||||
else
|
||||
return ((adapter->num_rx_desc + rxr->next_to_check) -
|
||||
rxr->next_to_refresh - 1);
|
||||
}
|
||||
|
||||
#define EM_CORE_LOCK_INIT(_sc, _name) \
|
||||
mtx_init(&(_sc)->core_mtx, _name, "EM Core Lock", MTX_DEF)
|
||||
#define EM_TX_LOCK_INIT(_sc, _name) \
|
||||
mtx_init(&(_sc)->tx_mtx, _name, "EM TX Lock", MTX_DEF)
|
||||
#define EM_RX_LOCK_INIT(_sc, _name) \
|
||||
mtx_init(&(_sc)->rx_mtx, _name, "EM RX Lock", MTX_DEF)
|
||||
#define EM_CORE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->core_mtx)
|
||||
#define EM_TX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->tx_mtx)
|
||||
#define EM_RX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rx_mtx)
|
||||
#define EM_CORE_LOCK(_sc) mtx_lock(&(_sc)->core_mtx)
|
||||
#define EM_TX_LOCK(_sc) mtx_lock(&(_sc)->tx_mtx)
|
||||
#define EM_TX_TRYLOCK(_sc) mtx_trylock(&(_sc)->tx_mtx)
|
||||
#define EM_RX_LOCK(_sc) mtx_lock(&(_sc)->rx_mtx)
|
||||
#define EM_CORE_UNLOCK(_sc) mtx_unlock(&(_sc)->core_mtx)
|
||||
#define EM_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->tx_mtx)
|
||||
#define EM_RX_UNLOCK(_sc) mtx_unlock(&(_sc)->rx_mtx)
|
||||
#define EM_CORE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->core_mtx, MA_OWNED)
|
||||
#define EM_TX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->tx_mtx, MA_OWNED)
|
||||
#define EM_RX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->rx_mtx, MA_OWNED)
|
||||
void em_dump_rs(struct adapter *);
|
||||
|
||||
#define EM_RSSRK_SIZE 4
|
||||
#define EM_RSSRK_VAL(key, i) (key[(i) * EM_RSSRK_SIZE] | \
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,638 +0,0 @@
|
||||
/******************************************************************************
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
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.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
|
||||
#ifndef _IF_IGB_H_
|
||||
#define _IF_IGB_H_
|
||||
|
||||
#ifdef ALTQ
|
||||
#define IGB_LEGACY_TX
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#ifndef IGB_LEGACY_TX
|
||||
#include <sys/buf_ring.h>
|
||||
#endif
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/eventhandler.h>
|
||||
#include <sys/pcpu.h>
|
||||
#include <sys/smp.h>
|
||||
#include <machine/smp.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#ifdef RSS
|
||||
#include <net/rss_config.h>
|
||||
#include <netinet/in_rss.h>
|
||||
#endif
|
||||
|
||||
#include <net/if_types.h>
|
||||
#include <net/if_vlan_var.h>
|
||||
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/tcp.h>
|
||||
#ifndef __HAIKU__
|
||||
#include <netinet/tcp_lro.h>
|
||||
#endif
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#include <machine/in_cksum.h>
|
||||
#include <dev/led/led.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
|
||||
#include "e1000_api.h"
|
||||
#include "e1000_82575.h"
|
||||
|
||||
/* Tunables */
|
||||
/*
|
||||
* IGB_TXD: Maximum number of Transmit Descriptors
|
||||
*
|
||||
* This value is the number of transmit descriptors allocated by the driver.
|
||||
* Increasing this value allows the driver to queue more transmits. Each
|
||||
* descriptor is 16 bytes.
|
||||
* Since TDLEN should be multiple of 128bytes, the number of transmit
|
||||
* desscriptors should meet the following condition.
|
||||
* (num_tx_desc * sizeof(struct e1000_tx_desc)) % 128 == 0
|
||||
*/
|
||||
#define IGB_MIN_TXD 256
|
||||
#define IGB_DEFAULT_TXD 1024
|
||||
#define IGB_MAX_TXD 4096
|
||||
|
||||
/*
|
||||
* IGB_RXD: Maximum number of Receive Descriptors
|
||||
*
|
||||
* This value is the number of receive descriptors allocated by the driver.
|
||||
* Increasing this value allows the driver to buffer more incoming packets.
|
||||
* Each descriptor is 16 bytes. A receive buffer is also allocated for each
|
||||
* descriptor. The maximum MTU size is 16110.
|
||||
* Since TDLEN should be multiple of 128bytes, the number of transmit
|
||||
* desscriptors should meet the following condition.
|
||||
* (num_tx_desc * sizeof(struct e1000_tx_desc)) % 128 == 0
|
||||
*/
|
||||
#define IGB_MIN_RXD 256
|
||||
#define IGB_DEFAULT_RXD 1024
|
||||
#define IGB_MAX_RXD 4096
|
||||
|
||||
/*
|
||||
* IGB_TIDV - Transmit Interrupt Delay Value
|
||||
* Valid Range: 0-65535 (0=off)
|
||||
* Default Value: 64
|
||||
* This value delays the generation of transmit interrupts in units of
|
||||
* 1.024 microseconds. Transmit interrupt reduction can improve CPU
|
||||
* efficiency if properly tuned for specific network traffic. If the
|
||||
* system is reporting dropped transmits, this value may be set too high
|
||||
* causing the driver to run out of available transmit descriptors.
|
||||
*/
|
||||
#define IGB_TIDV 64
|
||||
|
||||
/*
|
||||
* IGB_TADV - Transmit Absolute Interrupt Delay Value
|
||||
* Valid Range: 0-65535 (0=off)
|
||||
* Default Value: 64
|
||||
* This value, in units of 1.024 microseconds, limits the delay in which a
|
||||
* transmit interrupt is generated. Useful only if IGB_TIDV is non-zero,
|
||||
* this value ensures that an interrupt is generated after the initial
|
||||
* packet is sent on the wire within the set amount of time. Proper tuning,
|
||||
* along with IGB_TIDV, may improve traffic throughput in specific
|
||||
* network conditions.
|
||||
*/
|
||||
#define IGB_TADV 64
|
||||
|
||||
/*
|
||||
* IGB_RDTR - Receive Interrupt Delay Timer (Packet Timer)
|
||||
* Valid Range: 0-65535 (0=off)
|
||||
* Default Value: 0
|
||||
* This value delays the generation of receive interrupts in units of 1.024
|
||||
* microseconds. Receive interrupt reduction can improve CPU efficiency if
|
||||
* properly tuned for specific network traffic. Increasing this value adds
|
||||
* extra latency to frame reception and can end up decreasing the throughput
|
||||
* of TCP traffic. If the system is reporting dropped receives, this value
|
||||
* may be set too high, causing the driver to run out of available receive
|
||||
* descriptors.
|
||||
*
|
||||
* CAUTION: When setting IGB_RDTR to a value other than 0, adapters
|
||||
* may hang (stop transmitting) under certain network conditions.
|
||||
* If this occurs a WATCHDOG message is logged in the system
|
||||
* event log. In addition, the controller is automatically reset,
|
||||
* restoring the network connection. To eliminate the potential
|
||||
* for the hang ensure that IGB_RDTR is set to 0.
|
||||
*/
|
||||
#define IGB_RDTR 0
|
||||
|
||||
/*
|
||||
* Receive Interrupt Absolute Delay Timer (Not valid for 82542/82543/82544)
|
||||
* Valid Range: 0-65535 (0=off)
|
||||
* Default Value: 64
|
||||
* This value, in units of 1.024 microseconds, limits the delay in which a
|
||||
* receive interrupt is generated. Useful only if IGB_RDTR is non-zero,
|
||||
* this value ensures that an interrupt is generated after the initial
|
||||
* packet is received within the set amount of time. Proper tuning,
|
||||
* along with IGB_RDTR, may improve traffic throughput in specific network
|
||||
* conditions.
|
||||
*/
|
||||
#define IGB_RADV 64
|
||||
|
||||
/*
|
||||
* This parameter controls the duration of transmit watchdog timer.
|
||||
*/
|
||||
#define IGB_WATCHDOG (10 * hz)
|
||||
|
||||
/*
|
||||
* This parameter controls when the driver calls the routine to reclaim
|
||||
* transmit descriptors. Cleaning earlier seems a win.
|
||||
*/
|
||||
#define IGB_TX_CLEANUP_THRESHOLD (adapter->num_tx_desc / 2)
|
||||
|
||||
/*
|
||||
* This parameter controls whether or not autonegotation is enabled.
|
||||
* 0 - Disable autonegotiation
|
||||
* 1 - Enable autonegotiation
|
||||
*/
|
||||
#define DO_AUTO_NEG 1
|
||||
|
||||
/*
|
||||
* This parameter control whether or not the driver will wait for
|
||||
* autonegotiation to complete.
|
||||
* 1 - Wait for autonegotiation to complete
|
||||
* 0 - Don't wait for autonegotiation to complete
|
||||
*/
|
||||
#define WAIT_FOR_AUTO_NEG_DEFAULT 0
|
||||
|
||||
/* Tunables -- End */
|
||||
|
||||
#define AUTONEG_ADV_DEFAULT (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \
|
||||
ADVERTISE_100_HALF | ADVERTISE_100_FULL | \
|
||||
ADVERTISE_1000_FULL)
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
|
||||
/* PHY master/slave setting */
|
||||
#define IGB_MASTER_SLAVE e1000_ms_hw_default
|
||||
|
||||
/* Support AutoMediaDetect for Marvell M88 PHY in i354 */
|
||||
#define IGB_MEDIA_RESET (1 << 0)
|
||||
|
||||
/*
|
||||
* Micellaneous constants
|
||||
*/
|
||||
#define IGB_INTEL_VENDOR_ID 0x8086
|
||||
|
||||
#define IGB_JUMBO_PBA 0x00000028
|
||||
#define IGB_DEFAULT_PBA 0x00000030
|
||||
#define IGB_SMARTSPEED_DOWNSHIFT 3
|
||||
#define IGB_SMARTSPEED_MAX 15
|
||||
#define IGB_MAX_LOOP 10
|
||||
|
||||
#define IGB_RX_PTHRESH ((hw->mac.type == e1000_i354) ? 12 : \
|
||||
((hw->mac.type <= e1000_82576) ? 16 : 8))
|
||||
#define IGB_RX_HTHRESH 8
|
||||
#define IGB_RX_WTHRESH ((hw->mac.type == e1000_82576 && \
|
||||
adapter->msix_mem) ? 1 : 4)
|
||||
|
||||
#define IGB_TX_PTHRESH ((hw->mac.type == e1000_i354) ? 20 : 8)
|
||||
#define IGB_TX_HTHRESH 1
|
||||
#define IGB_TX_WTHRESH ((hw->mac.type != e1000_82575 && \
|
||||
adapter->msix_mem) ? 1 : 16)
|
||||
|
||||
#define MAX_NUM_MULTICAST_ADDRESSES 128
|
||||
#define PCI_ANY_ID (~0U)
|
||||
#define ETHER_ALIGN 2
|
||||
#define IGB_TX_BUFFER_SIZE ((uint32_t) 1514)
|
||||
#define IGB_FC_PAUSE_TIME 0x0680
|
||||
#define IGB_EEPROM_APME 0x400;
|
||||
/* Queue minimum free for use */
|
||||
#define IGB_QUEUE_THRESHOLD (adapter->num_tx_desc / 8)
|
||||
|
||||
/*
|
||||
* TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be
|
||||
* multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will
|
||||
* also optimize cache line size effect. H/W supports up to cache line size 128.
|
||||
*/
|
||||
#define IGB_DBA_ALIGN 128
|
||||
|
||||
#define SPEED_MODE_BIT (1<<21) /* On PCI-E MACs only */
|
||||
|
||||
/* PCI Config defines */
|
||||
#define IGB_MSIX_BAR 3
|
||||
|
||||
/* Defines for printing debug information */
|
||||
#define DEBUG_INIT 0
|
||||
#define DEBUG_IOCTL 0
|
||||
#define DEBUG_HW 0
|
||||
|
||||
#define INIT_DEBUGOUT(S) if (DEBUG_INIT) printf(S "\n")
|
||||
#define INIT_DEBUGOUT1(S, A) if (DEBUG_INIT) printf(S "\n", A)
|
||||
#define INIT_DEBUGOUT2(S, A, B) if (DEBUG_INIT) printf(S "\n", A, B)
|
||||
#define IOCTL_DEBUGOUT(S) if (DEBUG_IOCTL) printf(S "\n")
|
||||
#define IOCTL_DEBUGOUT1(S, A) if (DEBUG_IOCTL) printf(S "\n", A)
|
||||
#define IOCTL_DEBUGOUT2(S, A, B) if (DEBUG_IOCTL) printf(S "\n", A, B)
|
||||
#define HW_DEBUGOUT(S) if (DEBUG_HW) printf(S "\n")
|
||||
#define HW_DEBUGOUT1(S, A) if (DEBUG_HW) printf(S "\n", A)
|
||||
#define HW_DEBUGOUT2(S, A, B) if (DEBUG_HW) printf(S "\n", A, B)
|
||||
|
||||
#define IGB_MAX_SCATTER 40
|
||||
#define IGB_VFTA_SIZE 128
|
||||
#define IGB_BR_SIZE 4096 /* ring buf size */
|
||||
#define IGB_TSO_SIZE (65535 + sizeof(struct ether_vlan_header))
|
||||
#define IGB_TSO_SEG_SIZE 4096 /* Max dma segment size */
|
||||
#define IGB_TXPBSIZE 20408
|
||||
#define IGB_HDR_BUF 128
|
||||
#define IGB_PKTTYPE_MASK 0x0000FFF0
|
||||
#define IGB_DMCTLX_DCFLUSH_DIS 0x80000000 /* Disable DMA Coalesce Flush */
|
||||
#define ETH_ZLEN 60
|
||||
#define ETH_ADDR_LEN 6
|
||||
|
||||
/* Offload bits in mbuf flag */
|
||||
#if __FreeBSD_version >= 1000000
|
||||
#define CSUM_OFFLOAD_IPV4 (CSUM_IP|CSUM_IP_TCP|CSUM_IP_UDP|CSUM_IP_SCTP)
|
||||
#define CSUM_OFFLOAD_IPV6 (CSUM_IP6_TCP|CSUM_IP6_UDP|CSUM_IP6_SCTP)
|
||||
#define CSUM_OFFLOAD (CSUM_OFFLOAD_IPV4|CSUM_OFFLOAD_IPV6)
|
||||
#elif __FreeBSD_version >= 800000
|
||||
#define CSUM_OFFLOAD (CSUM_IP|CSUM_TCP|CSUM_UDP|CSUM_SCTP)
|
||||
#else
|
||||
#define CSUM_OFFLOAD (CSUM_IP|CSUM_TCP|CSUM_UDP)
|
||||
#endif
|
||||
|
||||
/* Define the starting Interrupt rate per Queue */
|
||||
#define IGB_INTS_PER_SEC 8000
|
||||
#define IGB_DEFAULT_ITR ((1000000/IGB_INTS_PER_SEC) << 2)
|
||||
|
||||
#define IGB_LINK_ITR 2000
|
||||
#define I210_LINK_DELAY 1000
|
||||
|
||||
/* Precision Time Sync (IEEE 1588) defines */
|
||||
#define ETHERTYPE_IEEE1588 0x88F7
|
||||
#define PICOSECS_PER_TICK 20833
|
||||
#define TSYNC_PORT 319 /* UDP port for the protocol */
|
||||
|
||||
/*
|
||||
* Bus dma allocation structure used by
|
||||
* e1000_dma_malloc and e1000_dma_free.
|
||||
*/
|
||||
struct igb_dma_alloc {
|
||||
bus_addr_t dma_paddr;
|
||||
caddr_t dma_vaddr;
|
||||
bus_dma_tag_t dma_tag;
|
||||
bus_dmamap_t dma_map;
|
||||
bus_dma_segment_t dma_seg;
|
||||
int dma_nseg;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Driver queue struct: this is the interrupt container
|
||||
** for the associated tx and rx ring.
|
||||
*/
|
||||
struct igb_queue {
|
||||
struct adapter *adapter;
|
||||
u32 msix; /* This queue's MSIX vector */
|
||||
u32 eims; /* This queue's EIMS bit */
|
||||
u32 eitr_setting;
|
||||
struct resource *res;
|
||||
void *tag;
|
||||
struct tx_ring *txr;
|
||||
struct rx_ring *rxr;
|
||||
struct task que_task;
|
||||
struct taskqueue *tq;
|
||||
u64 irqs;
|
||||
};
|
||||
|
||||
/*
|
||||
* The transmit ring, one per queue
|
||||
*/
|
||||
struct tx_ring {
|
||||
struct adapter *adapter;
|
||||
struct mtx tx_mtx;
|
||||
u32 me;
|
||||
int watchdog_time;
|
||||
union e1000_adv_tx_desc *tx_base;
|
||||
struct igb_tx_buf *tx_buffers;
|
||||
struct igb_dma_alloc txdma;
|
||||
volatile u16 tx_avail;
|
||||
u16 next_avail_desc;
|
||||
u16 next_to_clean;
|
||||
u16 num_desc;
|
||||
enum {
|
||||
IGB_QUEUE_IDLE = 1,
|
||||
IGB_QUEUE_WORKING = 2,
|
||||
IGB_QUEUE_HUNG = 4,
|
||||
IGB_QUEUE_DEPLETED = 8,
|
||||
} queue_status;
|
||||
u32 txd_cmd;
|
||||
bus_dma_tag_t txtag;
|
||||
char mtx_name[16];
|
||||
#ifndef IGB_LEGACY_TX
|
||||
struct buf_ring *br;
|
||||
struct task txq_task;
|
||||
#endif
|
||||
u32 bytes; /* used for AIM */
|
||||
u32 packets;
|
||||
/* Soft Stats */
|
||||
unsigned long tso_tx;
|
||||
unsigned long no_tx_map_avail;
|
||||
unsigned long no_tx_dma_setup;
|
||||
u64 no_desc_avail;
|
||||
u64 total_packets;
|
||||
};
|
||||
|
||||
/*
|
||||
* Receive ring: one per queue
|
||||
*/
|
||||
struct rx_ring {
|
||||
struct adapter *adapter;
|
||||
u32 me;
|
||||
struct igb_dma_alloc rxdma;
|
||||
union e1000_adv_rx_desc *rx_base;
|
||||
#ifndef __HAIKU__
|
||||
struct lro_ctrl lro;
|
||||
#endif
|
||||
bool lro_enabled;
|
||||
bool hdr_split;
|
||||
struct mtx rx_mtx;
|
||||
char mtx_name[16];
|
||||
u32 next_to_refresh;
|
||||
u32 next_to_check;
|
||||
struct igb_rx_buf *rx_buffers;
|
||||
bus_dma_tag_t htag; /* dma tag for rx head */
|
||||
bus_dma_tag_t ptag; /* dma tag for rx packet */
|
||||
/*
|
||||
* First/last mbuf pointers, for
|
||||
* collecting multisegment RX packets.
|
||||
*/
|
||||
struct mbuf *fmp;
|
||||
struct mbuf *lmp;
|
||||
|
||||
u32 bytes;
|
||||
u32 packets;
|
||||
int rdt;
|
||||
int rdh;
|
||||
|
||||
/* Soft stats */
|
||||
u64 rx_split_packets;
|
||||
u64 rx_discarded;
|
||||
u64 rx_packets;
|
||||
u64 rx_bytes;
|
||||
};
|
||||
|
||||
struct adapter {
|
||||
struct ifnet *ifp;
|
||||
struct e1000_hw hw;
|
||||
|
||||
struct e1000_osdep osdep;
|
||||
struct device *dev;
|
||||
struct cdev *led_dev;
|
||||
|
||||
struct resource *pci_mem;
|
||||
struct resource *msix_mem;
|
||||
int memrid;
|
||||
|
||||
/*
|
||||
* Interrupt resources: this set is
|
||||
* either used for legacy, or for Link
|
||||
* when doing MSIX
|
||||
*/
|
||||
void *tag;
|
||||
struct resource *res;
|
||||
|
||||
struct ifmedia media;
|
||||
struct callout timer;
|
||||
int msix;
|
||||
int if_flags;
|
||||
int pause_frames;
|
||||
|
||||
struct mtx core_mtx;
|
||||
|
||||
eventhandler_tag vlan_attach;
|
||||
eventhandler_tag vlan_detach;
|
||||
|
||||
u16 num_vlans;
|
||||
u16 num_queues;
|
||||
|
||||
/*
|
||||
** Shadow VFTA table, this is needed because
|
||||
** the real vlan filter table gets cleared during
|
||||
** a soft reset and the driver needs to be able
|
||||
** to repopulate it.
|
||||
*/
|
||||
u32 shadow_vfta[IGB_VFTA_SIZE];
|
||||
|
||||
/* Info about the interface */
|
||||
u32 optics;
|
||||
u32 fc; /* local flow ctrl setting */
|
||||
int advertise; /* link speeds */
|
||||
bool link_active;
|
||||
u16 max_frame_size;
|
||||
u16 num_segs;
|
||||
u16 link_speed;
|
||||
bool link_up;
|
||||
u32 linkvec;
|
||||
u16 link_duplex;
|
||||
u32 dmac;
|
||||
int link_mask;
|
||||
|
||||
/* Flags */
|
||||
u32 flags;
|
||||
|
||||
/* Mbuf cluster size */
|
||||
u32 rx_mbuf_sz;
|
||||
|
||||
/* Support for pluggable optics */
|
||||
bool sfp_probe;
|
||||
struct task link_task; /* Link tasklet */
|
||||
struct task mod_task; /* SFP tasklet */
|
||||
struct task msf_task; /* Multispeed Fiber */
|
||||
struct taskqueue *tq;
|
||||
|
||||
/*
|
||||
** Queues:
|
||||
** This is the irq holder, it has
|
||||
** and RX/TX pair or rings associated
|
||||
** with it.
|
||||
*/
|
||||
struct igb_queue *queues;
|
||||
|
||||
/*
|
||||
* Transmit rings:
|
||||
* Allocated at run time, an array of rings.
|
||||
*/
|
||||
struct tx_ring *tx_rings;
|
||||
u32 num_tx_desc;
|
||||
|
||||
/*
|
||||
* Receive rings:
|
||||
* Allocated at run time, an array of rings.
|
||||
*/
|
||||
struct rx_ring *rx_rings;
|
||||
u64 que_mask;
|
||||
u32 num_rx_desc;
|
||||
|
||||
/* Multicast array memory */
|
||||
u8 *mta;
|
||||
|
||||
/* Misc stats maintained by the driver */
|
||||
unsigned long device_control;
|
||||
unsigned long dropped_pkts;
|
||||
unsigned long eint_mask;
|
||||
unsigned long int_mask;
|
||||
unsigned long link_irq;
|
||||
unsigned long mbuf_defrag_failed;
|
||||
unsigned long no_tx_dma_setup;
|
||||
unsigned long packet_buf_alloc_rx;
|
||||
unsigned long packet_buf_alloc_tx;
|
||||
unsigned long rx_control;
|
||||
unsigned long rx_overruns;
|
||||
unsigned long watchdog_events;
|
||||
|
||||
/* Used in pf and vf */
|
||||
void *stats;
|
||||
|
||||
int enable_aim;
|
||||
int has_manage;
|
||||
int wol;
|
||||
int rx_process_limit;
|
||||
int tx_process_limit;
|
||||
u16 vf_ifp; /* a VF interface */
|
||||
bool in_detach; /* Used only in igb_ioctl */
|
||||
|
||||
};
|
||||
|
||||
/* ******************************************************************************
|
||||
* vendor_info_array
|
||||
*
|
||||
* This array contains the list of Subvendor/Subdevice IDs on which the driver
|
||||
* should load.
|
||||
*
|
||||
* ******************************************************************************/
|
||||
typedef struct _igb_vendor_info_t {
|
||||
unsigned int vendor_id;
|
||||
unsigned int device_id;
|
||||
unsigned int subvendor_id;
|
||||
unsigned int subdevice_id;
|
||||
unsigned int index;
|
||||
} igb_vendor_info_t;
|
||||
|
||||
struct igb_tx_buf {
|
||||
union e1000_adv_tx_desc *eop;
|
||||
struct mbuf *m_head;
|
||||
bus_dmamap_t map;
|
||||
};
|
||||
|
||||
struct igb_rx_buf {
|
||||
struct mbuf *m_head;
|
||||
struct mbuf *m_pack;
|
||||
bus_dmamap_t hmap; /* bus_dma map for header */
|
||||
bus_dmamap_t pmap; /* bus_dma map for packet */
|
||||
};
|
||||
|
||||
/*
|
||||
** Find the number of unrefreshed RX descriptors
|
||||
*/
|
||||
static inline u16
|
||||
igb_rx_unrefreshed(struct rx_ring *rxr)
|
||||
{
|
||||
struct adapter *adapter = rxr->adapter;
|
||||
|
||||
if (rxr->next_to_check > rxr->next_to_refresh)
|
||||
return (rxr->next_to_check - rxr->next_to_refresh - 1);
|
||||
else
|
||||
return ((adapter->num_rx_desc + rxr->next_to_check) -
|
||||
rxr->next_to_refresh - 1);
|
||||
}
|
||||
|
||||
#define IGB_CORE_LOCK_INIT(_sc, _name) \
|
||||
mtx_init(&(_sc)->core_mtx, _name, "IGB Core Lock", MTX_DEF)
|
||||
#define IGB_CORE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->core_mtx)
|
||||
#define IGB_CORE_LOCK(_sc) mtx_lock(&(_sc)->core_mtx)
|
||||
#define IGB_CORE_UNLOCK(_sc) mtx_unlock(&(_sc)->core_mtx)
|
||||
#define IGB_CORE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->core_mtx, MA_OWNED)
|
||||
|
||||
#define IGB_TX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->tx_mtx)
|
||||
#define IGB_TX_LOCK(_sc) mtx_lock(&(_sc)->tx_mtx)
|
||||
#define IGB_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->tx_mtx)
|
||||
#define IGB_TX_TRYLOCK(_sc) mtx_trylock(&(_sc)->tx_mtx)
|
||||
#define IGB_TX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->tx_mtx, MA_OWNED)
|
||||
|
||||
#define IGB_RX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rx_mtx)
|
||||
#define IGB_RX_LOCK(_sc) mtx_lock(&(_sc)->rx_mtx)
|
||||
#define IGB_RX_UNLOCK(_sc) mtx_unlock(&(_sc)->rx_mtx)
|
||||
#define IGB_RX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->rx_mtx, MA_OWNED)
|
||||
|
||||
#define UPDATE_VF_REG(reg, last, cur) \
|
||||
{ \
|
||||
u32 new = E1000_READ_REG(hw, reg); \
|
||||
if (new < last) \
|
||||
cur += 0x100000000LL; \
|
||||
last = new; \
|
||||
cur &= 0xFFFFFFFF00000000LL; \
|
||||
cur |= new; \
|
||||
}
|
||||
|
||||
#if __FreeBSD_version >= 800000 && __FreeBSD_version < 800504
|
||||
static __inline int
|
||||
drbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br)
|
||||
{
|
||||
#ifdef ALTQ
|
||||
if (ALTQ_IS_ENABLED(&ifp->if_snd))
|
||||
return (1);
|
||||
#endif
|
||||
return (!buf_ring_empty(br));
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _IF_IGB_H_ */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,521 +0,0 @@
|
||||
/******************************************************************************
|
||||
|
||||
Copyright (c) 2001-2015, Intel Corporation
|
||||
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.
|
||||
|
||||
******************************************************************************/
|
||||
/*$FreeBSD$*/
|
||||
|
||||
|
||||
#ifndef _LEM_H_DEFINED_
|
||||
#define _LEM_H_DEFINED_
|
||||
|
||||
|
||||
/* Tunables */
|
||||
|
||||
/*
|
||||
* EM_TXD: Maximum number of Transmit Descriptors
|
||||
* Valid Range: 80-256 for 82542 and 82543-based adapters
|
||||
* 80-4096 for others
|
||||
* Default Value: 256
|
||||
* This value is the number of transmit descriptors allocated by the driver.
|
||||
* Increasing this value allows the driver to queue more transmits. Each
|
||||
* descriptor is 16 bytes.
|
||||
* Since TDLEN should be multiple of 128bytes, the number of transmit
|
||||
* desscriptors should meet the following condition.
|
||||
* (num_tx_desc * sizeof(struct e1000_tx_desc)) % 128 == 0
|
||||
*/
|
||||
#define EM_MIN_TXD 80
|
||||
#define EM_MAX_TXD_82543 256
|
||||
#define EM_MAX_TXD 4096
|
||||
#define EM_DEFAULT_TXD EM_MAX_TXD_82543
|
||||
|
||||
/*
|
||||
* EM_RXD - Maximum number of receive Descriptors
|
||||
* Valid Range: 80-256 for 82542 and 82543-based adapters
|
||||
* 80-4096 for others
|
||||
* Default Value: 256
|
||||
* This value is the number of receive descriptors allocated by the driver.
|
||||
* Increasing this value allows the driver to buffer more incoming packets.
|
||||
* Each descriptor is 16 bytes. A receive buffer is also allocated for each
|
||||
* descriptor. The maximum MTU size is 16110.
|
||||
* Since TDLEN should be multiple of 128bytes, the number of transmit
|
||||
* desscriptors should meet the following condition.
|
||||
* (num_tx_desc * sizeof(struct e1000_tx_desc)) % 128 == 0
|
||||
*/
|
||||
#define EM_MIN_RXD 80
|
||||
#define EM_MAX_RXD_82543 256
|
||||
#define EM_MAX_RXD 4096
|
||||
#define EM_DEFAULT_RXD EM_MAX_RXD_82543
|
||||
|
||||
/*
|
||||
* EM_TIDV - Transmit Interrupt Delay Value
|
||||
* Valid Range: 0-65535 (0=off)
|
||||
* Default Value: 64
|
||||
* This value delays the generation of transmit interrupts in units of
|
||||
* 1.024 microseconds. Transmit interrupt reduction can improve CPU
|
||||
* efficiency if properly tuned for specific network traffic. If the
|
||||
* system is reporting dropped transmits, this value may be set too high
|
||||
* causing the driver to run out of available transmit descriptors.
|
||||
*/
|
||||
#define EM_TIDV 64
|
||||
|
||||
/*
|
||||
* EM_TADV - Transmit Absolute Interrupt Delay Value
|
||||
* (Not valid for 82542/82543/82544)
|
||||
* Valid Range: 0-65535 (0=off)
|
||||
* Default Value: 64
|
||||
* This value, in units of 1.024 microseconds, limits the delay in which a
|
||||
* transmit interrupt is generated. Useful only if EM_TIDV is non-zero,
|
||||
* this value ensures that an interrupt is generated after the initial
|
||||
* packet is sent on the wire within the set amount of time. Proper tuning,
|
||||
* along with EM_TIDV, may improve traffic throughput in specific
|
||||
* network conditions.
|
||||
*/
|
||||
#define EM_TADV 64
|
||||
|
||||
/*
|
||||
* EM_RDTR - Receive Interrupt Delay Timer (Packet Timer)
|
||||
* Valid Range: 0-65535 (0=off)
|
||||
* Default Value: 0
|
||||
* This value delays the generation of receive interrupts in units of 1.024
|
||||
* microseconds. Receive interrupt reduction can improve CPU efficiency if
|
||||
* properly tuned for specific network traffic. Increasing this value adds
|
||||
* extra latency to frame reception and can end up decreasing the throughput
|
||||
* of TCP traffic. If the system is reporting dropped receives, this value
|
||||
* may be set too high, causing the driver to run out of available receive
|
||||
* descriptors.
|
||||
*
|
||||
* CAUTION: When setting EM_RDTR to a value other than 0, adapters
|
||||
* may hang (stop transmitting) under certain network conditions.
|
||||
* If this occurs a WATCHDOG message is logged in the system
|
||||
* event log. In addition, the controller is automatically reset,
|
||||
* restoring the network connection. To eliminate the potential
|
||||
* for the hang ensure that EM_RDTR is set to 0.
|
||||
*/
|
||||
#define EM_RDTR 0
|
||||
|
||||
/*
|
||||
* Receive Interrupt Absolute Delay Timer (Not valid for 82542/82543/82544)
|
||||
* Valid Range: 0-65535 (0=off)
|
||||
* Default Value: 64
|
||||
* This value, in units of 1.024 microseconds, limits the delay in which a
|
||||
* receive interrupt is generated. Useful only if EM_RDTR is non-zero,
|
||||
* this value ensures that an interrupt is generated after the initial
|
||||
* packet is received within the set amount of time. Proper tuning,
|
||||
* along with EM_RDTR, may improve traffic throughput in specific network
|
||||
* conditions.
|
||||
*/
|
||||
#define EM_RADV 64
|
||||
|
||||
/*
|
||||
* This parameter controls the max duration of transmit watchdog.
|
||||
*/
|
||||
#define EM_WATCHDOG (10 * hz)
|
||||
|
||||
/*
|
||||
* This parameter controls when the driver calls the routine to reclaim
|
||||
* transmit descriptors.
|
||||
*/
|
||||
#define EM_TX_CLEANUP_THRESHOLD (adapter->num_tx_desc / 8)
|
||||
#define EM_TX_OP_THRESHOLD (adapter->num_tx_desc / 32)
|
||||
|
||||
/*
|
||||
* This parameter controls whether or not autonegotation is enabled.
|
||||
* 0 - Disable autonegotiation
|
||||
* 1 - Enable autonegotiation
|
||||
*/
|
||||
#define DO_AUTO_NEG 1
|
||||
|
||||
/*
|
||||
* This parameter control whether or not the driver will wait for
|
||||
* autonegotiation to complete.
|
||||
* 1 - Wait for autonegotiation to complete
|
||||
* 0 - Don't wait for autonegotiation to complete
|
||||
*/
|
||||
#define WAIT_FOR_AUTO_NEG_DEFAULT 0
|
||||
|
||||
/* Tunables -- End */
|
||||
|
||||
#define AUTONEG_ADV_DEFAULT (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \
|
||||
ADVERTISE_100_HALF | ADVERTISE_100_FULL | \
|
||||
ADVERTISE_1000_FULL)
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
|
||||
/* PHY master/slave setting */
|
||||
#define EM_MASTER_SLAVE e1000_ms_hw_default
|
||||
|
||||
/*
|
||||
* Micellaneous constants
|
||||
*/
|
||||
#define EM_VENDOR_ID 0x8086
|
||||
#define EM_FLASH 0x0014
|
||||
|
||||
#define EM_JUMBO_PBA 0x00000028
|
||||
#define EM_DEFAULT_PBA 0x00000030
|
||||
#define EM_SMARTSPEED_DOWNSHIFT 3
|
||||
#define EM_SMARTSPEED_MAX 15
|
||||
#define EM_MAX_LOOP 10
|
||||
|
||||
#define MAX_NUM_MULTICAST_ADDRESSES 128
|
||||
#define PCI_ANY_ID (~0U)
|
||||
#define ETHER_ALIGN 2
|
||||
#define EM_FC_PAUSE_TIME 0x0680
|
||||
#define EM_EEPROM_APME 0x400;
|
||||
#define EM_82544_APME 0x0004;
|
||||
|
||||
/* Code compatilbility between 6 and 7 */
|
||||
#ifndef ETHER_BPF_MTAP
|
||||
#define ETHER_BPF_MTAP BPF_MTAP
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be
|
||||
* multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will
|
||||
* also optimize cache line size effect. H/W supports up to cache line size 128.
|
||||
*/
|
||||
#define EM_DBA_ALIGN 128
|
||||
|
||||
#define SPEED_MODE_BIT (1<<21) /* On PCI-E MACs only */
|
||||
|
||||
/* PCI Config defines */
|
||||
#define EM_BAR_TYPE(v) ((v) & EM_BAR_TYPE_MASK)
|
||||
#define EM_BAR_TYPE_MASK 0x00000001
|
||||
#define EM_BAR_TYPE_MMEM 0x00000000
|
||||
#define EM_BAR_TYPE_IO 0x00000001
|
||||
#define EM_BAR_TYPE_FLASH 0x0014
|
||||
#define EM_BAR_MEM_TYPE(v) ((v) & EM_BAR_MEM_TYPE_MASK)
|
||||
#define EM_BAR_MEM_TYPE_MASK 0x00000006
|
||||
#define EM_BAR_MEM_TYPE_32BIT 0x00000000
|
||||
#define EM_BAR_MEM_TYPE_64BIT 0x00000004
|
||||
#define EM_MSIX_BAR 3 /* On 82575 */
|
||||
|
||||
#ifndef __HAIKU__
|
||||
#if __FreeBSD_version < 900000
|
||||
#define SYSCTL_ADD_UQUAD SYSCTL_ADD_QUAD
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Defines for printing debug information */
|
||||
#define DEBUG_INIT 0
|
||||
#define DEBUG_IOCTL 0
|
||||
#define DEBUG_HW 0
|
||||
|
||||
#define INIT_DEBUGOUT(S) if (DEBUG_INIT) printf(S "\n")
|
||||
#define INIT_DEBUGOUT1(S, A) if (DEBUG_INIT) printf(S "\n", A)
|
||||
#define INIT_DEBUGOUT2(S, A, B) if (DEBUG_INIT) printf(S "\n", A, B)
|
||||
#define IOCTL_DEBUGOUT(S) if (DEBUG_IOCTL) printf(S "\n")
|
||||
#define IOCTL_DEBUGOUT1(S, A) if (DEBUG_IOCTL) printf(S "\n", A)
|
||||
#define IOCTL_DEBUGOUT2(S, A, B) if (DEBUG_IOCTL) printf(S "\n", A, B)
|
||||
#define HW_DEBUGOUT(S) if (DEBUG_HW) printf(S "\n")
|
||||
#define HW_DEBUGOUT1(S, A) if (DEBUG_HW) printf(S "\n", A)
|
||||
#define HW_DEBUGOUT2(S, A, B) if (DEBUG_HW) printf(S "\n", A, B)
|
||||
|
||||
#define EM_MAX_SCATTER 40
|
||||
#define EM_VFTA_SIZE 128
|
||||
#define EM_MSIX_MASK 0x01F00000 /* For 82574 use */
|
||||
#define ETH_ZLEN 60
|
||||
#define ETH_ADDR_LEN 6
|
||||
#define CSUM_OFFLOAD 7 /* Offload bits in mbuf flag */
|
||||
|
||||
/*
|
||||
* 82574 has a nonstandard address for EIAC
|
||||
* and since its only used in MSIX, and in
|
||||
* the em driver only 82574 uses MSIX we can
|
||||
* solve it just using this define.
|
||||
*/
|
||||
#define EM_EIAC 0x000DC
|
||||
|
||||
/* Used in for 82547 10Mb Half workaround */
|
||||
#define EM_PBA_BYTES_SHIFT 0xA
|
||||
#define EM_TX_HEAD_ADDR_SHIFT 7
|
||||
#define EM_PBA_TX_MASK 0xFFFF0000
|
||||
#define EM_FIFO_HDR 0x10
|
||||
#define EM_82547_PKT_THRESH 0x3e0
|
||||
|
||||
/* Precision Time Sync (IEEE 1588) defines */
|
||||
#define ETHERTYPE_IEEE1588 0x88F7
|
||||
#define PICOSECS_PER_TICK 20833
|
||||
#define TSYNC_PORT 319 /* UDP port for the protocol */
|
||||
|
||||
#ifdef NIC_PARAVIRT
|
||||
#define E1000_PARA_SUBDEV 0x1101 /* special id */
|
||||
#define E1000_CSBAL 0x02830 /* csb phys. addr. low */
|
||||
#define E1000_CSBAH 0x02834 /* csb phys. addr. hi */
|
||||
#include <net/paravirt.h>
|
||||
#endif /* NIC_PARAVIRT */
|
||||
|
||||
/*
|
||||
* Bus dma allocation structure used by
|
||||
* e1000_dma_malloc and e1000_dma_free.
|
||||
*/
|
||||
struct em_dma_alloc {
|
||||
bus_addr_t dma_paddr;
|
||||
caddr_t dma_vaddr;
|
||||
bus_dma_tag_t dma_tag;
|
||||
bus_dmamap_t dma_map;
|
||||
bus_dma_segment_t dma_seg;
|
||||
int dma_nseg;
|
||||
};
|
||||
|
||||
struct adapter;
|
||||
|
||||
struct em_int_delay_info {
|
||||
struct adapter *adapter; /* Back-pointer to the adapter struct */
|
||||
int offset; /* Register offset to read/write */
|
||||
int value; /* Current value in usecs */
|
||||
};
|
||||
|
||||
/* Our adapter structure */
|
||||
struct adapter {
|
||||
if_t ifp;
|
||||
struct e1000_hw hw;
|
||||
|
||||
/* FreeBSD operating-system-specific structures. */
|
||||
struct e1000_osdep osdep;
|
||||
struct device *dev;
|
||||
struct cdev *led_dev;
|
||||
|
||||
struct resource *memory;
|
||||
struct resource *flash;
|
||||
struct resource *msix;
|
||||
|
||||
struct resource *ioport;
|
||||
int io_rid;
|
||||
|
||||
/* 82574 may use 3 int vectors */
|
||||
struct resource *res[3];
|
||||
void *tag[3];
|
||||
int rid[3];
|
||||
|
||||
struct ifmedia media;
|
||||
struct callout timer;
|
||||
struct callout tx_fifo_timer;
|
||||
bool watchdog_check;
|
||||
int watchdog_time;
|
||||
int msi;
|
||||
int if_flags;
|
||||
int max_frame_size;
|
||||
int min_frame_size;
|
||||
struct mtx core_mtx;
|
||||
struct mtx tx_mtx;
|
||||
struct mtx rx_mtx;
|
||||
int em_insert_vlan_header;
|
||||
|
||||
/* Task for FAST handling */
|
||||
struct task link_task;
|
||||
struct task rxtx_task;
|
||||
struct task rx_task;
|
||||
struct task tx_task;
|
||||
struct taskqueue *tq; /* private task queue */
|
||||
|
||||
eventhandler_tag vlan_attach;
|
||||
eventhandler_tag vlan_detach;
|
||||
u32 num_vlans;
|
||||
|
||||
/* Management and WOL features */
|
||||
u32 wol;
|
||||
bool has_manage;
|
||||
bool has_amt;
|
||||
|
||||
/* Multicast array memory */
|
||||
u8 *mta;
|
||||
|
||||
/*
|
||||
** Shadow VFTA table, this is needed because
|
||||
** the real vlan filter table gets cleared during
|
||||
** a soft reset and the driver needs to be able
|
||||
** to repopulate it.
|
||||
*/
|
||||
u32 shadow_vfta[EM_VFTA_SIZE];
|
||||
|
||||
/* Info about the interface */
|
||||
uint8_t link_active;
|
||||
uint16_t link_speed;
|
||||
uint16_t link_duplex;
|
||||
uint32_t smartspeed;
|
||||
uint32_t fc_setting;
|
||||
|
||||
struct em_int_delay_info tx_int_delay;
|
||||
struct em_int_delay_info tx_abs_int_delay;
|
||||
struct em_int_delay_info rx_int_delay;
|
||||
struct em_int_delay_info rx_abs_int_delay;
|
||||
struct em_int_delay_info tx_itr;
|
||||
|
||||
/*
|
||||
* Transmit definitions
|
||||
*
|
||||
* We have an array of num_tx_desc descriptors (handled
|
||||
* by the controller) paired with an array of tx_buffers
|
||||
* (at tx_buffer_area).
|
||||
* The index of the next available descriptor is next_avail_tx_desc.
|
||||
* The number of remaining tx_desc is num_tx_desc_avail.
|
||||
*/
|
||||
struct em_dma_alloc txdma; /* bus_dma glue for tx desc */
|
||||
struct e1000_tx_desc *tx_desc_base;
|
||||
uint32_t next_avail_tx_desc;
|
||||
uint32_t next_tx_to_clean;
|
||||
volatile uint16_t num_tx_desc_avail;
|
||||
uint16_t num_tx_desc;
|
||||
uint16_t last_hw_offload;
|
||||
uint32_t txd_cmd;
|
||||
struct em_buffer *tx_buffer_area;
|
||||
bus_dma_tag_t txtag; /* dma tag for tx */
|
||||
uint32_t tx_tso; /* last tx was tso */
|
||||
|
||||
/*
|
||||
* Receive definitions
|
||||
*
|
||||
* we have an array of num_rx_desc rx_desc (handled by the
|
||||
* controller), and paired with an array of rx_buffers
|
||||
* (at rx_buffer_area).
|
||||
* The next pair to check on receive is at offset next_rx_desc_to_check
|
||||
*/
|
||||
struct em_dma_alloc rxdma; /* bus_dma glue for rx desc */
|
||||
struct e1000_rx_desc *rx_desc_base;
|
||||
uint32_t next_rx_desc_to_check;
|
||||
uint32_t rx_buffer_len;
|
||||
uint16_t num_rx_desc;
|
||||
int rx_process_limit;
|
||||
struct em_buffer *rx_buffer_area;
|
||||
bus_dma_tag_t rxtag;
|
||||
bus_dmamap_t rx_sparemap;
|
||||
|
||||
/*
|
||||
* First/last mbuf pointers, for
|
||||
* collecting multisegment RX packets.
|
||||
*/
|
||||
struct mbuf *fmp;
|
||||
struct mbuf *lmp;
|
||||
|
||||
/* Misc stats maintained by the driver */
|
||||
unsigned long dropped_pkts;
|
||||
unsigned long link_irq;
|
||||
unsigned long mbuf_cluster_failed;
|
||||
unsigned long mbuf_defrag_failed;
|
||||
unsigned long no_tx_desc_avail1;
|
||||
unsigned long no_tx_desc_avail2;
|
||||
unsigned long no_tx_dma_setup;
|
||||
unsigned long no_tx_map_avail;
|
||||
unsigned long watchdog_events;
|
||||
unsigned long rx_irq;
|
||||
unsigned long rx_overruns;
|
||||
unsigned long tx_irq;
|
||||
|
||||
/* 82547 workaround */
|
||||
uint32_t tx_fifo_size;
|
||||
uint32_t tx_fifo_head;
|
||||
uint32_t tx_fifo_head_addr;
|
||||
uint64_t tx_fifo_reset_cnt;
|
||||
uint64_t tx_fifo_wrk_cnt;
|
||||
uint32_t tx_head_addr;
|
||||
|
||||
/* For 82544 PCIX Workaround */
|
||||
boolean_t pcix_82544;
|
||||
boolean_t in_detach;
|
||||
|
||||
#ifdef NIC_SEND_COMBINING
|
||||
/* 0 = idle; 1xxxx int-pending; 3xxxx int + d pending + tdt */
|
||||
#define MIT_PENDING_INT 0x10000 /* pending interrupt */
|
||||
#define MIT_PENDING_TDT 0x30000 /* both intr and tdt write are pending */
|
||||
uint32_t shadow_tdt;
|
||||
uint32_t sc_enable;
|
||||
#endif /* NIC_SEND_COMBINING */
|
||||
#ifdef BATCH_DISPATCH
|
||||
uint32_t batch_enable;
|
||||
#endif /* BATCH_DISPATCH */
|
||||
|
||||
#ifdef NIC_PARAVIRT
|
||||
struct em_dma_alloc csb_mem; /* phys address */
|
||||
struct paravirt_csb *csb; /* virtual addr */
|
||||
uint32_t rx_retries; /* optimize rx loop */
|
||||
uint32_t tdt_csb_count;// XXX stat
|
||||
uint32_t tdt_reg_count;// XXX stat
|
||||
uint32_t tdt_int_count;// XXX stat
|
||||
uint32_t guest_need_kick_count;// XXX stat
|
||||
#endif /* NIC_PARAVIRT */
|
||||
|
||||
struct e1000_hw_stats stats;
|
||||
};
|
||||
|
||||
/* ******************************************************************************
|
||||
* vendor_info_array
|
||||
*
|
||||
* This array contains the list of Subvendor/Subdevice IDs on which the driver
|
||||
* should load.
|
||||
*
|
||||
* ******************************************************************************/
|
||||
typedef struct _em_vendor_info_t {
|
||||
unsigned int vendor_id;
|
||||
unsigned int device_id;
|
||||
unsigned int subvendor_id;
|
||||
unsigned int subdevice_id;
|
||||
unsigned int index;
|
||||
} em_vendor_info_t;
|
||||
|
||||
struct em_buffer {
|
||||
int next_eop; /* Index of the desc to watch */
|
||||
struct mbuf *m_head;
|
||||
bus_dmamap_t map; /* bus_dma map for packet */
|
||||
};
|
||||
|
||||
/* For 82544 PCIX Workaround */
|
||||
typedef struct _ADDRESS_LENGTH_PAIR
|
||||
{
|
||||
uint64_t address;
|
||||
uint32_t length;
|
||||
} ADDRESS_LENGTH_PAIR, *PADDRESS_LENGTH_PAIR;
|
||||
|
||||
typedef struct _DESCRIPTOR_PAIR
|
||||
{
|
||||
ADDRESS_LENGTH_PAIR descriptor[4];
|
||||
uint32_t elements;
|
||||
} DESC_ARRAY, *PDESC_ARRAY;
|
||||
|
||||
#define EM_CORE_LOCK_INIT(_sc, _name) \
|
||||
mtx_init(&(_sc)->core_mtx, _name, "EM Core Lock", MTX_DEF)
|
||||
#define EM_TX_LOCK_INIT(_sc, _name) \
|
||||
mtx_init(&(_sc)->tx_mtx, _name, "EM TX Lock", MTX_DEF)
|
||||
#define EM_RX_LOCK_INIT(_sc, _name) \
|
||||
mtx_init(&(_sc)->rx_mtx, _name, "EM RX Lock", MTX_DEF)
|
||||
#define EM_CORE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->core_mtx)
|
||||
#define EM_TX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->tx_mtx)
|
||||
#define EM_RX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rx_mtx)
|
||||
#define EM_CORE_LOCK(_sc) mtx_lock(&(_sc)->core_mtx)
|
||||
#define EM_TX_LOCK(_sc) mtx_lock(&(_sc)->tx_mtx)
|
||||
#define EM_TX_TRYLOCK(_sc) mtx_trylock(&(_sc)->tx_mtx)
|
||||
#define EM_RX_LOCK(_sc) mtx_lock(&(_sc)->rx_mtx)
|
||||
#define EM_CORE_UNLOCK(_sc) mtx_unlock(&(_sc)->core_mtx)
|
||||
#define EM_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->tx_mtx)
|
||||
#define EM_RX_UNLOCK(_sc) mtx_unlock(&(_sc)->rx_mtx)
|
||||
#define EM_CORE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->core_mtx, MA_OWNED)
|
||||
#define EM_TX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->tx_mtx, MA_OWNED)
|
||||
|
||||
#endif /* _LEM_H_DEFINED_ */
|
||||
@@ -0,0 +1,587 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Matthew Macy <mmacy@mattmacy.io>
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
/* $FreeBSD: releng/12.0/sys/dev/e1000/igb_txrx.c 340366 2018-11-12 16:28:07Z shurd $ */
|
||||
#include "if_em.h"
|
||||
|
||||
#ifdef RSS
|
||||
#include <net/rss_config.h>
|
||||
#include <netinet/in_rss.h>
|
||||
#endif
|
||||
|
||||
#ifdef VERBOSE_DEBUG
|
||||
#define DPRINTF device_printf
|
||||
#else
|
||||
#define DPRINTF(...)
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
* Local Function prototypes
|
||||
*********************************************************************/
|
||||
static int igb_isc_txd_encap(void *arg, if_pkt_info_t pi);
|
||||
static void igb_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx);
|
||||
static int igb_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear);
|
||||
|
||||
static void igb_isc_rxd_refill(void *arg, if_rxd_update_t iru);
|
||||
|
||||
static void igb_isc_rxd_flush(void *arg, uint16_t rxqid, uint8_t flid __unused, qidx_t pidx);
|
||||
static int igb_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx, qidx_t budget);
|
||||
|
||||
static int igb_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri);
|
||||
|
||||
static int igb_tx_ctx_setup(struct tx_ring *txr, if_pkt_info_t pi, u32 *cmd_type_len, u32 *olinfo_status);
|
||||
static int igb_tso_setup(struct tx_ring *txr, if_pkt_info_t pi, u32 *cmd_type_len, u32 *olinfo_status);
|
||||
|
||||
static void igb_rx_checksum(u32 staterr, if_rxd_info_t ri, u32 ptype);
|
||||
static int igb_determine_rsstype(u16 pkt_info);
|
||||
|
||||
extern void igb_if_enable_intr(if_ctx_t ctx);
|
||||
extern int em_intr(void *arg);
|
||||
|
||||
struct if_txrx igb_txrx = {
|
||||
.ift_txd_encap = igb_isc_txd_encap,
|
||||
.ift_txd_flush = igb_isc_txd_flush,
|
||||
.ift_txd_credits_update = igb_isc_txd_credits_update,
|
||||
.ift_rxd_available = igb_isc_rxd_available,
|
||||
.ift_rxd_pkt_get = igb_isc_rxd_pkt_get,
|
||||
.ift_rxd_refill = igb_isc_rxd_refill,
|
||||
.ift_rxd_flush = igb_isc_rxd_flush,
|
||||
.ift_legacy_intr = em_intr
|
||||
};
|
||||
|
||||
extern if_shared_ctx_t em_sctx;
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* Setup work for hardware segmentation offload (TSO) on
|
||||
* adapters using advanced tx descriptors
|
||||
*
|
||||
**********************************************************************/
|
||||
static int
|
||||
igb_tso_setup(struct tx_ring *txr, if_pkt_info_t pi, u32 *cmd_type_len, u32 *olinfo_status)
|
||||
{
|
||||
struct e1000_adv_tx_context_desc *TXD;
|
||||
struct adapter *adapter = txr->adapter;
|
||||
u32 type_tucmd_mlhl = 0, vlan_macip_lens = 0;
|
||||
u32 mss_l4len_idx = 0;
|
||||
u32 paylen;
|
||||
|
||||
switch(pi->ipi_etype) {
|
||||
case ETHERTYPE_IPV6:
|
||||
type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV6;
|
||||
break;
|
||||
case ETHERTYPE_IP:
|
||||
type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV4;
|
||||
/* Tell transmit desc to also do IPv4 checksum. */
|
||||
*olinfo_status |= E1000_TXD_POPTS_IXSM << 8;
|
||||
break;
|
||||
default:
|
||||
panic("%s: CSUM_TSO but no supported IP version (0x%04x)",
|
||||
__func__, ntohs(pi->ipi_etype));
|
||||
break;
|
||||
}
|
||||
|
||||
TXD = (struct e1000_adv_tx_context_desc *) &txr->tx_base[pi->ipi_pidx];
|
||||
|
||||
/* This is used in the transmit desc in encap */
|
||||
paylen = pi->ipi_len - pi->ipi_ehdrlen - pi->ipi_ip_hlen - pi->ipi_tcp_hlen;
|
||||
|
||||
/* VLAN MACLEN IPLEN */
|
||||
if (pi->ipi_mflags & M_VLANTAG) {
|
||||
vlan_macip_lens |= (pi->ipi_vtag << E1000_ADVTXD_VLAN_SHIFT);
|
||||
}
|
||||
|
||||
vlan_macip_lens |= pi->ipi_ehdrlen << E1000_ADVTXD_MACLEN_SHIFT;
|
||||
vlan_macip_lens |= pi->ipi_ip_hlen;
|
||||
TXD->vlan_macip_lens = htole32(vlan_macip_lens);
|
||||
|
||||
/* ADV DTYPE TUCMD */
|
||||
type_tucmd_mlhl |= E1000_ADVTXD_DCMD_DEXT | E1000_ADVTXD_DTYP_CTXT;
|
||||
type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_TCP;
|
||||
TXD->type_tucmd_mlhl = htole32(type_tucmd_mlhl);
|
||||
|
||||
/* MSS L4LEN IDX */
|
||||
mss_l4len_idx |= (pi->ipi_tso_segsz << E1000_ADVTXD_MSS_SHIFT);
|
||||
mss_l4len_idx |= (pi->ipi_tcp_hlen << E1000_ADVTXD_L4LEN_SHIFT);
|
||||
/* 82575 needs the queue index added */
|
||||
if (adapter->hw.mac.type == e1000_82575)
|
||||
mss_l4len_idx |= txr->me << 4;
|
||||
TXD->mss_l4len_idx = htole32(mss_l4len_idx);
|
||||
|
||||
TXD->seqnum_seed = htole32(0);
|
||||
*cmd_type_len |= E1000_ADVTXD_DCMD_TSE;
|
||||
*olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
|
||||
*olinfo_status |= paylen << E1000_ADVTXD_PAYLEN_SHIFT;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Advanced Context Descriptor setup for VLAN, CSUM or TSO
|
||||
*
|
||||
**********************************************************************/
|
||||
static int
|
||||
igb_tx_ctx_setup(struct tx_ring *txr, if_pkt_info_t pi, u32 *cmd_type_len, u32 *olinfo_status)
|
||||
{
|
||||
struct e1000_adv_tx_context_desc *TXD;
|
||||
struct adapter *adapter = txr->adapter;
|
||||
u32 vlan_macip_lens, type_tucmd_mlhl;
|
||||
u32 mss_l4len_idx;
|
||||
mss_l4len_idx = vlan_macip_lens = type_tucmd_mlhl = 0;
|
||||
|
||||
/* First check if TSO is to be used */
|
||||
if (pi->ipi_csum_flags & CSUM_TSO)
|
||||
return (igb_tso_setup(txr, pi, cmd_type_len, olinfo_status));
|
||||
|
||||
/* Indicate the whole packet as payload when not doing TSO */
|
||||
*olinfo_status |= pi->ipi_len << E1000_ADVTXD_PAYLEN_SHIFT;
|
||||
|
||||
/* Now ready a context descriptor */
|
||||
TXD = (struct e1000_adv_tx_context_desc *) &txr->tx_base[pi->ipi_pidx];
|
||||
|
||||
/*
|
||||
** In advanced descriptors the vlan tag must
|
||||
** be placed into the context descriptor. Hence
|
||||
** we need to make one even if not doing offloads.
|
||||
*/
|
||||
if (pi->ipi_mflags & M_VLANTAG) {
|
||||
vlan_macip_lens |= (pi->ipi_vtag << E1000_ADVTXD_VLAN_SHIFT);
|
||||
} else if ((pi->ipi_csum_flags & IGB_CSUM_OFFLOAD) == 0) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Set the ether header length */
|
||||
vlan_macip_lens |= pi->ipi_ehdrlen << E1000_ADVTXD_MACLEN_SHIFT;
|
||||
|
||||
switch(pi->ipi_etype) {
|
||||
case ETHERTYPE_IP:
|
||||
type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV4;
|
||||
break;
|
||||
case ETHERTYPE_IPV6:
|
||||
type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV6;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
vlan_macip_lens |= pi->ipi_ip_hlen;
|
||||
type_tucmd_mlhl |= E1000_ADVTXD_DCMD_DEXT | E1000_ADVTXD_DTYP_CTXT;
|
||||
|
||||
switch (pi->ipi_ipproto) {
|
||||
case IPPROTO_TCP:
|
||||
if (pi->ipi_csum_flags & (CSUM_IP_TCP | CSUM_IP6_TCP)) {
|
||||
type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_TCP;
|
||||
*olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
|
||||
}
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
if (pi->ipi_csum_flags & (CSUM_IP_UDP | CSUM_IP6_UDP)) {
|
||||
type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_UDP;
|
||||
*olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
|
||||
}
|
||||
break;
|
||||
#ifndef __HAIKU__
|
||||
case IPPROTO_SCTP:
|
||||
if (pi->ipi_csum_flags & (CSUM_IP_SCTP | CSUM_IP6_SCTP)) {
|
||||
type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_SCTP;
|
||||
*olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* 82575 needs the queue index added */
|
||||
if (adapter->hw.mac.type == e1000_82575)
|
||||
mss_l4len_idx = txr->me << 4;
|
||||
|
||||
/* Now copy bits into descriptor */
|
||||
TXD->vlan_macip_lens = htole32(vlan_macip_lens);
|
||||
TXD->type_tucmd_mlhl = htole32(type_tucmd_mlhl);
|
||||
TXD->seqnum_seed = htole32(0);
|
||||
TXD->mss_l4len_idx = htole32(mss_l4len_idx);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
igb_isc_txd_encap(void *arg, if_pkt_info_t pi)
|
||||
{
|
||||
struct adapter *sc = arg;
|
||||
if_softc_ctx_t scctx = sc->shared;
|
||||
struct em_tx_queue *que = &sc->tx_queues[pi->ipi_qsidx];
|
||||
struct tx_ring *txr = &que->txr;
|
||||
int nsegs = pi->ipi_nsegs;
|
||||
bus_dma_segment_t *segs = pi->ipi_segs;
|
||||
union e1000_adv_tx_desc *txd = NULL;
|
||||
int i, j, pidx_last;
|
||||
u32 olinfo_status, cmd_type_len, txd_flags;
|
||||
qidx_t ntxd;
|
||||
|
||||
pidx_last = olinfo_status = 0;
|
||||
/* Basic descriptor defines */
|
||||
cmd_type_len = (E1000_ADVTXD_DTYP_DATA |
|
||||
E1000_ADVTXD_DCMD_IFCS | E1000_ADVTXD_DCMD_DEXT);
|
||||
|
||||
if (pi->ipi_mflags & M_VLANTAG)
|
||||
cmd_type_len |= E1000_ADVTXD_DCMD_VLE;
|
||||
|
||||
i = pi->ipi_pidx;
|
||||
ntxd = scctx->isc_ntxd[0];
|
||||
txd_flags = pi->ipi_flags & IPI_TX_INTR ? E1000_ADVTXD_DCMD_RS : 0;
|
||||
/* Consume the first descriptor */
|
||||
i += igb_tx_ctx_setup(txr, pi, &cmd_type_len, &olinfo_status);
|
||||
if (i == scctx->isc_ntxd[0])
|
||||
i = 0;
|
||||
|
||||
/* 82575 needs the queue index added */
|
||||
if (sc->hw.mac.type == e1000_82575)
|
||||
olinfo_status |= txr->me << 4;
|
||||
|
||||
for (j = 0; j < nsegs; j++) {
|
||||
bus_size_t seglen;
|
||||
bus_addr_t segaddr;
|
||||
|
||||
txd = (union e1000_adv_tx_desc *)&txr->tx_base[i];
|
||||
seglen = segs[j].ds_len;
|
||||
segaddr = htole64(segs[j].ds_addr);
|
||||
|
||||
txd->read.buffer_addr = segaddr;
|
||||
txd->read.cmd_type_len = htole32(E1000_TXD_CMD_IFCS |
|
||||
cmd_type_len | seglen);
|
||||
txd->read.olinfo_status = htole32(olinfo_status);
|
||||
pidx_last = i;
|
||||
if (++i == scctx->isc_ntxd[0]) {
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
if (txd_flags) {
|
||||
txr->tx_rsq[txr->tx_rs_pidx] = pidx_last;
|
||||
txr->tx_rs_pidx = (txr->tx_rs_pidx+1) & (ntxd-1);
|
||||
MPASS(txr->tx_rs_pidx != txr->tx_rs_cidx);
|
||||
}
|
||||
|
||||
txd->read.cmd_type_len |= htole32(E1000_TXD_CMD_EOP | txd_flags);
|
||||
pi->ipi_new_pidx = i;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
igb_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx)
|
||||
{
|
||||
struct adapter *adapter = arg;
|
||||
struct em_tx_queue *que = &adapter->tx_queues[txqid];
|
||||
struct tx_ring *txr = &que->txr;
|
||||
|
||||
E1000_WRITE_REG(&adapter->hw, E1000_TDT(txr->me), pidx);
|
||||
}
|
||||
|
||||
static int
|
||||
igb_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear)
|
||||
{
|
||||
struct adapter *adapter = arg;
|
||||
if_softc_ctx_t scctx = adapter->shared;
|
||||
struct em_tx_queue *que = &adapter->tx_queues[txqid];
|
||||
struct tx_ring *txr = &que->txr;
|
||||
|
||||
qidx_t processed = 0;
|
||||
int updated;
|
||||
qidx_t cur, prev, ntxd, rs_cidx;
|
||||
int32_t delta;
|
||||
uint8_t status;
|
||||
|
||||
rs_cidx = txr->tx_rs_cidx;
|
||||
if (rs_cidx == txr->tx_rs_pidx)
|
||||
return (0);
|
||||
cur = txr->tx_rsq[rs_cidx];
|
||||
status = ((union e1000_adv_tx_desc *)&txr->tx_base[cur])->wb.status;
|
||||
updated = !!(status & E1000_TXD_STAT_DD);
|
||||
|
||||
if (!updated)
|
||||
return (0);
|
||||
|
||||
/* If clear is false just let caller know that there
|
||||
* are descriptors to reclaim */
|
||||
if (!clear)
|
||||
return (1);
|
||||
|
||||
prev = txr->tx_cidx_processed;
|
||||
ntxd = scctx->isc_ntxd[0];
|
||||
do {
|
||||
delta = (int32_t)cur - (int32_t)prev;
|
||||
/*
|
||||
* XXX This appears to be a hack for first-packet.
|
||||
* A correct fix would prevent prev == cur in the first place.
|
||||
*/
|
||||
MPASS(prev == 0 || delta != 0);
|
||||
if (prev == 0 && cur == 0)
|
||||
delta += 1;
|
||||
if (delta < 0)
|
||||
delta += ntxd;
|
||||
|
||||
processed += delta;
|
||||
prev = cur;
|
||||
rs_cidx = (rs_cidx + 1) & (ntxd-1);
|
||||
if (rs_cidx == txr->tx_rs_pidx)
|
||||
break;
|
||||
cur = txr->tx_rsq[rs_cidx];
|
||||
status = ((union e1000_adv_tx_desc *)&txr->tx_base[cur])->wb.status;
|
||||
} while ((status & E1000_TXD_STAT_DD));
|
||||
|
||||
txr->tx_rs_cidx = rs_cidx;
|
||||
txr->tx_cidx_processed = prev;
|
||||
return (processed);
|
||||
}
|
||||
|
||||
static void
|
||||
igb_isc_rxd_refill(void *arg, if_rxd_update_t iru)
|
||||
{
|
||||
struct adapter *sc = arg;
|
||||
if_softc_ctx_t scctx = sc->shared;
|
||||
uint16_t rxqid = iru->iru_qsidx;
|
||||
struct em_rx_queue *que = &sc->rx_queues[rxqid];
|
||||
union e1000_adv_rx_desc *rxd;
|
||||
struct rx_ring *rxr = &que->rxr;
|
||||
uint64_t *paddrs;
|
||||
uint32_t next_pidx, pidx;
|
||||
uint16_t count;
|
||||
int i;
|
||||
|
||||
paddrs = iru->iru_paddrs;
|
||||
pidx = iru->iru_pidx;
|
||||
count = iru->iru_count;
|
||||
|
||||
for (i = 0, next_pidx = pidx; i < count; i++) {
|
||||
rxd = (union e1000_adv_rx_desc *)&rxr->rx_base[next_pidx];
|
||||
|
||||
rxd->read.pkt_addr = htole64(paddrs[i]);
|
||||
if (++next_pidx == scctx->isc_nrxd[0])
|
||||
next_pidx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
igb_isc_rxd_flush(void *arg, uint16_t rxqid, uint8_t flid __unused, qidx_t pidx)
|
||||
{
|
||||
struct adapter *sc = arg;
|
||||
struct em_rx_queue *que = &sc->rx_queues[rxqid];
|
||||
struct rx_ring *rxr = &que->rxr;
|
||||
|
||||
E1000_WRITE_REG(&sc->hw, E1000_RDT(rxr->me), pidx);
|
||||
}
|
||||
|
||||
static int
|
||||
igb_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx, qidx_t budget)
|
||||
{
|
||||
struct adapter *sc = arg;
|
||||
if_softc_ctx_t scctx = sc->shared;
|
||||
struct em_rx_queue *que = &sc->rx_queues[rxqid];
|
||||
struct rx_ring *rxr = &que->rxr;
|
||||
union e1000_adv_rx_desc *rxd;
|
||||
u32 staterr = 0;
|
||||
int cnt, i;
|
||||
|
||||
for (cnt = 0, i = idx; cnt < scctx->isc_nrxd[0] && cnt <= budget;) {
|
||||
rxd = (union e1000_adv_rx_desc *)&rxr->rx_base[i];
|
||||
staterr = le32toh(rxd->wb.upper.status_error);
|
||||
|
||||
if ((staterr & E1000_RXD_STAT_DD) == 0)
|
||||
break;
|
||||
if (++i == scctx->isc_nrxd[0])
|
||||
i = 0;
|
||||
if (staterr & E1000_RXD_STAT_EOP)
|
||||
cnt++;
|
||||
}
|
||||
return (cnt);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* Routine sends data which has been dma'ed into host memory
|
||||
* to upper layer. Initialize ri structure.
|
||||
*
|
||||
* Returns 0 upon success, errno on failure
|
||||
***************************************************************/
|
||||
|
||||
static int
|
||||
igb_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri)
|
||||
{
|
||||
struct adapter *adapter = arg;
|
||||
if_softc_ctx_t scctx = adapter->shared;
|
||||
struct em_rx_queue *que = &adapter->rx_queues[ri->iri_qsidx];
|
||||
struct rx_ring *rxr = &que->rxr;
|
||||
struct ifnet *ifp = iflib_get_ifp(adapter->ctx);
|
||||
union e1000_adv_rx_desc *rxd;
|
||||
|
||||
u16 pkt_info, len;
|
||||
u16 vtag = 0;
|
||||
u32 ptype;
|
||||
u32 staterr = 0;
|
||||
bool eop;
|
||||
int i = 0;
|
||||
int cidx = ri->iri_cidx;
|
||||
|
||||
do {
|
||||
rxd = (union e1000_adv_rx_desc *)&rxr->rx_base[cidx];
|
||||
staterr = le32toh(rxd->wb.upper.status_error);
|
||||
pkt_info = le16toh(rxd->wb.lower.lo_dword.hs_rss.pkt_info);
|
||||
|
||||
MPASS ((staterr & E1000_RXD_STAT_DD) != 0);
|
||||
|
||||
len = le16toh(rxd->wb.upper.length);
|
||||
ptype = le32toh(rxd->wb.lower.lo_dword.data) & IGB_PKTTYPE_MASK;
|
||||
|
||||
ri->iri_len += len;
|
||||
rxr->rx_bytes += ri->iri_len;
|
||||
|
||||
rxd->wb.upper.status_error = 0;
|
||||
eop = ((staterr & E1000_RXD_STAT_EOP) == E1000_RXD_STAT_EOP);
|
||||
|
||||
if (((adapter->hw.mac.type == e1000_i350) ||
|
||||
(adapter->hw.mac.type == e1000_i354)) &&
|
||||
(staterr & E1000_RXDEXT_STATERR_LB))
|
||||
vtag = be16toh(rxd->wb.upper.vlan);
|
||||
else
|
||||
vtag = le16toh(rxd->wb.upper.vlan);
|
||||
|
||||
/* Make sure bad packets are discarded */
|
||||
if (eop && ((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) != 0)) {
|
||||
adapter->dropped_pkts++;
|
||||
++rxr->rx_discarded;
|
||||
return (EBADMSG);
|
||||
}
|
||||
ri->iri_frags[i].irf_flid = 0;
|
||||
ri->iri_frags[i].irf_idx = cidx;
|
||||
ri->iri_frags[i].irf_len = len;
|
||||
|
||||
if (++cidx == scctx->isc_nrxd[0])
|
||||
cidx = 0;
|
||||
#ifdef notyet
|
||||
if (rxr->hdr_split == TRUE) {
|
||||
ri->iri_frags[i].irf_flid = 1;
|
||||
ri->iri_frags[i].irf_idx = cidx;
|
||||
if (++cidx == scctx->isc_nrxd[0])
|
||||
cidx = 0;
|
||||
}
|
||||
#endif
|
||||
i++;
|
||||
} while (!eop);
|
||||
|
||||
rxr->rx_packets++;
|
||||
|
||||
if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
|
||||
igb_rx_checksum(staterr, ri, ptype);
|
||||
|
||||
if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 &&
|
||||
(staterr & E1000_RXD_STAT_VP) != 0) {
|
||||
ri->iri_vtag = vtag;
|
||||
ri->iri_flags |= M_VLANTAG;
|
||||
}
|
||||
ri->iri_flowid =
|
||||
le32toh(rxd->wb.lower.hi_dword.rss);
|
||||
ri->iri_rsstype = igb_determine_rsstype(pkt_info);
|
||||
ri->iri_nfrags = i;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Verify that the hardware indicated that the checksum is valid.
|
||||
* Inform the stack about the status of checksum so that stack
|
||||
* doesn't spend time verifying the checksum.
|
||||
*
|
||||
*********************************************************************/
|
||||
static void
|
||||
igb_rx_checksum(u32 staterr, if_rxd_info_t ri, u32 ptype)
|
||||
{
|
||||
u16 status = (u16)staterr;
|
||||
u8 errors = (u8) (staterr >> 24);
|
||||
bool sctp = FALSE;
|
||||
|
||||
/* Ignore Checksum bit is set */
|
||||
if (status & E1000_RXD_STAT_IXSM) {
|
||||
ri->iri_csum_flags = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ptype & E1000_RXDADV_PKTTYPE_ETQF) == 0 &&
|
||||
(ptype & E1000_RXDADV_PKTTYPE_SCTP) != 0)
|
||||
sctp = 1;
|
||||
else
|
||||
sctp = 0;
|
||||
|
||||
if (status & E1000_RXD_STAT_IPCS) {
|
||||
/* Did it pass? */
|
||||
if (!(errors & E1000_RXD_ERR_IPE)) {
|
||||
/* IP Checksum Good */
|
||||
ri->iri_csum_flags = CSUM_IP_CHECKED;
|
||||
ri->iri_csum_flags |= CSUM_IP_VALID;
|
||||
} else
|
||||
ri->iri_csum_flags = 0;
|
||||
}
|
||||
|
||||
if (status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)) {
|
||||
u64 type = (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
|
||||
if (sctp) /* reassign */
|
||||
type = CSUM_SCTP_VALID;
|
||||
/* Did it pass? */
|
||||
if (!(errors & E1000_RXD_ERR_TCPE)) {
|
||||
ri->iri_csum_flags |= type;
|
||||
if (sctp == 0)
|
||||
ri->iri_csum_data = htons(0xffff);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
*
|
||||
* Parse the packet type to determine the appropriate hash
|
||||
*
|
||||
******************************************************************/
|
||||
static int
|
||||
igb_determine_rsstype(u16 pkt_info)
|
||||
{
|
||||
switch (pkt_info & E1000_RXDADV_RSSTYPE_MASK) {
|
||||
case E1000_RXDADV_RSSTYPE_IPV4_TCP:
|
||||
return M_HASHTYPE_RSS_TCP_IPV4;
|
||||
case E1000_RXDADV_RSSTYPE_IPV4:
|
||||
return M_HASHTYPE_RSS_IPV4;
|
||||
case E1000_RXDADV_RSSTYPE_IPV6_TCP:
|
||||
return M_HASHTYPE_RSS_TCP_IPV6;
|
||||
case E1000_RXDADV_RSSTYPE_IPV6_EX:
|
||||
return M_HASHTYPE_RSS_IPV6_EX;
|
||||
case E1000_RXDADV_RSSTYPE_IPV6:
|
||||
return M_HASHTYPE_RSS_IPV6;
|
||||
case E1000_RXDADV_RSSTYPE_IPV6_TCP_EX:
|
||||
return M_HASHTYPE_RSS_TCP_IPV6_EX;
|
||||
default:
|
||||
return M_HASHTYPE_OPAQUE;
|
||||
}
|
||||
}
|
||||
@@ -8,12 +8,12 @@
|
||||
|
||||
|
||||
extern driver_t* DRIVER_MODULE_NAME(em, pci);
|
||||
extern driver_t* DRIVER_MODULE_NAME(lem, pci);
|
||||
extern driver_t* DRIVER_MODULE_NAME(igb, pci);
|
||||
|
||||
HAIKU_FBSD_DRIVERS_GLUE(ipro1000);
|
||||
HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_FAST_TASKQUEUE);
|
||||
HAIKU_DRIVER_REQUIREMENTS(0);
|
||||
NO_HAIKU_FBSD_MII_DRIVER();
|
||||
NO_HAIKU_CHECK_DISABLE_INTERRUPTS();
|
||||
NO_HAIKU_REENABLE_INTERRUPTS();
|
||||
|
||||
|
||||
@@ -22,17 +22,8 @@ __haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[]))
|
||||
{
|
||||
driver_t *drivers[] = {
|
||||
DRIVER_MODULE_NAME(em, pci),
|
||||
DRIVER_MODULE_NAME(lem, pci),
|
||||
DRIVER_MODULE_NAME(igb, pci),
|
||||
NULL
|
||||
};
|
||||
return (*handler)(drivers);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev)
|
||||
{
|
||||
// only MSI interrupts, legacy uses fast intr
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user