igb: add access to specific device info
add function to support ethtool ops: - get_reg_length - get_regs - get_eeprom_length - get_eeprom - set_eeprom Signed-off-by: Liang-Min Larry Wang <liang-min.wang@intel.com> Acked-by: Andrew Harvey <agh@cisco.com> Acked-by: David Harton <dharton@cisco.com> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
This commit is contained in:
parent
7a3f27cbf5
commit
83c314da4c
@ -55,6 +55,7 @@
|
||||
#include "e1000_logs.h"
|
||||
#include "base/e1000_api.h"
|
||||
#include "e1000_ethdev.h"
|
||||
#include "igb_regs.h"
|
||||
|
||||
/*
|
||||
* Default values for port configuration
|
||||
@ -154,6 +155,10 @@ static int igbvf_set_vfta(struct e1000_hw *hw, uint16_t vid, bool on);
|
||||
static void igbvf_set_vfta_all(struct rte_eth_dev *dev, bool on);
|
||||
static void igbvf_default_mac_addr_set(struct rte_eth_dev *dev,
|
||||
struct ether_addr *addr);
|
||||
static int igbvf_get_reg_length(struct rte_eth_dev *dev);
|
||||
static int igbvf_get_regs(struct rte_eth_dev *dev,
|
||||
struct rte_dev_reg_info *regs);
|
||||
|
||||
static int eth_igb_rss_reta_update(struct rte_eth_dev *dev,
|
||||
struct rte_eth_rss_reta_entry64 *reta_conf,
|
||||
uint16_t reta_size);
|
||||
@ -205,6 +210,14 @@ static int eth_igb_filter_ctrl(struct rte_eth_dev *dev,
|
||||
enum rte_filter_type filter_type,
|
||||
enum rte_filter_op filter_op,
|
||||
void *arg);
|
||||
static int eth_igb_get_reg_length(struct rte_eth_dev *dev);
|
||||
static int eth_igb_get_regs(struct rte_eth_dev *dev,
|
||||
struct rte_dev_reg_info *regs);
|
||||
static int eth_igb_get_eeprom_length(struct rte_eth_dev *dev);
|
||||
static int eth_igb_get_eeprom(struct rte_eth_dev *dev,
|
||||
struct rte_dev_eeprom_info *eeprom);
|
||||
static int eth_igb_set_eeprom(struct rte_eth_dev *dev,
|
||||
struct rte_dev_eeprom_info *eeprom);
|
||||
|
||||
static int eth_igb_set_mc_addr_list(struct rte_eth_dev *dev,
|
||||
struct ether_addr *mc_addr_set,
|
||||
@ -298,6 +311,11 @@ static const struct eth_dev_ops eth_igb_ops = {
|
||||
.timesync_disable = igb_timesync_disable,
|
||||
.timesync_read_rx_timestamp = igb_timesync_read_rx_timestamp,
|
||||
.timesync_read_tx_timestamp = igb_timesync_read_tx_timestamp,
|
||||
.get_reg_length = eth_igb_get_reg_length,
|
||||
.get_reg = eth_igb_get_regs,
|
||||
.get_eeprom_length = eth_igb_get_eeprom_length,
|
||||
.get_eeprom = eth_igb_get_eeprom,
|
||||
.set_eeprom = eth_igb_set_eeprom,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -320,6 +338,8 @@ static const struct eth_dev_ops igbvf_eth_dev_ops = {
|
||||
.tx_queue_release = eth_igb_tx_queue_release,
|
||||
.set_mc_addr_list = eth_igb_set_mc_addr_list,
|
||||
.mac_addr_set = igbvf_default_mac_addr_set,
|
||||
.get_reg_length = igbvf_get_reg_length,
|
||||
.get_reg = igbvf_get_regs,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -3803,6 +3823,136 @@ igb_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
eth_igb_get_reg_length(struct rte_eth_dev *dev __rte_unused)
|
||||
{
|
||||
int count = 0;
|
||||
int g_ind = 0;
|
||||
const struct reg_info *reg_group;
|
||||
|
||||
while ((reg_group = igb_regs[g_ind++]))
|
||||
count += igb_reg_group_count(reg_group);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int
|
||||
igbvf_get_reg_length(struct rte_eth_dev *dev __rte_unused)
|
||||
{
|
||||
int count = 0;
|
||||
int g_ind = 0;
|
||||
const struct reg_info *reg_group;
|
||||
|
||||
while ((reg_group = igbvf_regs[g_ind++]))
|
||||
count += igb_reg_group_count(reg_group);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int
|
||||
eth_igb_get_regs(struct rte_eth_dev *dev,
|
||||
struct rte_dev_reg_info *regs)
|
||||
{
|
||||
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
|
||||
uint32_t *data = regs->data;
|
||||
int g_ind = 0;
|
||||
int count = 0;
|
||||
const struct reg_info *reg_group;
|
||||
|
||||
/* Support only full register dump */
|
||||
if ((regs->length == 0) ||
|
||||
(regs->length == (uint32_t)eth_igb_get_reg_length(dev))) {
|
||||
regs->version = hw->mac.type << 24 | hw->revision_id << 16 |
|
||||
hw->device_id;
|
||||
while ((reg_group = igb_regs[g_ind++]))
|
||||
count += igb_read_regs_group(dev, &data[count],
|
||||
reg_group);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int
|
||||
igbvf_get_regs(struct rte_eth_dev *dev,
|
||||
struct rte_dev_reg_info *regs)
|
||||
{
|
||||
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
|
||||
uint32_t *data = regs->data;
|
||||
int g_ind = 0;
|
||||
int count = 0;
|
||||
const struct reg_info *reg_group;
|
||||
|
||||
/* Support only full register dump */
|
||||
if ((regs->length == 0) ||
|
||||
(regs->length == (uint32_t)igbvf_get_reg_length(dev))) {
|
||||
regs->version = hw->mac.type << 24 | hw->revision_id << 16 |
|
||||
hw->device_id;
|
||||
while ((reg_group = igbvf_regs[g_ind++]))
|
||||
count += igb_read_regs_group(dev, &data[count],
|
||||
reg_group);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int
|
||||
eth_igb_get_eeprom_length(struct rte_eth_dev *dev)
|
||||
{
|
||||
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
|
||||
|
||||
/* Return unit is byte count */
|
||||
return hw->nvm.word_size * 2;
|
||||
}
|
||||
|
||||
static int
|
||||
eth_igb_get_eeprom(struct rte_eth_dev *dev,
|
||||
struct rte_dev_eeprom_info *in_eeprom)
|
||||
{
|
||||
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
uint16_t *data = in_eeprom->data;
|
||||
int first, length;
|
||||
|
||||
first = in_eeprom->offset >> 1;
|
||||
length = in_eeprom->length >> 1;
|
||||
if ((first >= hw->nvm.word_size) ||
|
||||
((first + length) >= hw->nvm.word_size))
|
||||
return -EINVAL;
|
||||
|
||||
in_eeprom->magic = hw->vendor_id |
|
||||
((uint32_t)hw->device_id << 16);
|
||||
|
||||
if ((nvm->ops.read) == NULL)
|
||||
return -ENOTSUP;
|
||||
|
||||
return nvm->ops.read(hw, first, length, data);
|
||||
}
|
||||
|
||||
static int
|
||||
eth_igb_set_eeprom(struct rte_eth_dev *dev,
|
||||
struct rte_dev_eeprom_info *in_eeprom)
|
||||
{
|
||||
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
|
||||
struct e1000_nvm_info *nvm = &hw->nvm;
|
||||
uint16_t *data = in_eeprom->data;
|
||||
int first, length;
|
||||
|
||||
first = in_eeprom->offset >> 1;
|
||||
length = in_eeprom->length >> 1;
|
||||
if ((first >= hw->nvm.word_size) ||
|
||||
((first + length) >= hw->nvm.word_size))
|
||||
return -EINVAL;
|
||||
|
||||
in_eeprom->magic = (uint32_t)hw->vendor_id |
|
||||
((uint32_t)hw->device_id << 16);
|
||||
|
||||
if ((nvm->ops.write) == NULL)
|
||||
return -ENOTSUP;
|
||||
return nvm->ops.write(hw, first, length, data);
|
||||
}
|
||||
|
||||
static struct rte_driver pmd_igb_drv = {
|
||||
.type = PMD_PDEV,
|
||||
.init = rte_igb_pmd_init,
|
||||
|
223
drivers/net/e1000/igb_regs.h
Normal file
223
drivers/net/e1000/igb_regs.h
Normal file
@ -0,0 +1,223 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2015 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * 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.
|
||||
* * Neither the name of 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.
|
||||
*/
|
||||
#ifndef _IGB_REGS_H_
|
||||
#define _IGB_REGS_H_
|
||||
|
||||
#include "e1000_ethdev.h"
|
||||
|
||||
struct reg_info {
|
||||
uint32_t base_addr;
|
||||
uint32_t count;
|
||||
uint32_t stride;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const struct reg_info igb_regs_general[] = {
|
||||
{E1000_CTRL, 1, 1, "E1000_CTRL"},
|
||||
{E1000_STATUS, 1, 1, "E1000_STATUS"},
|
||||
{E1000_CTRL_EXT, 1, 1, "E1000_CTRL_EXT"},
|
||||
{E1000_MDIC, 1, 1, "E1000_MDIC"},
|
||||
{E1000_SCTL, 1, 1, "E1000_SCTL"},
|
||||
{E1000_CONNSW, 1, 1, "E1000_CONNSW"},
|
||||
{E1000_VET, 1, 1, "E1000_VET"},
|
||||
{E1000_LEDCTL, 1, 1, "E1000_LEDCTL"},
|
||||
{E1000_PBA, 1, 1, "E1000_PBA"},
|
||||
{E1000_PBS, 1, 1, "E1000_PBS"},
|
||||
{E1000_FRTIMER, 1, 1, "E1000_FRTIMER"},
|
||||
{E1000_TCPTIMER, 1, 1, "E1000_TCPTIMER"},
|
||||
{0, 0, 0, ""}
|
||||
};
|
||||
|
||||
static const struct reg_info igb_regs_nvm[] = {
|
||||
{E1000_EECD, 1, 1, "E1000_EECD"},
|
||||
{0, 0, 0, ""}
|
||||
};
|
||||
|
||||
static const struct reg_info igb_regs_interrupt[] = {
|
||||
{E1000_EICS, 1, 1, "E1000_EICS"},
|
||||
{E1000_EIMS, 1, 1, "E1000_EIMS"},
|
||||
{E1000_EIMC, 1, 1, "E1000_EIMC"},
|
||||
{E1000_EIAC, 1, 1, "E1000_EIAC"},
|
||||
{E1000_EIAM, 1, 1, "E1000_EIAM"},
|
||||
{E1000_ICS, 1, 1, "E1000_ICS"},
|
||||
{E1000_IMS, 1, 1, "E1000_IMS"},
|
||||
{E1000_IMC, 1, 1, "E1000_IMC"},
|
||||
{E1000_IAC, 1, 1, "E1000_IAC"},
|
||||
{E1000_IAM, 1, 1, "E1000_IAM"},
|
||||
{E1000_IMIRVP, 1, 1, "E1000_IMIRVP"},
|
||||
{E1000_EITR(0), 10, 4, "E1000_EITR"},
|
||||
{E1000_IMIR(0), 8, 4, "E1000_IMIR"},
|
||||
{E1000_IMIREXT(0), 8, 4, "E1000_IMIREXT"},
|
||||
{0, 0, 0, ""}
|
||||
};
|
||||
|
||||
static const struct reg_info igb_regs_fctl[] = {
|
||||
{E1000_FCAL, 1, 1, "E1000_FCAL"},
|
||||
{E1000_FCAH, 1, 1, "E1000_FCAH"},
|
||||
{E1000_FCTTV, 1, 1, "E1000_FCTTV"},
|
||||
{E1000_FCRTL, 1, 1, "E1000_FCRTL"},
|
||||
{E1000_FCRTH, 1, 1, "E1000_FCRTH"},
|
||||
{E1000_FCRTV, 1, 1, "E1000_FCRTV"},
|
||||
{0, 0, 0, ""}
|
||||
};
|
||||
|
||||
static const struct reg_info igb_regs_rxdma[] = {
|
||||
{E1000_RDBAL(0), 4, 0x100, "E1000_RDBAL"},
|
||||
{E1000_RDBAH(0), 4, 0x100, "E1000_RDBAH"},
|
||||
{E1000_RDLEN(0), 4, 0x100, "E1000_RDLEN"},
|
||||
{E1000_RDH(0), 4, 0x100, "E1000_RDH"},
|
||||
{E1000_RDT(0), 4, 0x100, "E1000_RDT"},
|
||||
{E1000_RXCTL(0), 4, 0x100, "E1000_RXCTL"},
|
||||
{E1000_SRRCTL(0), 4, 0x100, "E1000_SRRCTL"},
|
||||
{E1000_DCA_RXCTRL(0), 4, 0x100, "E1000_DCA_RXCTRL"},
|
||||
{0, 0, 0, ""}
|
||||
};
|
||||
|
||||
static const struct reg_info igb_regs_rx[] = {
|
||||
{E1000_RCTL, 1, 1, "E1000_RCTL"},
|
||||
{E1000_RXCSUM, 1, 1, "E1000_RXCSUM"},
|
||||
{E1000_RLPML, 1, 1, "E1000_RLPML"},
|
||||
{E1000_RFCTL, 1, 1, "E1000_RFCTL"},
|
||||
{E1000_MRQC, 1, 1, "E1000_MRQC"},
|
||||
{E1000_VT_CTL, 1, 1, "E1000_VT_CTL"},
|
||||
{E1000_RAL(0), 16, 8, "E1000_RAL"},
|
||||
{E1000_RAH(0), 16, 8, "E1000_RAH"},
|
||||
{0, 0, 0, ""}
|
||||
};
|
||||
|
||||
static const struct reg_info igb_regs_tx[] = {
|
||||
{E1000_TCTL, 1, 1, "E1000_TCTL"},
|
||||
{E1000_TCTL_EXT, 1, 1, "E1000_TCTL_EXT"},
|
||||
{E1000_TIPG, 1, 1, "E1000_TIPG"},
|
||||
{E1000_DTXCTL, 1, 1, "E1000_DTXCTL"},
|
||||
{E1000_TDBAL(0), 4, 0x100, "E1000_TDBAL"},
|
||||
{E1000_TDBAH(0), 4, 0x100, "E1000_TDBAH"},
|
||||
{E1000_TDLEN(0), 4, 0x100, "E1000_TDLEN"},
|
||||
{E1000_TDH(0), 4, 0x100, "E1000_TDLEN"},
|
||||
{E1000_TDT(0), 4, 0x100, "E1000_TDT"},
|
||||
{E1000_TXDCTL(0), 4, 0x100, "E1000_TXDCTL"},
|
||||
{E1000_TDWBAL(0), 4, 0x100, "E1000_TDWBAL"},
|
||||
{E1000_TDWBAH(0), 4, 0x100, "E1000_TDWBAH"},
|
||||
{E1000_DCA_TXCTRL(0), 4, 0x100, "E1000_DCA_TXCTRL"},
|
||||
{E1000_TDFH, 1, 1, "E1000_TDFH"},
|
||||
{E1000_TDFT, 1, 1, "E1000_TDFT"},
|
||||
{E1000_TDFHS, 1, 1, "E1000_TDFHS"},
|
||||
{E1000_TDFPC, 1, 1, "E1000_TDFPC"},
|
||||
{0, 0, 0, ""}
|
||||
};
|
||||
|
||||
static const struct reg_info igb_regs_wakeup[] = {
|
||||
{E1000_WUC, 1, 1, "E1000_WUC"},
|
||||
{E1000_WUFC, 1, 1, "E1000_WUFC"},
|
||||
{E1000_WUS, 1, 1, "E1000_WUS"},
|
||||
{E1000_IPAV, 1, 1, "E1000_IPAV"},
|
||||
{E1000_WUPL, 1, 1, "E1000_WUPL"},
|
||||
{E1000_IP4AT_REG(0), 4, 8, "E1000_IP4AT_REG"},
|
||||
{E1000_IP6AT_REG(0), 4, 4, "E1000_IP6AT_REG"},
|
||||
{E1000_WUPM_REG(0), 4, 4, "E1000_WUPM_REG"},
|
||||
{E1000_FFMT_REG(0), 4, 8, "E1000_FFMT_REG"},
|
||||
{E1000_FFVT_REG(0), 4, 8, "E1000_FFVT_REG"},
|
||||
{E1000_FFLT_REG(0), 4, 8, "E1000_FFLT_REG"},
|
||||
{0, 0, 0, ""}
|
||||
};
|
||||
|
||||
static const struct reg_info igb_regs_mac[] = {
|
||||
{E1000_PCS_CFG0, 1, 1, "E1000_PCS_CFG0"},
|
||||
{E1000_PCS_LCTL, 1, 1, "E1000_PCS_LCTL"},
|
||||
{E1000_PCS_LSTAT, 1, 1, "E1000_PCS_LSTAT"},
|
||||
{E1000_PCS_ANADV, 1, 1, "E1000_PCS_ANADV"},
|
||||
{E1000_PCS_LPAB, 1, 1, "E1000_PCS_LPAB"},
|
||||
{E1000_PCS_NPTX, 1, 1, "E1000_PCS_NPTX"},
|
||||
{E1000_PCS_LPABNP, 1, 1, "E1000_PCS_LPABNP"},
|
||||
{0, 0, 0, ""}
|
||||
};
|
||||
|
||||
static const struct reg_info *igb_regs[] = {
|
||||
igb_regs_general,
|
||||
igb_regs_nvm,
|
||||
igb_regs_interrupt,
|
||||
igb_regs_fctl,
|
||||
igb_regs_rxdma,
|
||||
igb_regs_rx,
|
||||
igb_regs_tx,
|
||||
igb_regs_wakeup,
|
||||
igb_regs_mac,
|
||||
NULL};
|
||||
|
||||
/* FIXME: reading igb_regs_interrupt results side-effect which doesn't
|
||||
* work with VFIO; re-install igb_regs_interrupt once issue is resolved.
|
||||
*/
|
||||
static const struct reg_info *igbvf_regs[] = {
|
||||
igb_regs_general,
|
||||
igb_regs_rxdma,
|
||||
igb_regs_tx,
|
||||
NULL};
|
||||
|
||||
static inline int
|
||||
igb_read_regs(struct e1000_hw *hw, const struct reg_info *reg,
|
||||
uint32_t *reg_buf)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < reg->count; i++) {
|
||||
reg_buf[i] = E1000_READ_REG(hw,
|
||||
reg->base_addr + i * reg->stride);
|
||||
}
|
||||
return reg->count;
|
||||
};
|
||||
|
||||
static inline int
|
||||
igb_reg_group_count(const struct reg_info *regs)
|
||||
{
|
||||
int count = 0;
|
||||
int i = 0;
|
||||
|
||||
while (regs[i].count)
|
||||
count += regs[i++].count;
|
||||
return count;
|
||||
};
|
||||
|
||||
static inline int
|
||||
igb_read_regs_group(struct rte_eth_dev *dev, uint32_t *reg_buf,
|
||||
const struct reg_info *regs)
|
||||
{
|
||||
int count = 0;
|
||||
int i = 0;
|
||||
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
|
||||
|
||||
while (regs[i].count)
|
||||
count += igb_read_regs(hw, ®s[i++], ®_buf[count]);
|
||||
return count;
|
||||
};
|
||||
|
||||
#endif /* _IGB_REGS_H_ */
|
Loading…
Reference in New Issue
Block a user