fm10k: fix Tx queue cleaning after start error
[dpdk.git] / drivers / net / e1000 / em_ethdev.c
index 9960c70..912f5dd 100644 (file)
@@ -116,6 +116,10 @@ static void eth_em_rar_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
                uint32_t index, uint32_t pool);
 static void eth_em_rar_clear(struct rte_eth_dev *dev, uint32_t index);
 
+static int eth_em_set_mc_addr_list(struct rte_eth_dev *dev,
+                                  struct ether_addr *mc_addr_set,
+                                  uint32_t nb_mc_addr);
+
 #define EM_FC_PAUSE_TIME 0x0680
 #define EM_LINK_UPDATE_CHECK_TIMEOUT  90  /* 9s */
 #define EM_LINK_UPDATE_CHECK_INTERVAL 100 /* ms */
@@ -161,6 +165,7 @@ static const struct eth_dev_ops eth_em_ops = {
        .flow_ctrl_set        = eth_em_flow_ctrl_set,
        .mac_addr_add         = eth_em_rar_set,
        .mac_addr_remove      = eth_em_rar_clear,
+       .set_mc_addr_list     = eth_em_set_mc_addr_list,
 };
 
 /**
@@ -219,6 +224,8 @@ static int
 eth_em_dev_init(struct rte_eth_dev *eth_dev)
 {
        struct rte_pci_device *pci_dev;
+       struct e1000_adapter *adapter =
+               E1000_DEV_PRIVATE(eth_dev->data->dev_private);
        struct e1000_hw *hw =
                E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
        struct e1000_vfta * shadow_vfta =
@@ -241,6 +248,7 @@ eth_em_dev_init(struct rte_eth_dev *eth_dev)
 
        hw->hw_addr = (void *)pci_dev->mem_resource[0].addr;
        hw->device_id = pci_dev->id.device_id;
+       adapter->stopped = 0;
 
        /* For ICH8 support we'll need to map the flash memory BAR */
 
@@ -270,7 +278,7 @@ eth_em_dev_init(struct rte_eth_dev *eth_dev)
        /* initialize the vfta */
        memset(shadow_vfta, 0, sizeof(*shadow_vfta));
 
-       PMD_INIT_LOG(INFO, "port_id %d vendorID=0x%x deviceID=0x%x",
+       PMD_INIT_LOG(DEBUG, "port_id %d vendorID=0x%x deviceID=0x%x",
                     eth_dev->data->port_id, pci_dev->id.vendor_id,
                     pci_dev->id.device_id);
 
@@ -280,13 +288,47 @@ eth_em_dev_init(struct rte_eth_dev *eth_dev)
        return (0);
 }
 
+static int
+eth_em_dev_uninit(struct rte_eth_dev *eth_dev)
+{
+       struct rte_pci_device *pci_dev;
+       struct e1000_adapter *adapter =
+               E1000_DEV_PRIVATE(eth_dev->data->dev_private);
+
+       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->dev_ops = NULL;
+       eth_dev->rx_pkt_burst = NULL;
+       eth_dev->tx_pkt_burst = NULL;
+
+       rte_free(eth_dev->data->mac_addrs);
+       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);
+
+       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,
+               .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
+                       RTE_PCI_DRV_DETACHABLE,
        },
        .eth_dev_init = eth_em_dev_init,
+       .eth_dev_uninit = eth_em_dev_uninit,
        .dev_private_size = sizeof(struct e1000_adapter),
 };
 
@@ -446,6 +488,8 @@ em_set_pba(struct e1000_hw *hw)
 static int
 eth_em_start(struct rte_eth_dev *dev)
 {
+       struct e1000_adapter *adapter =
+               E1000_DEV_PRIVATE(dev->data->dev_private);
        struct e1000_hw *hw =
                E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        int ret, mask;
@@ -565,6 +609,8 @@ eth_em_start(struct rte_eth_dev *dev)
                }
        }
 
+       adapter->stopped = 0;
+
        PMD_INIT_LOG(DEBUG, "<<");
 
        return (0);
@@ -608,8 +654,12 @@ static void
 eth_em_close(struct rte_eth_dev *dev)
 {
        struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct e1000_adapter *adapter =
+               E1000_DEV_PRIVATE(dev->data->dev_private);
 
        eth_em_stop(dev);
+       adapter->stopped = 1;
+       em_dev_free_queues(dev);
        e1000_phy_hw_reset(hw);
        em_release_manageability(hw);
        em_hw_control_release(hw);
@@ -843,11 +893,11 @@ em_get_max_pktlen(const struct e1000_hw *hw)
        case e1000_pch2lan:
        case e1000_82574:
        case e1000_80003es2lan: /* 9K Jumbo Frame size */
+       case e1000_82583:
                return (0x2412);
        case e1000_pchlan:
                return (0x1000);
        /* Adapters that do not support jumbo frames */
-       case e1000_82583:
        case e1000_ich8lan:
                return (ETHER_MAX_LEN);
        default:
@@ -1300,9 +1350,10 @@ eth_em_interrupt_action(struct rte_eth_dev *dev)
        } else {
                PMD_INIT_LOG(INFO, " Port %d: Link Down", dev->data->port_id);
        }
-       PMD_INIT_LOG(INFO, "PCI Address: %04d:%02d:%02d:%d",
+       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);
+
        tctl = E1000_READ_REG(hw, E1000_TCTL);
        rctl = E1000_READ_REG(hw, E1000_RCTL);
        if (link.link_status) {
@@ -1522,6 +1573,18 @@ eth_em_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
        return 0;
 }
 
+static int
+eth_em_set_mc_addr_list(struct rte_eth_dev *dev,
+                       struct ether_addr *mc_addr_set,
+                       uint32_t nb_mc_addr)
+{
+       struct e1000_hw *hw;
+
+       hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       e1000_update_mc_addr_list(hw, (u8 *)mc_addr_set, nb_mc_addr);
+       return 0;
+}
+
 struct rte_driver em_pmd_drv = {
        .type = PMD_PDEV,
        .init = rte_em_pmd_init,