New upstream version 17.11.4
[deb_dpdk.git] / drivers / net / bonding / rte_eth_bond_pmd.c
index 1d3fbeb..8880231 100644 (file)
@@ -1912,7 +1912,7 @@ bond_ethdev_start(struct rte_eth_dev *eth_dev)
 
        if (internals->slave_count == 0) {
                RTE_BOND_LOG(ERR, "Cannot start port since there are no slave devices");
-               return -1;
+               goto out_err;
        }
 
        if (internals->user_defined_mac == 0) {
@@ -1923,19 +1923,15 @@ bond_ethdev_start(struct rte_eth_dev *eth_dev)
                                new_mac_addr = &internals->slaves[i].persisted_mac_addr;
 
                if (new_mac_addr == NULL)
-                       return -1;
+                       goto out_err;
 
                if (mac_address_set(eth_dev, new_mac_addr) != 0) {
                        RTE_BOND_LOG(ERR, "bonded port (%d) failed to update MAC address",
                                        eth_dev->data->port_id);
-                       return -1;
+                       goto out_err;
                }
        }
 
-       /* Update all slave devices MACs*/
-       if (mac_address_slaves_update(eth_dev) != 0)
-               return -1;
-
        /* If bonded device is configure in promiscuous mode then re-apply config */
        if (internals->promiscuous_en)
                bond_ethdev_promiscuous_enable(eth_dev);
@@ -1959,7 +1955,7 @@ bond_ethdev_start(struct rte_eth_dev *eth_dev)
                                "bonded port (%d) failed to reconfigure slave device (%d)",
                                eth_dev->data->port_id,
                                internals->slaves[i].port_id);
-                       return -1;
+                       goto out_err;
                }
                /* We will need to poll for link status if any slave doesn't
                 * support interrupts
@@ -1967,6 +1963,7 @@ bond_ethdev_start(struct rte_eth_dev *eth_dev)
                if (internals->slaves[i].link_status_poll_enabled)
                        internals->link_status_polling_enabled = 1;
        }
+
        /* start polling if needed */
        if (internals->link_status_polling_enabled) {
                rte_eal_alarm_set(
@@ -1975,6 +1972,10 @@ bond_ethdev_start(struct rte_eth_dev *eth_dev)
                        (void *)&rte_eth_devices[internals->port_id]);
        }
 
+       /* Update all slave devices MACs*/
+       if (mac_address_slaves_update(eth_dev) != 0)
+               goto out_err;
+
        if (internals->user_defined_primary_port)
                bond_ethdev_primary_set(internals, internals->primary_port);
 
@@ -1986,6 +1987,10 @@ bond_ethdev_start(struct rte_eth_dev *eth_dev)
                bond_tlb_enable(internals);
 
        return 0;
+
+out_err:
+       eth_dev->data->dev_started = 0;
+       return -1;
 }
 
 static void
@@ -2043,7 +2048,6 @@ bond_ethdev_stop(struct rte_eth_dev *eth_dev)
                        tlb_last_obytets[internals->active_slaves[i]] = 0;
        }
 
-       internals->active_slave_count = 0;
        internals->link_status_polling_enabled = 0;
        for (i = 0; i < internals->slave_count; i++)
                internals->slaves[i].last_link_status = 0;
@@ -2519,6 +2523,11 @@ bond_ethdev_lsc_event_callback(uint16_t port_id, enum rte_eth_event_type type,
        if (!valid_slave)
                return rc;
 
+       /* Synchronize lsc callback parallel calls either by real link event
+        * from the slaves PMDs or by the bonding PMD itself.
+        */
+       rte_spinlock_lock(&internals->lsc_lock);
+
        /* Search for port in active port list */
        active_pos = find_slave_by_id(internals->active_slaves,
                        internals->active_slave_count, port_id);
@@ -2526,7 +2535,7 @@ bond_ethdev_lsc_event_callback(uint16_t port_id, enum rte_eth_event_type type,
        rte_eth_link_get_nowait(port_id, &link);
        if (link.link_status) {
                if (active_pos < internals->active_slave_count)
-                       return rc;
+                       goto link_update;
 
                /* if no active slave ports then set this port to be primary port */
                if (internals->active_slave_count < 1) {
@@ -2546,7 +2555,7 @@ bond_ethdev_lsc_event_callback(uint16_t port_id, enum rte_eth_event_type type,
                        bond_ethdev_primary_set(internals, port_id);
        } else {
                if (active_pos == internals->active_slave_count)
-                       return rc;
+                       goto link_update;
 
                /* Remove from active slave list */
                deactivate_slave(bonded_eth_dev, port_id);
@@ -2565,6 +2574,7 @@ bond_ethdev_lsc_event_callback(uint16_t port_id, enum rte_eth_event_type type,
                }
        }
 
+link_update:
        /**
         * Update bonded device link properties after any change to active
         * slaves
@@ -2599,7 +2609,10 @@ bond_ethdev_lsc_event_callback(uint16_t port_id, enum rte_eth_event_type type,
                                                NULL, NULL);
                }
        }
-       return 0;
+
+       rte_spinlock_unlock(&internals->lsc_lock);
+
+       return rc;
 }
 
 static int
@@ -2766,6 +2779,7 @@ bond_alloc(struct rte_vdev_device *dev, uint8_t mode)
        eth_dev->data->dev_flags = RTE_ETH_DEV_INTR_LSC;
 
        rte_spinlock_init(&internals->lock);
+       rte_spinlock_init(&internals->lsc_lock);
 
        internals->port_id = eth_dev->data->port_id;
        internals->mode = BONDING_MODE_INVALID;
@@ -2967,6 +2981,10 @@ bond_remove(struct rte_vdev_device *dev)
        eth_dev->tx_pkt_burst = NULL;
 
        internals = eth_dev->data->dev_private;
+       /* Try to release mempool used in mode6. If the bond
+        * device is not mode6, free the NULL is not problem.
+        */
+       rte_mempool_free(internals->mode6.mempool);
        rte_bitmap_free(internals->vlan_filter_bmp);
        rte_free(internals->vlan_filter_bmpmem);
        rte_free(eth_dev->data->dev_private);