1ebea83f8SGaetan Rivet /*- 2ebea83f8SGaetan Rivet * BSD LICENSE 3ebea83f8SGaetan Rivet * 4ebea83f8SGaetan Rivet * Copyright 2017 6WIND S.A. 5ebea83f8SGaetan Rivet * Copyright 2017 Mellanox. 6ebea83f8SGaetan Rivet * 7ebea83f8SGaetan Rivet * Redistribution and use in source and binary forms, with or without 8ebea83f8SGaetan Rivet * modification, are permitted provided that the following conditions 9ebea83f8SGaetan Rivet * are met: 10ebea83f8SGaetan Rivet * 11ebea83f8SGaetan Rivet * * Redistributions of source code must retain the above copyright 12ebea83f8SGaetan Rivet * notice, this list of conditions and the following disclaimer. 13ebea83f8SGaetan Rivet * * Redistributions in binary form must reproduce the above copyright 14ebea83f8SGaetan Rivet * notice, this list of conditions and the following disclaimer in 15ebea83f8SGaetan Rivet * the documentation and/or other materials provided with the 16ebea83f8SGaetan Rivet * distribution. 17ebea83f8SGaetan Rivet * * Neither the name of 6WIND S.A. nor the names of its 18ebea83f8SGaetan Rivet * contributors may be used to endorse or promote products derived 19ebea83f8SGaetan Rivet * from this software without specific prior written permission. 20ebea83f8SGaetan Rivet * 21ebea83f8SGaetan Rivet * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22ebea83f8SGaetan Rivet * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23ebea83f8SGaetan Rivet * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24ebea83f8SGaetan Rivet * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25ebea83f8SGaetan Rivet * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26ebea83f8SGaetan Rivet * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27ebea83f8SGaetan Rivet * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28ebea83f8SGaetan Rivet * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29ebea83f8SGaetan Rivet * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30ebea83f8SGaetan Rivet * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31ebea83f8SGaetan Rivet * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32ebea83f8SGaetan Rivet */ 33ebea83f8SGaetan Rivet 34ebea83f8SGaetan Rivet #include <unistd.h> 35ebea83f8SGaetan Rivet 36b737a1eeSGaetan Rivet #include <rte_flow.h> 37b737a1eeSGaetan Rivet #include <rte_flow_driver.h> 38b737a1eeSGaetan Rivet 39ebea83f8SGaetan Rivet #include "failsafe_private.h" 40ebea83f8SGaetan Rivet 41b737a1eeSGaetan Rivet /** Print a message out of a flow error. */ 42b737a1eeSGaetan Rivet static int 43b737a1eeSGaetan Rivet fs_flow_complain(struct rte_flow_error *error) 44b737a1eeSGaetan Rivet { 45b737a1eeSGaetan Rivet static const char *const errstrlist[] = { 46b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_NONE] = "no error", 47b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_UNSPECIFIED] = "cause unspecified", 48b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_HANDLE] = "flow rule (handle)", 49b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ATTR_GROUP] = "group field", 50b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY] = "priority field", 51b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ATTR_INGRESS] = "ingress field", 52b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ATTR_EGRESS] = "egress field", 53b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ATTR] = "attributes structure", 54b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ITEM_NUM] = "pattern length", 55b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ITEM] = "specific pattern item", 56b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ACTION_NUM] = "number of actions", 57b737a1eeSGaetan Rivet [RTE_FLOW_ERROR_TYPE_ACTION] = "specific action", 58b737a1eeSGaetan Rivet }; 59b737a1eeSGaetan Rivet const char *errstr; 60b737a1eeSGaetan Rivet char buf[32]; 61b737a1eeSGaetan Rivet int err = rte_errno; 62b737a1eeSGaetan Rivet 63b737a1eeSGaetan Rivet if ((unsigned int)error->type >= RTE_DIM(errstrlist) || 64b737a1eeSGaetan Rivet !errstrlist[error->type]) 65b737a1eeSGaetan Rivet errstr = "unknown type"; 66b737a1eeSGaetan Rivet else 67b737a1eeSGaetan Rivet errstr = errstrlist[error->type]; 68b737a1eeSGaetan Rivet ERROR("Caught error type %d (%s): %s%s\n", 69b737a1eeSGaetan Rivet error->type, errstr, 70b737a1eeSGaetan Rivet error->cause ? (snprintf(buf, sizeof(buf), "cause: %p, ", 71b737a1eeSGaetan Rivet error->cause), buf) : "", 72b737a1eeSGaetan Rivet error->message ? error->message : "(no stated reason)"); 73b737a1eeSGaetan Rivet return -err; 74b737a1eeSGaetan Rivet } 75b737a1eeSGaetan Rivet 76ebea83f8SGaetan Rivet static int 772cc52cd7SGaetan Rivet eth_dev_flow_isolate_set(struct rte_eth_dev *dev, 782cc52cd7SGaetan Rivet struct sub_device *sdev) 792cc52cd7SGaetan Rivet { 802cc52cd7SGaetan Rivet struct rte_flow_error ferror; 812cc52cd7SGaetan Rivet int ret; 822cc52cd7SGaetan Rivet 832cc52cd7SGaetan Rivet if (!PRIV(dev)->flow_isolated) { 842cc52cd7SGaetan Rivet DEBUG("Flow isolation already disabled"); 852cc52cd7SGaetan Rivet } else { 862cc52cd7SGaetan Rivet DEBUG("Enabling flow isolation"); 872cc52cd7SGaetan Rivet ret = rte_flow_isolate(PORT_ID(sdev), 882cc52cd7SGaetan Rivet PRIV(dev)->flow_isolated, 892cc52cd7SGaetan Rivet &ferror); 902cc52cd7SGaetan Rivet if (ret) { 912cc52cd7SGaetan Rivet fs_flow_complain(&ferror); 922cc52cd7SGaetan Rivet return ret; 932cc52cd7SGaetan Rivet } 942cc52cd7SGaetan Rivet } 952cc52cd7SGaetan Rivet return 0; 962cc52cd7SGaetan Rivet } 972cc52cd7SGaetan Rivet 982cc52cd7SGaetan Rivet static int 99ebea83f8SGaetan Rivet fs_eth_dev_conf_apply(struct rte_eth_dev *dev, 100ebea83f8SGaetan Rivet struct sub_device *sdev) 101ebea83f8SGaetan Rivet { 102ebea83f8SGaetan Rivet struct rte_eth_dev *edev; 103ebea83f8SGaetan Rivet struct rte_vlan_filter_conf *vfc1; 104ebea83f8SGaetan Rivet struct rte_vlan_filter_conf *vfc2; 105b737a1eeSGaetan Rivet struct rte_flow *flow; 106b737a1eeSGaetan Rivet struct rte_flow_error ferror; 107ebea83f8SGaetan Rivet uint32_t i; 108ebea83f8SGaetan Rivet int ret; 109ebea83f8SGaetan Rivet 110ebea83f8SGaetan Rivet edev = ETH(sdev); 111ebea83f8SGaetan Rivet /* RX queue setup */ 112ebea83f8SGaetan Rivet for (i = 0; i < dev->data->nb_rx_queues; i++) { 113ebea83f8SGaetan Rivet struct rxq *rxq; 114ebea83f8SGaetan Rivet 115ebea83f8SGaetan Rivet rxq = dev->data->rx_queues[i]; 116ebea83f8SGaetan Rivet ret = rte_eth_rx_queue_setup(PORT_ID(sdev), i, 117ebea83f8SGaetan Rivet rxq->info.nb_desc, rxq->socket_id, 118ebea83f8SGaetan Rivet &rxq->info.conf, rxq->info.mp); 119ebea83f8SGaetan Rivet if (ret) { 120ebea83f8SGaetan Rivet ERROR("rx_queue_setup failed"); 121ebea83f8SGaetan Rivet return ret; 122ebea83f8SGaetan Rivet } 123ebea83f8SGaetan Rivet } 124ebea83f8SGaetan Rivet /* TX queue setup */ 125ebea83f8SGaetan Rivet for (i = 0; i < dev->data->nb_tx_queues; i++) { 126ebea83f8SGaetan Rivet struct txq *txq; 127ebea83f8SGaetan Rivet 128ebea83f8SGaetan Rivet txq = dev->data->tx_queues[i]; 129ebea83f8SGaetan Rivet ret = rte_eth_tx_queue_setup(PORT_ID(sdev), i, 130ebea83f8SGaetan Rivet txq->info.nb_desc, txq->socket_id, 131ebea83f8SGaetan Rivet &txq->info.conf); 132ebea83f8SGaetan Rivet if (ret) { 133ebea83f8SGaetan Rivet ERROR("tx_queue_setup failed"); 134ebea83f8SGaetan Rivet return ret; 135ebea83f8SGaetan Rivet } 136ebea83f8SGaetan Rivet } 137ebea83f8SGaetan Rivet /* dev_link.link_status */ 138ebea83f8SGaetan Rivet if (dev->data->dev_link.link_status != 139ebea83f8SGaetan Rivet edev->data->dev_link.link_status) { 140ebea83f8SGaetan Rivet DEBUG("Configuring link_status"); 141ebea83f8SGaetan Rivet if (dev->data->dev_link.link_status) 142ebea83f8SGaetan Rivet ret = rte_eth_dev_set_link_up(PORT_ID(sdev)); 143ebea83f8SGaetan Rivet else 144ebea83f8SGaetan Rivet ret = rte_eth_dev_set_link_down(PORT_ID(sdev)); 145ebea83f8SGaetan Rivet if (ret) { 146ebea83f8SGaetan Rivet ERROR("Failed to apply link_status"); 147ebea83f8SGaetan Rivet return ret; 148ebea83f8SGaetan Rivet } 149ebea83f8SGaetan Rivet } else { 150ebea83f8SGaetan Rivet DEBUG("link_status already set"); 151ebea83f8SGaetan Rivet } 152ebea83f8SGaetan Rivet /* promiscuous */ 153ebea83f8SGaetan Rivet if (dev->data->promiscuous != edev->data->promiscuous) { 154ebea83f8SGaetan Rivet DEBUG("Configuring promiscuous"); 155ebea83f8SGaetan Rivet if (dev->data->promiscuous) 156ebea83f8SGaetan Rivet rte_eth_promiscuous_enable(PORT_ID(sdev)); 157ebea83f8SGaetan Rivet else 158ebea83f8SGaetan Rivet rte_eth_promiscuous_disable(PORT_ID(sdev)); 159ebea83f8SGaetan Rivet } else { 160ebea83f8SGaetan Rivet DEBUG("promiscuous already set"); 161ebea83f8SGaetan Rivet } 162ebea83f8SGaetan Rivet /* all_multicast */ 163ebea83f8SGaetan Rivet if (dev->data->all_multicast != edev->data->all_multicast) { 164ebea83f8SGaetan Rivet DEBUG("Configuring all_multicast"); 165ebea83f8SGaetan Rivet if (dev->data->all_multicast) 166ebea83f8SGaetan Rivet rte_eth_allmulticast_enable(PORT_ID(sdev)); 167ebea83f8SGaetan Rivet else 168ebea83f8SGaetan Rivet rte_eth_allmulticast_disable(PORT_ID(sdev)); 169ebea83f8SGaetan Rivet } else { 170ebea83f8SGaetan Rivet DEBUG("all_multicast already set"); 171ebea83f8SGaetan Rivet } 172ebea83f8SGaetan Rivet /* MTU */ 173ebea83f8SGaetan Rivet if (dev->data->mtu != edev->data->mtu) { 174ebea83f8SGaetan Rivet DEBUG("Configuring MTU"); 175ebea83f8SGaetan Rivet ret = rte_eth_dev_set_mtu(PORT_ID(sdev), dev->data->mtu); 176ebea83f8SGaetan Rivet if (ret) { 177ebea83f8SGaetan Rivet ERROR("Failed to apply MTU"); 178ebea83f8SGaetan Rivet return ret; 179ebea83f8SGaetan Rivet } 180ebea83f8SGaetan Rivet } else { 181ebea83f8SGaetan Rivet DEBUG("MTU already set"); 182ebea83f8SGaetan Rivet } 183ebea83f8SGaetan Rivet /* default MAC */ 184ebea83f8SGaetan Rivet DEBUG("Configuring default MAC address"); 185ebea83f8SGaetan Rivet ret = rte_eth_dev_default_mac_addr_set(PORT_ID(sdev), 186ebea83f8SGaetan Rivet &dev->data->mac_addrs[0]); 187ebea83f8SGaetan Rivet if (ret) { 188ebea83f8SGaetan Rivet ERROR("Setting default MAC address failed"); 189ebea83f8SGaetan Rivet return ret; 190ebea83f8SGaetan Rivet } 191ebea83f8SGaetan Rivet /* additional MAC */ 192ebea83f8SGaetan Rivet if (PRIV(dev)->nb_mac_addr > 1) 193ebea83f8SGaetan Rivet DEBUG("Configure additional MAC address%s", 194ebea83f8SGaetan Rivet (PRIV(dev)->nb_mac_addr > 2 ? "es" : "")); 195ebea83f8SGaetan Rivet for (i = 1; i < PRIV(dev)->nb_mac_addr; i++) { 196ebea83f8SGaetan Rivet struct ether_addr *ea; 197ebea83f8SGaetan Rivet 198ebea83f8SGaetan Rivet ea = &dev->data->mac_addrs[i]; 199ebea83f8SGaetan Rivet ret = rte_eth_dev_mac_addr_add(PORT_ID(sdev), ea, 200ebea83f8SGaetan Rivet PRIV(dev)->mac_addr_pool[i]); 201ebea83f8SGaetan Rivet if (ret) { 202ebea83f8SGaetan Rivet char ea_fmt[ETHER_ADDR_FMT_SIZE]; 203ebea83f8SGaetan Rivet 204ebea83f8SGaetan Rivet ether_format_addr(ea_fmt, ETHER_ADDR_FMT_SIZE, ea); 205ebea83f8SGaetan Rivet ERROR("Adding MAC address %s failed", ea_fmt); 206ae7cb246SMatan Azrad return ret; 207ebea83f8SGaetan Rivet } 208ebea83f8SGaetan Rivet } 209ebea83f8SGaetan Rivet /* VLAN filter */ 210ebea83f8SGaetan Rivet vfc1 = &dev->data->vlan_filter_conf; 211ebea83f8SGaetan Rivet vfc2 = &edev->data->vlan_filter_conf; 212ebea83f8SGaetan Rivet if (memcmp(vfc1, vfc2, sizeof(struct rte_vlan_filter_conf))) { 213ebea83f8SGaetan Rivet uint64_t vbit; 214ebea83f8SGaetan Rivet uint64_t ids; 215ebea83f8SGaetan Rivet size_t i; 216ebea83f8SGaetan Rivet uint16_t vlan_id; 217ebea83f8SGaetan Rivet 218ebea83f8SGaetan Rivet DEBUG("Configuring VLAN filter"); 219ebea83f8SGaetan Rivet for (i = 0; i < RTE_DIM(vfc1->ids); i++) { 220ebea83f8SGaetan Rivet if (vfc1->ids[i] == 0) 221ebea83f8SGaetan Rivet continue; 222ebea83f8SGaetan Rivet ids = vfc1->ids[i]; 223ebea83f8SGaetan Rivet while (ids) { 224ebea83f8SGaetan Rivet vlan_id = 64 * i; 225ebea83f8SGaetan Rivet /* count trailing zeroes */ 226ebea83f8SGaetan Rivet vbit = ~ids & (ids - 1); 227ebea83f8SGaetan Rivet /* clear least significant bit set */ 228ebea83f8SGaetan Rivet ids ^= (ids ^ (ids - 1)) ^ vbit; 229ebea83f8SGaetan Rivet for (; vbit; vlan_id++) 230ebea83f8SGaetan Rivet vbit >>= 1; 231ebea83f8SGaetan Rivet ret = rte_eth_dev_vlan_filter( 232ebea83f8SGaetan Rivet PORT_ID(sdev), vlan_id, 1); 233ebea83f8SGaetan Rivet if (ret) { 234ebea83f8SGaetan Rivet ERROR("Failed to apply VLAN filter %hu", 235ebea83f8SGaetan Rivet vlan_id); 236ebea83f8SGaetan Rivet return ret; 237ebea83f8SGaetan Rivet } 238ebea83f8SGaetan Rivet } 239ebea83f8SGaetan Rivet } 240ebea83f8SGaetan Rivet } else { 241ebea83f8SGaetan Rivet DEBUG("VLAN filter already set"); 242ebea83f8SGaetan Rivet } 243b737a1eeSGaetan Rivet /* rte_flow */ 244b737a1eeSGaetan Rivet if (TAILQ_EMPTY(&PRIV(dev)->flow_list)) { 245b737a1eeSGaetan Rivet DEBUG("rte_flow already set"); 246b737a1eeSGaetan Rivet } else { 247b737a1eeSGaetan Rivet DEBUG("Resetting rte_flow configuration"); 248b737a1eeSGaetan Rivet ret = rte_flow_flush(PORT_ID(sdev), &ferror); 249b737a1eeSGaetan Rivet if (ret) { 250b737a1eeSGaetan Rivet fs_flow_complain(&ferror); 251b737a1eeSGaetan Rivet return ret; 252b737a1eeSGaetan Rivet } 253b737a1eeSGaetan Rivet i = 0; 254b737a1eeSGaetan Rivet rte_errno = 0; 255b737a1eeSGaetan Rivet DEBUG("Configuring rte_flow"); 256b737a1eeSGaetan Rivet TAILQ_FOREACH(flow, &PRIV(dev)->flow_list, next) { 257b737a1eeSGaetan Rivet DEBUG("Creating flow #%" PRIu32, i++); 258b737a1eeSGaetan Rivet flow->flows[SUB_ID(sdev)] = 259b737a1eeSGaetan Rivet rte_flow_create(PORT_ID(sdev), 260b737a1eeSGaetan Rivet &flow->fd->attr, 261b737a1eeSGaetan Rivet flow->fd->items, 262b737a1eeSGaetan Rivet flow->fd->actions, 263b737a1eeSGaetan Rivet &ferror); 264b737a1eeSGaetan Rivet ret = rte_errno; 265b737a1eeSGaetan Rivet if (ret) 266b737a1eeSGaetan Rivet break; 267b737a1eeSGaetan Rivet } 268b737a1eeSGaetan Rivet if (ret) { 269b737a1eeSGaetan Rivet fs_flow_complain(&ferror); 270b737a1eeSGaetan Rivet return ret; 271b737a1eeSGaetan Rivet } 272b737a1eeSGaetan Rivet } 273ebea83f8SGaetan Rivet return 0; 274ebea83f8SGaetan Rivet } 275ebea83f8SGaetan Rivet 276598fb8aeSGaetan Rivet static void 277598fb8aeSGaetan Rivet fs_dev_remove(struct sub_device *sdev) 278598fb8aeSGaetan Rivet { 279598fb8aeSGaetan Rivet int ret; 280598fb8aeSGaetan Rivet 281598fb8aeSGaetan Rivet if (sdev == NULL) 282598fb8aeSGaetan Rivet return; 283598fb8aeSGaetan Rivet switch (sdev->state) { 284598fb8aeSGaetan Rivet case DEV_STARTED: 285598fb8aeSGaetan Rivet rte_eth_dev_stop(PORT_ID(sdev)); 286598fb8aeSGaetan Rivet sdev->state = DEV_ACTIVE; 287598fb8aeSGaetan Rivet /* fallthrough */ 288598fb8aeSGaetan Rivet case DEV_ACTIVE: 289598fb8aeSGaetan Rivet rte_eth_dev_close(PORT_ID(sdev)); 290598fb8aeSGaetan Rivet sdev->state = DEV_PROBED; 291598fb8aeSGaetan Rivet /* fallthrough */ 292598fb8aeSGaetan Rivet case DEV_PROBED: 293598fb8aeSGaetan Rivet ret = rte_eal_hotplug_remove(sdev->bus->name, 294598fb8aeSGaetan Rivet sdev->dev->name); 295598fb8aeSGaetan Rivet if (ret) { 296598fb8aeSGaetan Rivet ERROR("Bus detach failed for sub_device %u", 297598fb8aeSGaetan Rivet SUB_ID(sdev)); 298598fb8aeSGaetan Rivet } else { 299598fb8aeSGaetan Rivet ETH(sdev)->state = RTE_ETH_DEV_UNUSED; 300598fb8aeSGaetan Rivet } 301598fb8aeSGaetan Rivet sdev->state = DEV_PARSED; 302598fb8aeSGaetan Rivet /* fallthrough */ 303598fb8aeSGaetan Rivet case DEV_PARSED: 304598fb8aeSGaetan Rivet case DEV_UNDEFINED: 305598fb8aeSGaetan Rivet sdev->state = DEV_UNDEFINED; 306598fb8aeSGaetan Rivet /* the end */ 307598fb8aeSGaetan Rivet break; 308598fb8aeSGaetan Rivet } 309598fb8aeSGaetan Rivet failsafe_hotplug_alarm_install(sdev->fs_dev); 310598fb8aeSGaetan Rivet } 311598fb8aeSGaetan Rivet 312*6265ab51SMatan Azrad static void 313*6265ab51SMatan Azrad fs_dev_stats_save(struct sub_device *sdev) 314*6265ab51SMatan Azrad { 315*6265ab51SMatan Azrad failsafe_stats_increment(&PRIV(sdev->fs_dev)->stats_accumulator, 316*6265ab51SMatan Azrad &sdev->stats_snapshot); 317*6265ab51SMatan Azrad memset(&sdev->stats_snapshot, 0, sizeof(struct rte_eth_stats)); 318*6265ab51SMatan Azrad } 319*6265ab51SMatan Azrad 320598fb8aeSGaetan Rivet static inline int 321598fb8aeSGaetan Rivet fs_rxtx_clean(struct sub_device *sdev) 322598fb8aeSGaetan Rivet { 323598fb8aeSGaetan Rivet uint16_t i; 324598fb8aeSGaetan Rivet 325598fb8aeSGaetan Rivet for (i = 0; i < ETH(sdev)->data->nb_rx_queues; i++) 326598fb8aeSGaetan Rivet if (FS_ATOMIC_RX(sdev, i)) 327598fb8aeSGaetan Rivet return 0; 328598fb8aeSGaetan Rivet for (i = 0; i < ETH(sdev)->data->nb_tx_queues; i++) 329598fb8aeSGaetan Rivet if (FS_ATOMIC_TX(sdev, i)) 330598fb8aeSGaetan Rivet return 0; 331598fb8aeSGaetan Rivet return 1; 332598fb8aeSGaetan Rivet } 333598fb8aeSGaetan Rivet 334598fb8aeSGaetan Rivet void 335598fb8aeSGaetan Rivet failsafe_dev_remove(struct rte_eth_dev *dev) 336598fb8aeSGaetan Rivet { 337598fb8aeSGaetan Rivet struct sub_device *sdev; 338598fb8aeSGaetan Rivet uint8_t i; 339598fb8aeSGaetan Rivet 340598fb8aeSGaetan Rivet FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) 341*6265ab51SMatan Azrad if (sdev->remove && fs_rxtx_clean(sdev)) { 342*6265ab51SMatan Azrad fs_dev_stats_save(sdev); 343598fb8aeSGaetan Rivet fs_dev_remove(sdev); 344598fb8aeSGaetan Rivet } 345*6265ab51SMatan Azrad } 346598fb8aeSGaetan Rivet 347ebea83f8SGaetan Rivet int 348ebea83f8SGaetan Rivet failsafe_eth_dev_state_sync(struct rte_eth_dev *dev) 349ebea83f8SGaetan Rivet { 350ebea83f8SGaetan Rivet struct sub_device *sdev; 351ebea83f8SGaetan Rivet uint32_t inactive; 352ebea83f8SGaetan Rivet int ret; 353ebea83f8SGaetan Rivet uint8_t i; 354ebea83f8SGaetan Rivet 355a0194d82SGaetan Rivet if (PRIV(dev)->state < DEV_PARSED) 356a0194d82SGaetan Rivet return 0; 357a0194d82SGaetan Rivet 358a0194d82SGaetan Rivet ret = failsafe_args_parse_subs(dev); 359a0194d82SGaetan Rivet if (ret) 360598fb8aeSGaetan Rivet goto err_remove; 361a0194d82SGaetan Rivet 362ebea83f8SGaetan Rivet if (PRIV(dev)->state < DEV_PROBED) 363ebea83f8SGaetan Rivet return 0; 364ebea83f8SGaetan Rivet ret = failsafe_eal_init(dev); 365ebea83f8SGaetan Rivet if (ret) 366598fb8aeSGaetan Rivet goto err_remove; 367ebea83f8SGaetan Rivet if (PRIV(dev)->state < DEV_ACTIVE) 368ebea83f8SGaetan Rivet return 0; 369ebea83f8SGaetan Rivet inactive = 0; 3702cc52cd7SGaetan Rivet FOREACH_SUBDEV(sdev, i, dev) { 3712cc52cd7SGaetan Rivet if (sdev->state == DEV_PROBED) { 372ebea83f8SGaetan Rivet inactive |= UINT32_C(1) << i; 3732cc52cd7SGaetan Rivet ret = eth_dev_flow_isolate_set(dev, sdev); 3742cc52cd7SGaetan Rivet if (ret) { 3752cc52cd7SGaetan Rivet ERROR("Could not apply configuration to sub_device %d", 3762cc52cd7SGaetan Rivet i); 3772cc52cd7SGaetan Rivet goto err_remove; 3782cc52cd7SGaetan Rivet } 3792cc52cd7SGaetan Rivet } 3802cc52cd7SGaetan Rivet } 381ebea83f8SGaetan Rivet ret = dev->dev_ops->dev_configure(dev); 382ebea83f8SGaetan Rivet if (ret) 383598fb8aeSGaetan Rivet goto err_remove; 384ebea83f8SGaetan Rivet FOREACH_SUBDEV(sdev, i, dev) { 385ebea83f8SGaetan Rivet if (inactive & (UINT32_C(1) << i)) { 386ebea83f8SGaetan Rivet ret = fs_eth_dev_conf_apply(dev, sdev); 387ebea83f8SGaetan Rivet if (ret) { 388ebea83f8SGaetan Rivet ERROR("Could not apply configuration to sub_device %d", 389ebea83f8SGaetan Rivet i); 390598fb8aeSGaetan Rivet goto err_remove; 391ebea83f8SGaetan Rivet } 392ebea83f8SGaetan Rivet } 393ebea83f8SGaetan Rivet } 394ebea83f8SGaetan Rivet /* 395ebea83f8SGaetan Rivet * If new devices have been configured, check if 396ebea83f8SGaetan Rivet * the link state has changed. 397ebea83f8SGaetan Rivet */ 398ebea83f8SGaetan Rivet if (inactive) 399ebea83f8SGaetan Rivet dev->dev_ops->link_update(dev, 1); 400ebea83f8SGaetan Rivet if (PRIV(dev)->state < DEV_STARTED) 401ebea83f8SGaetan Rivet return 0; 402ebea83f8SGaetan Rivet ret = dev->dev_ops->dev_start(dev); 403ebea83f8SGaetan Rivet if (ret) 404598fb8aeSGaetan Rivet goto err_remove; 405598fb8aeSGaetan Rivet return 0; 406598fb8aeSGaetan Rivet err_remove: 407598fb8aeSGaetan Rivet FOREACH_SUBDEV(sdev, i, dev) 408598fb8aeSGaetan Rivet if (sdev->state != PRIV(dev)->state) 409598fb8aeSGaetan Rivet sdev->remove = 1; 410ebea83f8SGaetan Rivet return ret; 411598fb8aeSGaetan Rivet } 412598fb8aeSGaetan Rivet 413*6265ab51SMatan Azrad void 414*6265ab51SMatan Azrad failsafe_stats_increment(struct rte_eth_stats *to, struct rte_eth_stats *from) 415*6265ab51SMatan Azrad { 416*6265ab51SMatan Azrad uint32_t i; 417*6265ab51SMatan Azrad 418*6265ab51SMatan Azrad RTE_ASSERT(to != NULL && from != NULL); 419*6265ab51SMatan Azrad to->ipackets += from->ipackets; 420*6265ab51SMatan Azrad to->opackets += from->opackets; 421*6265ab51SMatan Azrad to->ibytes += from->ibytes; 422*6265ab51SMatan Azrad to->obytes += from->obytes; 423*6265ab51SMatan Azrad to->imissed += from->imissed; 424*6265ab51SMatan Azrad to->ierrors += from->ierrors; 425*6265ab51SMatan Azrad to->oerrors += from->oerrors; 426*6265ab51SMatan Azrad to->rx_nombuf += from->rx_nombuf; 427*6265ab51SMatan Azrad for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { 428*6265ab51SMatan Azrad to->q_ipackets[i] += from->q_ipackets[i]; 429*6265ab51SMatan Azrad to->q_opackets[i] += from->q_opackets[i]; 430*6265ab51SMatan Azrad to->q_ibytes[i] += from->q_ibytes[i]; 431*6265ab51SMatan Azrad to->q_obytes[i] += from->q_obytes[i]; 432*6265ab51SMatan Azrad to->q_errors[i] += from->q_errors[i]; 433*6265ab51SMatan Azrad } 434*6265ab51SMatan Azrad } 435*6265ab51SMatan Azrad 436598fb8aeSGaetan Rivet int 437598fb8aeSGaetan Rivet failsafe_eth_rmv_event_callback(uint8_t port_id __rte_unused, 438598fb8aeSGaetan Rivet enum rte_eth_event_type event __rte_unused, 439598fb8aeSGaetan Rivet void *cb_arg, void *out __rte_unused) 440598fb8aeSGaetan Rivet { 441598fb8aeSGaetan Rivet struct sub_device *sdev = cb_arg; 442598fb8aeSGaetan Rivet 443598fb8aeSGaetan Rivet /* Switch as soon as possible tx_dev. */ 444598fb8aeSGaetan Rivet fs_switch_dev(sdev->fs_dev, sdev); 445598fb8aeSGaetan Rivet /* Use safe bursts in any case. */ 446598fb8aeSGaetan Rivet set_burst_fn(sdev->fs_dev, 1); 447598fb8aeSGaetan Rivet /* 448598fb8aeSGaetan Rivet * Async removal, the sub-PMD will try to unregister 449598fb8aeSGaetan Rivet * the callback at the source of the current thread context. 450598fb8aeSGaetan Rivet */ 451598fb8aeSGaetan Rivet sdev->remove = 1; 452ebea83f8SGaetan Rivet return 0; 453ebea83f8SGaetan Rivet } 454ad7d6a35SGaetan Rivet 455ad7d6a35SGaetan Rivet int 456ad7d6a35SGaetan Rivet failsafe_eth_lsc_event_callback(uint8_t port_id __rte_unused, 457ad7d6a35SGaetan Rivet enum rte_eth_event_type event __rte_unused, 458ad7d6a35SGaetan Rivet void *cb_arg, void *out __rte_unused) 459ad7d6a35SGaetan Rivet { 460ad7d6a35SGaetan Rivet struct rte_eth_dev *dev = cb_arg; 461ad7d6a35SGaetan Rivet int ret; 462ad7d6a35SGaetan Rivet 463ad7d6a35SGaetan Rivet ret = dev->dev_ops->link_update(dev, 0); 464ad7d6a35SGaetan Rivet /* We must pass on the LSC event */ 465ad7d6a35SGaetan Rivet if (ret) 466ad7d6a35SGaetan Rivet return _rte_eth_dev_callback_process(dev, 467ad7d6a35SGaetan Rivet RTE_ETH_EVENT_INTR_LSC, 468ad7d6a35SGaetan Rivet NULL, NULL); 469ad7d6a35SGaetan Rivet else 470ad7d6a35SGaetan Rivet return 0; 471ad7d6a35SGaetan Rivet } 472