net/qede/base: use function pointers for spq async callback
[dpdk.git] / drivers / net / bonding / rte_eth_bond_pmd.c
index de9f9c7..d783320 100644 (file)
@@ -175,12 +175,13 @@ const struct rte_flow_attr flow_attr_8023ad = {
 int
 bond_ethdev_8023ad_flow_verify(struct rte_eth_dev *bond_dev,
                uint8_t slave_port) {
+       struct rte_eth_dev_info slave_info;
        struct rte_flow_error error;
        struct bond_dev_private *internals = (struct bond_dev_private *)
                        (bond_dev->data->dev_private);
 
-       struct rte_flow_action_queue lacp_queue_conf = {
-               .index = internals->mode4.dedicated_queues.rx_qid,
+       const struct rte_flow_action_queue lacp_queue_conf = {
+               .index = 0,
        };
 
        const struct rte_flow_action actions[] = {
@@ -195,8 +196,21 @@ bond_ethdev_8023ad_flow_verify(struct rte_eth_dev *bond_dev,
 
        int ret = rte_flow_validate(slave_port, &flow_attr_8023ad,
                        flow_item_8023ad, actions, &error);
-       if (ret < 0)
+       if (ret < 0) {
+               RTE_BOND_LOG(ERR, "%s: %s (slave_port=%d queue_id=%d)",
+                               __func__, error.message, slave_port,
+                               internals->mode4.dedicated_queues.rx_qid);
                return -1;
+       }
+
+       rte_eth_dev_info_get(slave_port, &slave_info);
+       if (slave_info.max_rx_queues < bond_dev->data->nb_rx_queues ||
+                       slave_info.max_tx_queues < bond_dev->data->nb_tx_queues) {
+               RTE_BOND_LOG(ERR,
+                       "%s: Slave %d capabilities doesn't allow to allocate additional queues",
+                       __func__, slave_port);
+               return -1;
+       }
 
        return 0;
 }
@@ -206,7 +220,7 @@ bond_8023ad_slow_pkt_hw_filter_supported(uint8_t port_id) {
        struct rte_eth_dev *bond_dev = &rte_eth_devices[port_id];
        struct bond_dev_private *internals = (struct bond_dev_private *)
                        (bond_dev->data->dev_private);
-       struct rte_eth_dev_info bond_info, slave_info;
+       struct rte_eth_dev_info bond_info;
        uint8_t idx;
 
        /* Verify if all slaves in bonding supports flow director and */
@@ -217,9 +231,6 @@ bond_8023ad_slow_pkt_hw_filter_supported(uint8_t port_id) {
                internals->mode4.dedicated_queues.tx_qid = bond_info.nb_tx_queues;
 
                for (idx = 0; idx < internals->slave_count; idx++) {
-                       rte_eth_dev_info_get(internals->slaves[idx].port_id,
-                                       &slave_info);
-
                        if (bond_ethdev_8023ad_flow_verify(bond_dev,
                                        internals->slaves[idx].port_id) != 0)
                                return -1;
@@ -1386,39 +1397,44 @@ bond_ethdev_tx_burst_broadcast(void *queue, struct rte_mbuf **bufs,
 }
 
 void
-link_properties_set(struct rte_eth_dev *bonded_eth_dev,
-               struct rte_eth_link *slave_dev_link)
+link_properties_set(struct rte_eth_dev *ethdev, struct rte_eth_link *slave_link)
 {
-       struct rte_eth_link *bonded_dev_link = &bonded_eth_dev->data->dev_link;
-       struct bond_dev_private *internals = bonded_eth_dev->data->dev_private;
+       struct bond_dev_private *bond_ctx = ethdev->data->dev_private;
 
-       if (slave_dev_link->link_status &&
-               bonded_eth_dev->data->dev_started) {
-               bonded_dev_link->link_duplex = slave_dev_link->link_duplex;
-               bonded_dev_link->link_speed = slave_dev_link->link_speed;
+       if (bond_ctx->mode == BONDING_MODE_8023AD) {
+               /**
+                * If in mode 4 then save the link properties of the first
+                * slave, all subsequent slaves must match these properties
+                */
+               struct rte_eth_link *bond_link = &bond_ctx->mode4.slave_link;
 
-               internals->link_props_set = 1;
+               bond_link->link_autoneg = slave_link->link_autoneg;
+               bond_link->link_duplex = slave_link->link_duplex;
+               bond_link->link_speed = slave_link->link_speed;
+       } else {
+               /**
+                * In any other mode the link properties are set to default
+                * values of AUTONEG/DUPLEX
+                */
+               ethdev->data->dev_link.link_autoneg = ETH_LINK_AUTONEG;
+               ethdev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX;
        }
 }
 
-void
-link_properties_reset(struct rte_eth_dev *bonded_eth_dev)
+int
+link_properties_valid(struct rte_eth_dev *ethdev,
+               struct rte_eth_link *slave_link)
 {
-       struct bond_dev_private *internals = bonded_eth_dev->data->dev_private;
+       struct bond_dev_private *bond_ctx = ethdev->data->dev_private;
 
-       memset(&(bonded_eth_dev->data->dev_link), 0,
-                       sizeof(bonded_eth_dev->data->dev_link));
+       if (bond_ctx->mode == BONDING_MODE_8023AD) {
+               struct rte_eth_link *bond_link = &bond_ctx->mode4.slave_link;
 
-       internals->link_props_set = 0;
-}
-
-int
-link_properties_valid(struct rte_eth_link *bonded_dev_link,
-               struct rte_eth_link *slave_dev_link)
-{
-       if (bonded_dev_link->link_duplex != slave_dev_link->link_duplex ||
-               bonded_dev_link->link_speed !=  slave_dev_link->link_speed)
-               return -1;
+               if (bond_link->link_duplex != slave_link->link_duplex ||
+                       bond_link->link_autoneg != slave_link->link_autoneg ||
+                       bond_link->link_speed != slave_link->link_speed)
+                       return -1;
+       }
 
        return 0;
 }
@@ -2270,36 +2286,90 @@ bond_ethdev_slave_link_status_change_monitor(void *cb_arg)
 }
 
 static int
-bond_ethdev_link_update(struct rte_eth_dev *bonded_eth_dev,
-               int wait_to_complete)
+bond_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
 {
-       struct bond_dev_private *internals = bonded_eth_dev->data->dev_private;
+       void (*link_update)(uint8_t port_id, struct rte_eth_link *eth_link);
+
+       struct bond_dev_private *bond_ctx;
+       struct rte_eth_link slave_link;
 
-       if (!bonded_eth_dev->data->dev_started ||
-               internals->active_slave_count == 0) {
-               bonded_eth_dev->data->dev_link.link_status = ETH_LINK_DOWN;
+       uint32_t idx;
+
+       bond_ctx = ethdev->data->dev_private;
+
+       ethdev->data->dev_link.link_speed = ETH_SPEED_NUM_NONE;
+
+       if (ethdev->data->dev_started == 0 ||
+                       bond_ctx->active_slave_count == 0) {
+               ethdev->data->dev_link.link_status = ETH_LINK_DOWN;
                return 0;
-       } else {
-               struct rte_eth_dev *slave_eth_dev;
-               int i, link_up = 0;
+       }
 
-               for (i = 0; i < internals->active_slave_count; i++) {
-                       slave_eth_dev = &rte_eth_devices[internals->active_slaves[i]];
+       ethdev->data->dev_link.link_status = ETH_LINK_UP;
 
-                       (*slave_eth_dev->dev_ops->link_update)(slave_eth_dev,
-                                       wait_to_complete);
-                       if (slave_eth_dev->data->dev_link.link_status == ETH_LINK_UP) {
-                               link_up = 1;
-                               break;
-                       }
+       if (wait_to_complete)
+               link_update = rte_eth_link_get;
+       else
+               link_update = rte_eth_link_get_nowait;
+
+       switch (bond_ctx->mode) {
+       case BONDING_MODE_BROADCAST:
+               /**
+                * Setting link speed to UINT32_MAX to ensure we pick up the
+                * value of the first active slave
+                */
+               ethdev->data->dev_link.link_speed = UINT32_MAX;
+
+               /**
+                * link speed is minimum value of all the slaves link speed as
+                * packet loss will occur on this slave if transmission at rates
+                * greater than this are attempted
+                */
+               for (idx = 1; idx < bond_ctx->active_slave_count; idx++) {
+                       link_update(bond_ctx->active_slaves[0], &slave_link);
+
+                       if (slave_link.link_speed <
+                                       ethdev->data->dev_link.link_speed)
+                               ethdev->data->dev_link.link_speed =
+                                               slave_link.link_speed;
                }
+               break;
+       case BONDING_MODE_ACTIVE_BACKUP:
+               /* Current primary slave */
+               link_update(bond_ctx->current_primary_port, &slave_link);
+
+               ethdev->data->dev_link.link_speed = slave_link.link_speed;
+               break;
+       case BONDING_MODE_8023AD:
+               ethdev->data->dev_link.link_autoneg =
+                               bond_ctx->mode4.slave_link.link_autoneg;
+               ethdev->data->dev_link.link_duplex =
+                               bond_ctx->mode4.slave_link.link_duplex;
+               /* fall through to update link speed */
+       case BONDING_MODE_ROUND_ROBIN:
+       case BONDING_MODE_BALANCE:
+       case BONDING_MODE_TLB:
+       case BONDING_MODE_ALB:
+       default:
+               /**
+                * In theses mode the maximum theoretical link speed is the sum
+                * of all the slaves
+                */
+               ethdev->data->dev_link.link_speed = ETH_SPEED_NUM_NONE;
+
+               for (idx = 0; idx < bond_ctx->active_slave_count; idx++) {
+                       link_update(bond_ctx->active_slaves[idx], &slave_link);
 
-               bonded_eth_dev->data->dev_link.link_status = link_up;
+                       ethdev->data->dev_link.link_speed +=
+                                       slave_link.link_speed;
+               }
        }
 
+
        return 0;
 }
 
+
 static void
 bond_ethdev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 {
@@ -2410,7 +2480,7 @@ int
 bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,
                void *param, void *ret_param __rte_unused)
 {
-       struct rte_eth_dev *bonded_eth_dev, *slave_eth_dev;
+       struct rte_eth_dev *bonded_eth_dev;
        struct bond_dev_private *internals;
        struct rte_eth_link link;
        int rc = -1;
@@ -2423,7 +2493,6 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,
                return rc;
 
        bonded_eth_dev = &rte_eth_devices[*(uint8_t *)param];
-       slave_eth_dev = &rte_eth_devices[port_id];
 
        if (check_for_bonded_ethdev(bonded_eth_dev))
                return rc;
@@ -2462,20 +2531,6 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,
                        lsc_flag = 1;
 
                        mac_address_slaves_update(bonded_eth_dev);
-
-                       /* Inherit eth dev link properties from first active slave */
-                       link_properties_set(bonded_eth_dev,
-                                       &(slave_eth_dev->data->dev_link));
-               } else {
-                       if (link_properties_valid(
-                               &bonded_eth_dev->data->dev_link, &link) != 0) {
-                               slave_eth_dev->data->dev_flags &=
-                                       (~RTE_ETH_DEV_BONDED_SLAVE);
-                               RTE_LOG(ERR, PMD,
-                                       "port %u invalid speed/duplex\n",
-                                       port_id);
-                               return rc;
-                       }
                }
 
                activate_slave(bonded_eth_dev, port_id);
@@ -2491,14 +2546,8 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,
                /* Remove from active slave list */
                deactivate_slave(bonded_eth_dev, port_id);
 
-               /* No active slaves, change link status to down and reset other
-                * link properties */
-               if (internals->active_slave_count < 1) {
+               if (internals->active_slave_count < 1)
                        lsc_flag = 1;
-                       bonded_eth_dev->data->dev_link.link_status = ETH_LINK_DOWN;
-
-                       link_properties_reset(bonded_eth_dev);
-               }
 
                /* Update primary id, take first active slave from list or if none
                 * available set to -1 */
@@ -2511,6 +2560,12 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,
                }
        }
 
+       /**
+        * Update bonded device link properties after any change to active
+        * slaves
+        */
+       bond_ethdev_link_update(bonded_eth_dev, 0);
+
        if (lsc_flag) {
                /* Cancel any possible outstanding interrupts if delays are enabled */
                if (internals->link_up_delay_ms > 0 ||
@@ -2714,7 +2769,6 @@ bond_alloc(struct rte_vdev_device *dev, uint8_t mode)
        internals->balance_xmit_policy = BALANCE_XMIT_POLICY_LAYER2;
        internals->xmit_hash = xmit_l2_hash;
        internals->user_defined_mac = 0;
-       internals->link_props_set = 0;
 
        internals->link_status_polling_enabled = 0;
 
@@ -2782,7 +2836,7 @@ bond_probe(struct rte_vdev_device *dev)
        const char *name;
        struct bond_dev_private *internals;
        struct rte_kvargs *kvlist;
-       uint8_t bonding_mode, socket_id;
+       uint8_t bonding_mode, socket_id/*, agg_mode*/;
        int  arg_count, port_id;
 
        if (!dev)
@@ -2909,6 +2963,7 @@ bond_ethdev_configure(struct rte_eth_dev *dev)
        struct rte_kvargs *kvlist = internals->kvlist;
        int arg_count;
        uint8_t port_id = dev - rte_eth_devices;
+       uint8_t agg_mode;
 
        static const uint8_t default_rss_key[40] = {
                0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, 0x41, 0x67, 0x25, 0x3D,
@@ -2996,6 +3051,21 @@ bond_ethdev_configure(struct rte_eth_dev *dev)
                return -1;
        }
 
+       if (rte_kvargs_count(kvlist, PMD_BOND_AGG_MODE_KVARG) == 1) {
+               if (rte_kvargs_process(kvlist,
+                               PMD_BOND_AGG_MODE_KVARG,
+                               &bond_ethdev_parse_slave_agg_mode_kvarg,
+                               &agg_mode) != 0) {
+                       RTE_LOG(ERR, EAL,
+                                       "Failed to parse agg selection mode for bonded device %s\n",
+                                       name);
+               }
+               if (internals->mode == BONDING_MODE_8023AD)
+                       if (agg_mode != 0)
+                               rte_eth_bond_8023ad_agg_selection_set(port_id,
+                                               agg_mode);
+       }
+
        /* Parse/add slave ports to bonded device */
        if (rte_kvargs_count(kvlist, PMD_BOND_SLAVE_PORT_KVARG) > 0) {
                struct bond_ethdev_slave_ports slave_ports;
@@ -3159,6 +3229,7 @@ RTE_PMD_REGISTER_PARAM_STRING(net_bonding,
        "primary=<ifc> "
        "mode=[0-6] "
        "xmit_policy=[l2 | l23 | l34] "
+       "agg_mode=[count | stable | bandwidth] "
        "socket_id=<int> "
        "mac=<mac addr> "
        "lsc_poll_period_ms=<int> "