/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
static int eth_em_interrupt_setup(struct rte_eth_dev *dev);
static int eth_em_rxq_interrupt_setup(struct rte_eth_dev *dev);
static int eth_em_interrupt_get_status(struct rte_eth_dev *dev);
-static int eth_em_interrupt_action(struct rte_eth_dev *dev);
+static int eth_em_interrupt_action(struct rte_eth_dev *dev,
+ struct rte_intr_handle *handle);
static void eth_em_interrupt_handler(struct rte_intr_handle *handle,
void *param);
* The set of PCI devices this driver supports
*/
static const struct rte_pci_id pci_id_em_map[] = {
-
-#define RTE_PCI_DEV_ID_DECL_EM(vend, dev) {RTE_PCI_DEVICE(vend, dev)},
-#include "rte_pci_dev_ids.h"
-
-{0},
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82540EM) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82545EM_COPPER) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82545EM_FIBER) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82546EB_COPPER) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82546EB_FIBER) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82546EB_QUAD_COPPER) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82571EB_COPPER) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82571EB_FIBER) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82571EB_SERDES) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82571EB_SERDES_DUAL) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82571EB_SERDES_QUAD) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82571EB_QUAD_COPPER) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82571PT_QUAD_COPPER) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82571EB_QUAD_FIBER) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82571EB_QUAD_COPPER_LP) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82572EI_COPPER) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82572EI_FIBER) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82572EI_SERDES) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82572EI) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82573L) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82574L) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82574LA) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_82583V) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_LPT_I217_LM) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_LPT_I217_V) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_LPTLP_I218_LM) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_LPTLP_I218_V) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_I218_LM2) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_I218_V2) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_I218_LM3) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_I218_V3) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_SPT_I219_LM) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_SPT_I219_V) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_SPT_I219_LM2) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_SPT_I219_V2) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_LBG_I219_LM3) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_SPT_I219_LM4) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_SPT_I219_V4) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_SPT_I219_LM5) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_SPT_I219_V5) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_CNP_I219_LM6) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_CNP_I219_V6) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_CNP_I219_LM7) },
+ { RTE_PCI_DEVICE(E1000_INTEL_VENDOR_ID, E1000_DEV_ID_PCH_CNP_I219_V7) },
+ { .vendor_id = 0, /* sentinel */ },
};
static const struct eth_dev_ops eth_em_ops = {
case E1000_DEV_ID_PCH_I218_LM2:
case E1000_DEV_ID_PCH_I218_V3:
case E1000_DEV_ID_PCH_I218_LM3:
+ case E1000_DEV_ID_PCH_SPT_I219_LM:
+ case E1000_DEV_ID_PCH_SPT_I219_V:
+ case E1000_DEV_ID_PCH_SPT_I219_LM2:
+ case E1000_DEV_ID_PCH_SPT_I219_V2:
+ case E1000_DEV_ID_PCH_LBG_I219_LM3:
+ case E1000_DEV_ID_PCH_SPT_I219_LM4:
+ case E1000_DEV_ID_PCH_SPT_I219_V4:
+ case E1000_DEV_ID_PCH_SPT_I219_LM5:
+ case E1000_DEV_ID_PCH_SPT_I219_V5:
+ 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:
return 1;
default:
return 0;
static int
eth_em_dev_init(struct rte_eth_dev *eth_dev)
{
- struct rte_pci_device *pci_dev;
+ struct rte_pci_device *pci_dev = E1000_DEV_TO_PCI(eth_dev);
+ struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
struct e1000_adapter *adapter =
E1000_DEV_PRIVATE(eth_dev->data->dev_private);
struct e1000_hw *hw =
struct e1000_vfta * shadow_vfta =
E1000_DEV_PRIVATE_TO_VFTA(eth_dev->data->dev_private);
- pci_dev = eth_dev->pci_dev;
-
eth_dev->dev_ops = ð_em_ops;
eth_dev->rx_pkt_burst = (eth_rx_burst_t)ð_em_recv_pkts;
eth_dev->tx_pkt_burst = (eth_tx_burst_t)ð_em_xmit_pkts;
+ eth_dev->tx_pkt_prepare = (eth_tx_prep_t)ð_em_prep_pkts;
/* for secondary processes, we don't initialise any further as primary
* has already done this work. Only check we don't need a different
}
rte_eth_copy_pci_info(eth_dev, pci_dev);
+ eth_dev->data->dev_flags = RTE_ETH_DEV_DETACHABLE;
hw->hw_addr = (void *)pci_dev->mem_resource[0].addr;
hw->device_id = pci_dev->id.device_id;
eth_dev->data->port_id, pci_dev->id.vendor_id,
pci_dev->id.device_id);
- rte_intr_callback_register(&(pci_dev->intr_handle),
- eth_em_interrupt_handler, (void *)eth_dev);
+ rte_intr_callback_register(intr_handle,
+ eth_em_interrupt_handler, eth_dev);
return 0;
}
static int
eth_em_dev_uninit(struct rte_eth_dev *eth_dev)
{
- struct rte_pci_device *pci_dev;
+ struct rte_pci_device *pci_dev = E1000_DEV_TO_PCI(eth_dev);
struct e1000_adapter *adapter =
E1000_DEV_PRIVATE(eth_dev->data->dev_private);
+ struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
PMD_INIT_FUNC_TRACE();
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
return -EPERM;
- pci_dev = eth_dev->pci_dev;
-
if (adapter->stopped == 0)
eth_em_close(eth_dev);
eth_dev->data->mac_addrs = NULL;
/* disable uio intr before callback unregister */
- rte_intr_disable(&(pci_dev->intr_handle));
- rte_intr_callback_unregister(&(pci_dev->intr_handle),
- eth_em_interrupt_handler, (void *)eth_dev);
+ rte_intr_disable(intr_handle);
+ rte_intr_callback_unregister(intr_handle,
+ eth_em_interrupt_handler, eth_dev);
return 0;
}
static struct eth_driver rte_em_pmd = {
.pci_drv = {
- .name = "rte_em_pmd",
.id_table = pci_id_em_map,
- .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
- RTE_PCI_DRV_DETACHABLE,
+ .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
+ .probe = rte_eth_dev_pci_probe,
+ .remove = rte_eth_dev_pci_remove,
},
.eth_dev_init = eth_em_dev_init,
.eth_dev_uninit = eth_em_dev_uninit,
.dev_private_size = sizeof(struct e1000_adapter),
};
-static int
-rte_em_pmd_init(const char *name __rte_unused, const char *params __rte_unused)
-{
- rte_eth_driver_register(&rte_em_pmd);
- return 0;
-}
-
static int
em_hw_init(struct e1000_hw *hw)
{
case e1000_pchlan:
case e1000_pch2lan:
case e1000_pch_lpt:
+ case e1000_pch_spt:
+ case e1000_pch_cnp:
pba = E1000_PBA_26K;
break;
default:
E1000_DEV_PRIVATE(dev->data->dev_private);
struct e1000_hw *hw =
E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+ struct rte_pci_device *pci_dev =
+ E1000_DEV_TO_PCI(dev);
+ struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
int ret, mask;
uint32_t intr_vector = 0;
+ uint32_t *speeds;
+ int num_speeds;
+ bool autoneg;
PMD_INIT_FUNC_TRACE();
E1000_WRITE_REG(hw, E1000_ITR, UINT16_MAX);
/* Setup link speed and duplex */
- switch (dev->data->dev_conf.link_speed) {
- case ETH_LINK_SPEED_AUTONEG:
- if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX)
- hw->phy.autoneg_advertised = E1000_ALL_SPEED_DUPLEX;
- else if (dev->data->dev_conf.link_duplex ==
- ETH_LINK_HALF_DUPLEX)
- hw->phy.autoneg_advertised = E1000_ALL_HALF_DUPLEX;
- else if (dev->data->dev_conf.link_duplex ==
- ETH_LINK_FULL_DUPLEX)
- hw->phy.autoneg_advertised = E1000_ALL_FULL_DUPLEX;
- else
- goto error_invalid_config;
- break;
- case ETH_SPEED_NUM_10M:
- if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX)
- hw->phy.autoneg_advertised = E1000_ALL_10_SPEED;
- else if (dev->data->dev_conf.link_duplex ==
- ETH_LINK_HALF_DUPLEX)
- hw->phy.autoneg_advertised = ADVERTISE_10_HALF;
- else if (dev->data->dev_conf.link_duplex ==
- ETH_LINK_FULL_DUPLEX)
- hw->phy.autoneg_advertised = ADVERTISE_10_FULL;
- else
- goto error_invalid_config;
- break;
- case ETH_SPEED_NUM_100M:
- if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX)
- hw->phy.autoneg_advertised = E1000_ALL_100_SPEED;
- else if (dev->data->dev_conf.link_duplex ==
- ETH_LINK_HALF_DUPLEX)
- hw->phy.autoneg_advertised = ADVERTISE_100_HALF;
- else if (dev->data->dev_conf.link_duplex ==
- ETH_LINK_FULL_DUPLEX)
- hw->phy.autoneg_advertised = ADVERTISE_100_FULL;
- else
+ speeds = &dev->data->dev_conf.link_speeds;
+ if (*speeds == ETH_LINK_SPEED_AUTONEG) {
+ hw->phy.autoneg_advertised = E1000_ALL_SPEED_DUPLEX;
+ hw->mac.autoneg = 1;
+ } else {
+ num_speeds = 0;
+ autoneg = (*speeds & ETH_LINK_SPEED_FIXED) == 0;
+
+ /* Reset */
+ hw->phy.autoneg_advertised = 0;
+
+ if (*speeds & ~(ETH_LINK_SPEED_10M_HD | ETH_LINK_SPEED_10M |
+ ETH_LINK_SPEED_100M_HD | ETH_LINK_SPEED_100M |
+ ETH_LINK_SPEED_1G | ETH_LINK_SPEED_FIXED)) {
+ num_speeds = -1;
goto error_invalid_config;
- break;
- case ETH_SPEED_NUM_1G:
- if ((dev->data->dev_conf.link_duplex ==
- ETH_LINK_AUTONEG_DUPLEX) ||
- (dev->data->dev_conf.link_duplex ==
- ETH_LINK_FULL_DUPLEX))
- hw->phy.autoneg_advertised = ADVERTISE_1000_FULL;
- else
+ }
+ if (*speeds & ETH_LINK_SPEED_10M_HD) {
+ hw->phy.autoneg_advertised |= ADVERTISE_10_HALF;
+ num_speeds++;
+ }
+ if (*speeds & ETH_LINK_SPEED_10M) {
+ hw->phy.autoneg_advertised |= ADVERTISE_10_FULL;
+ num_speeds++;
+ }
+ if (*speeds & ETH_LINK_SPEED_100M_HD) {
+ hw->phy.autoneg_advertised |= ADVERTISE_100_HALF;
+ num_speeds++;
+ }
+ if (*speeds & ETH_LINK_SPEED_100M) {
+ hw->phy.autoneg_advertised |= ADVERTISE_100_FULL;
+ num_speeds++;
+ }
+ if (*speeds & ETH_LINK_SPEED_1G) {
+ hw->phy.autoneg_advertised |= ADVERTISE_1000_FULL;
+ num_speeds++;
+ }
+ if (num_speeds == 0 || (!autoneg && (num_speeds > 1)))
goto error_invalid_config;
- break;
- case ETH_SPEED_NUM_10G:
- default:
- goto error_invalid_config;
+
+ /* Set/reset the mac.autoneg based on the link speed,
+ * fixed or not
+ */
+ if (!autoneg) {
+ hw->mac.autoneg = 0;
+ hw->mac.forced_speed_duplex =
+ hw->phy.autoneg_advertised;
+ } else {
+ hw->mac.autoneg = 1;
+ }
}
+
e1000_setup_link(hw);
if (rte_intr_allow_others(intr_handle)) {
return 0;
error_invalid_config:
- PMD_INIT_LOG(ERR, "Invalid link_speed/link_duplex (%u/%u) for port %u",
- dev->data->dev_conf.link_speed,
- dev->data->dev_conf.link_duplex, dev->data->port_id);
+ PMD_INIT_LOG(ERR, "Invalid advertised speeds (%u) for port %u",
+ dev->data->dev_conf.link_speeds, dev->data->port_id);
em_dev_clear_queues(dev);
return -EINVAL;
}
{
struct rte_eth_link link;
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+ struct rte_pci_device *pci_dev = E1000_DEV_TO_PCI(dev);
+ struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
em_rxq_intr_disable(hw);
em_lsc_intr_disable(hw);
hw->fc.low_water = 0x5048;
hw->fc.pause_time = 0x0650;
hw->fc.refresh_time = 0x0400;
- } else if (hw->mac.type == e1000_pch_lpt) {
+ } else if (hw->mac.type == e1000_pch_lpt ||
+ hw->mac.type == e1000_pch_spt ||
+ hw->mac.type == e1000_pch_cnp) {
hw->fc.requested_mode = e1000_fc_full;
}
eth_em_rx_queue_intr_enable(struct rte_eth_dev *dev, __rte_unused uint16_t queue_id)
{
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct rte_pci_device *pci_dev = E1000_DEV_TO_PCI(dev);
+ struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
em_rxq_intr_enable(hw);
- rte_intr_enable(&dev->pci_dev->intr_handle);
+ rte_intr_enable(intr_handle);
return 0;
}
case e1000_ich10lan:
case e1000_pch2lan:
case e1000_pch_lpt:
+ case e1000_pch_spt:
+ case e1000_pch_cnp:
case e1000_82574:
case e1000_80003es2lan: /* 9K Jumbo Frame size */
case e1000_82583:
{
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ dev_info->pci_dev = RTE_DEV_TO_PCI(dev->device);
dev_info->min_rx_bufsize = 256; /* See BSIZE field of RCTL register. */
dev_info->max_rx_pktlen = em_get_max_pktlen(hw);
dev_info->max_mac_addrs = hw->mac.rar_entry_count;
.nb_max = E1000_MAX_RING_DESC,
.nb_min = E1000_MIN_RING_DESC,
.nb_align = EM_TXD_ALIGN,
+ .nb_seg_max = EM_TX_MAX_SEG,
+ .nb_mtu_seg_max = EM_TX_MAX_MTU_SEG,
};
dev_info->speed_capa = ETH_LINK_SPEED_10M_HD | ETH_LINK_SPEED_10M |
/* Now we check if a transition has happened */
if (link_check && (link.link_status == ETH_LINK_DOWN)) {
- hw->mac.ops.get_link_up_info(hw, &link.link_speed,
- &link.link_duplex);
+ uint16_t duplex, speed;
+ hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
+ link.link_duplex = (duplex == FULL_DUPLEX) ?
+ ETH_LINK_FULL_DUPLEX :
+ ETH_LINK_HALF_DUPLEX;
+ link.link_speed = speed;
link.link_status = ETH_LINK_UP;
+ link.link_autoneg = !(dev->data->dev_conf.link_speeds &
+ ETH_LINK_SPEED_FIXED);
} else if (!link_check && (link.link_status == ETH_LINK_UP)) {
link.link_speed = 0;
link.link_duplex = ETH_LINK_HALF_DUPLEX;
link.link_status = ETH_LINK_DOWN;
+ link.link_autoneg = ETH_LINK_SPEED_FIXED;
}
rte_em_dev_atomic_write_link_status(dev, &link);
* - On failure, a negative value.
*/
static int
-eth_em_interrupt_action(struct rte_eth_dev *dev)
+eth_em_interrupt_action(struct rte_eth_dev *dev,
+ struct rte_intr_handle *intr_handle)
{
+ struct rte_pci_device *pci_dev = E1000_DEV_TO_PCI(dev);
struct e1000_hw *hw =
E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct e1000_interrupt *intr =
return -1;
intr->flags &= ~E1000_FLAG_NEED_LINK_UPDATE;
- rte_intr_enable(&(dev->pci_dev->intr_handle));
+ rte_intr_enable(intr_handle);
/* set get_link_status to check register later */
hw->mac.get_link_status = 1;
PMD_INIT_LOG(INFO, " Port %d: Link Down", dev->data->port_id);
}
PMD_INIT_LOG(DEBUG, "PCI Address: %04d:%02d:%02d:%d",
- dev->pci_dev->addr.domain, dev->pci_dev->addr.bus,
- dev->pci_dev->addr.devid, dev->pci_dev->addr.function);
+ pci_dev->addr.domain, pci_dev->addr.bus,
+ pci_dev->addr.devid, pci_dev->addr.function);
tctl = E1000_READ_REG(hw, E1000_TCTL);
rctl = E1000_READ_REG(hw, E1000_RCTL);
* void
*/
static void
-eth_em_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
- void *param)
+eth_em_interrupt_handler(struct rte_intr_handle *handle,
+ void *param)
{
struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
eth_em_interrupt_get_status(dev);
- eth_em_interrupt_action(dev);
- _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC);
+ eth_em_interrupt_action(dev, handle);
+ _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
}
static int
return 0;
}
-struct rte_driver em_pmd_drv = {
- .type = PMD_PDEV,
- .init = rte_em_pmd_init,
-};
-
-PMD_REGISTER_DRIVER(em_pmd_drv);
+RTE_PMD_REGISTER_PCI(net_e1000_em, rte_em_pmd.pci_drv);
+RTE_PMD_REGISTER_PCI_TABLE(net_e1000_em, pci_id_em_map);
+RTE_PMD_REGISTER_KMOD_DEP(net_e1000_em, "* igb_uio | uio_pci_generic | vfio");