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 77*2cc52cd7SGaetan Rivet eth_dev_flow_isolate_set(struct rte_eth_dev *dev, 78*2cc52cd7SGaetan Rivet struct sub_device *sdev) 79*2cc52cd7SGaetan Rivet { 80*2cc52cd7SGaetan Rivet struct rte_flow_error ferror; 81*2cc52cd7SGaetan Rivet int ret; 82*2cc52cd7SGaetan Rivet 83*2cc52cd7SGaetan Rivet if (!PRIV(dev)->flow_isolated) { 84*2cc52cd7SGaetan Rivet DEBUG("Flow isolation already disabled"); 85*2cc52cd7SGaetan Rivet } else { 86*2cc52cd7SGaetan Rivet DEBUG("Enabling flow isolation"); 87*2cc52cd7SGaetan Rivet ret = rte_flow_isolate(PORT_ID(sdev), 88*2cc52cd7SGaetan Rivet PRIV(dev)->flow_isolated, 89*2cc52cd7SGaetan Rivet &ferror); 90*2cc52cd7SGaetan Rivet if (ret) { 91*2cc52cd7SGaetan Rivet fs_flow_complain(&ferror); 92*2cc52cd7SGaetan Rivet return ret; 93*2cc52cd7SGaetan Rivet } 94*2cc52cd7SGaetan Rivet } 95*2cc52cd7SGaetan Rivet return 0; 96*2cc52cd7SGaetan Rivet } 97*2cc52cd7SGaetan Rivet 98*2cc52cd7SGaetan 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); 206ebea83f8SGaetan Rivet } 207ebea83f8SGaetan Rivet } 208ebea83f8SGaetan Rivet /* VLAN filter */ 209ebea83f8SGaetan Rivet vfc1 = &dev->data->vlan_filter_conf; 210ebea83f8SGaetan Rivet vfc2 = &edev->data->vlan_filter_conf; 211ebea83f8SGaetan Rivet if (memcmp(vfc1, vfc2, sizeof(struct rte_vlan_filter_conf))) { 212ebea83f8SGaetan Rivet uint64_t vbit; 213ebea83f8SGaetan Rivet uint64_t ids; 214ebea83f8SGaetan Rivet size_t i; 215ebea83f8SGaetan Rivet uint16_t vlan_id; 216ebea83f8SGaetan Rivet 217ebea83f8SGaetan Rivet DEBUG("Configuring VLAN filter"); 218ebea83f8SGaetan Rivet for (i = 0; i < RTE_DIM(vfc1->ids); i++) { 219ebea83f8SGaetan Rivet if (vfc1->ids[i] == 0) 220ebea83f8SGaetan Rivet continue; 221ebea83f8SGaetan Rivet ids = vfc1->ids[i]; 222ebea83f8SGaetan Rivet while (ids) { 223ebea83f8SGaetan Rivet vlan_id = 64 * i; 224ebea83f8SGaetan Rivet /* count trailing zeroes */ 225ebea83f8SGaetan Rivet vbit = ~ids & (ids - 1); 226ebea83f8SGaetan Rivet /* clear least significant bit set */ 227ebea83f8SGaetan Rivet ids ^= (ids ^ (ids - 1)) ^ vbit; 228ebea83f8SGaetan Rivet for (; vbit; vlan_id++) 229ebea83f8SGaetan Rivet vbit >>= 1; 230ebea83f8SGaetan Rivet ret = rte_eth_dev_vlan_filter( 231ebea83f8SGaetan Rivet PORT_ID(sdev), vlan_id, 1); 232ebea83f8SGaetan Rivet if (ret) { 233ebea83f8SGaetan Rivet ERROR("Failed to apply VLAN filter %hu", 234ebea83f8SGaetan Rivet vlan_id); 235ebea83f8SGaetan Rivet return ret; 236ebea83f8SGaetan Rivet } 237ebea83f8SGaetan Rivet } 238ebea83f8SGaetan Rivet } 239ebea83f8SGaetan Rivet } else { 240ebea83f8SGaetan Rivet DEBUG("VLAN filter already set"); 241ebea83f8SGaetan Rivet } 242b737a1eeSGaetan Rivet /* rte_flow */ 243b737a1eeSGaetan Rivet if (TAILQ_EMPTY(&PRIV(dev)->flow_list)) { 244b737a1eeSGaetan Rivet DEBUG("rte_flow already set"); 245b737a1eeSGaetan Rivet } else { 246b737a1eeSGaetan Rivet DEBUG("Resetting rte_flow configuration"); 247b737a1eeSGaetan Rivet ret = rte_flow_flush(PORT_ID(sdev), &ferror); 248b737a1eeSGaetan Rivet if (ret) { 249b737a1eeSGaetan Rivet fs_flow_complain(&ferror); 250b737a1eeSGaetan Rivet return ret; 251b737a1eeSGaetan Rivet } 252b737a1eeSGaetan Rivet i = 0; 253b737a1eeSGaetan Rivet rte_errno = 0; 254b737a1eeSGaetan Rivet DEBUG("Configuring rte_flow"); 255b737a1eeSGaetan Rivet TAILQ_FOREACH(flow, &PRIV(dev)->flow_list, next) { 256b737a1eeSGaetan Rivet DEBUG("Creating flow #%" PRIu32, i++); 257b737a1eeSGaetan Rivet flow->flows[SUB_ID(sdev)] = 258b737a1eeSGaetan Rivet rte_flow_create(PORT_ID(sdev), 259b737a1eeSGaetan Rivet &flow->fd->attr, 260b737a1eeSGaetan Rivet flow->fd->items, 261b737a1eeSGaetan Rivet flow->fd->actions, 262b737a1eeSGaetan Rivet &ferror); 263b737a1eeSGaetan Rivet ret = rte_errno; 264b737a1eeSGaetan Rivet if (ret) 265b737a1eeSGaetan Rivet break; 266b737a1eeSGaetan Rivet } 267b737a1eeSGaetan Rivet if (ret) { 268b737a1eeSGaetan Rivet fs_flow_complain(&ferror); 269b737a1eeSGaetan Rivet return ret; 270b737a1eeSGaetan Rivet } 271b737a1eeSGaetan Rivet } 272ebea83f8SGaetan Rivet return 0; 273ebea83f8SGaetan Rivet } 274ebea83f8SGaetan Rivet 275598fb8aeSGaetan Rivet static void 276598fb8aeSGaetan Rivet fs_dev_remove(struct sub_device *sdev) 277598fb8aeSGaetan Rivet { 278598fb8aeSGaetan Rivet int ret; 279598fb8aeSGaetan Rivet 280598fb8aeSGaetan Rivet if (sdev == NULL) 281598fb8aeSGaetan Rivet return; 282598fb8aeSGaetan Rivet switch (sdev->state) { 283598fb8aeSGaetan Rivet case DEV_STARTED: 284598fb8aeSGaetan Rivet rte_eth_dev_stop(PORT_ID(sdev)); 285598fb8aeSGaetan Rivet sdev->state = DEV_ACTIVE; 286598fb8aeSGaetan Rivet /* fallthrough */ 287598fb8aeSGaetan Rivet case DEV_ACTIVE: 288598fb8aeSGaetan Rivet rte_eth_dev_close(PORT_ID(sdev)); 289598fb8aeSGaetan Rivet sdev->state = DEV_PROBED; 290598fb8aeSGaetan Rivet /* fallthrough */ 291598fb8aeSGaetan Rivet case DEV_PROBED: 292598fb8aeSGaetan Rivet ret = rte_eal_hotplug_remove(sdev->bus->name, 293598fb8aeSGaetan Rivet sdev->dev->name); 294598fb8aeSGaetan Rivet if (ret) { 295598fb8aeSGaetan Rivet ERROR("Bus detach failed for sub_device %u", 296598fb8aeSGaetan Rivet SUB_ID(sdev)); 297598fb8aeSGaetan Rivet } else { 298598fb8aeSGaetan Rivet ETH(sdev)->state = RTE_ETH_DEV_UNUSED; 299598fb8aeSGaetan Rivet } 300598fb8aeSGaetan Rivet sdev->state = DEV_PARSED; 301598fb8aeSGaetan Rivet /* fallthrough */ 302598fb8aeSGaetan Rivet case DEV_PARSED: 303598fb8aeSGaetan Rivet case DEV_UNDEFINED: 304598fb8aeSGaetan Rivet sdev->state = DEV_UNDEFINED; 305598fb8aeSGaetan Rivet /* the end */ 306598fb8aeSGaetan Rivet break; 307598fb8aeSGaetan Rivet } 308598fb8aeSGaetan Rivet failsafe_hotplug_alarm_install(sdev->fs_dev); 309598fb8aeSGaetan Rivet } 310598fb8aeSGaetan Rivet 311598fb8aeSGaetan Rivet static inline int 312598fb8aeSGaetan Rivet fs_rxtx_clean(struct sub_device *sdev) 313598fb8aeSGaetan Rivet { 314598fb8aeSGaetan Rivet uint16_t i; 315598fb8aeSGaetan Rivet 316598fb8aeSGaetan Rivet for (i = 0; i < ETH(sdev)->data->nb_rx_queues; i++) 317598fb8aeSGaetan Rivet if (FS_ATOMIC_RX(sdev, i)) 318598fb8aeSGaetan Rivet return 0; 319598fb8aeSGaetan Rivet for (i = 0; i < ETH(sdev)->data->nb_tx_queues; i++) 320598fb8aeSGaetan Rivet if (FS_ATOMIC_TX(sdev, i)) 321598fb8aeSGaetan Rivet return 0; 322598fb8aeSGaetan Rivet return 1; 323598fb8aeSGaetan Rivet } 324598fb8aeSGaetan Rivet 325598fb8aeSGaetan Rivet void 326598fb8aeSGaetan Rivet failsafe_dev_remove(struct rte_eth_dev *dev) 327598fb8aeSGaetan Rivet { 328598fb8aeSGaetan Rivet struct sub_device *sdev; 329598fb8aeSGaetan Rivet uint8_t i; 330598fb8aeSGaetan Rivet 331598fb8aeSGaetan Rivet FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) 332598fb8aeSGaetan Rivet if (sdev->remove && fs_rxtx_clean(sdev)) 333598fb8aeSGaetan Rivet fs_dev_remove(sdev); 334598fb8aeSGaetan Rivet } 335598fb8aeSGaetan Rivet 336ebea83f8SGaetan Rivet int 337ebea83f8SGaetan Rivet failsafe_eth_dev_state_sync(struct rte_eth_dev *dev) 338ebea83f8SGaetan Rivet { 339ebea83f8SGaetan Rivet struct sub_device *sdev; 340ebea83f8SGaetan Rivet uint32_t inactive; 341ebea83f8SGaetan Rivet int ret; 342ebea83f8SGaetan Rivet uint8_t i; 343ebea83f8SGaetan Rivet 344a0194d82SGaetan Rivet if (PRIV(dev)->state < DEV_PARSED) 345a0194d82SGaetan Rivet return 0; 346a0194d82SGaetan Rivet 347a0194d82SGaetan Rivet ret = failsafe_args_parse_subs(dev); 348a0194d82SGaetan Rivet if (ret) 349598fb8aeSGaetan Rivet goto err_remove; 350a0194d82SGaetan Rivet 351ebea83f8SGaetan Rivet if (PRIV(dev)->state < DEV_PROBED) 352ebea83f8SGaetan Rivet return 0; 353ebea83f8SGaetan Rivet ret = failsafe_eal_init(dev); 354ebea83f8SGaetan Rivet if (ret) 355598fb8aeSGaetan Rivet goto err_remove; 356ebea83f8SGaetan Rivet if (PRIV(dev)->state < DEV_ACTIVE) 357ebea83f8SGaetan Rivet return 0; 358ebea83f8SGaetan Rivet inactive = 0; 359*2cc52cd7SGaetan Rivet FOREACH_SUBDEV(sdev, i, dev) { 360*2cc52cd7SGaetan Rivet if (sdev->state == DEV_PROBED) { 361ebea83f8SGaetan Rivet inactive |= UINT32_C(1) << i; 362*2cc52cd7SGaetan Rivet ret = eth_dev_flow_isolate_set(dev, sdev); 363*2cc52cd7SGaetan Rivet if (ret) { 364*2cc52cd7SGaetan Rivet ERROR("Could not apply configuration to sub_device %d", 365*2cc52cd7SGaetan Rivet i); 366*2cc52cd7SGaetan Rivet goto err_remove; 367*2cc52cd7SGaetan Rivet } 368*2cc52cd7SGaetan Rivet } 369*2cc52cd7SGaetan Rivet } 370ebea83f8SGaetan Rivet ret = dev->dev_ops->dev_configure(dev); 371ebea83f8SGaetan Rivet if (ret) 372598fb8aeSGaetan Rivet goto err_remove; 373ebea83f8SGaetan Rivet FOREACH_SUBDEV(sdev, i, dev) { 374ebea83f8SGaetan Rivet if (inactive & (UINT32_C(1) << i)) { 375ebea83f8SGaetan Rivet ret = fs_eth_dev_conf_apply(dev, sdev); 376ebea83f8SGaetan Rivet if (ret) { 377ebea83f8SGaetan Rivet ERROR("Could not apply configuration to sub_device %d", 378ebea83f8SGaetan Rivet i); 379598fb8aeSGaetan Rivet goto err_remove; 380ebea83f8SGaetan Rivet } 381ebea83f8SGaetan Rivet } 382ebea83f8SGaetan Rivet } 383ebea83f8SGaetan Rivet /* 384ebea83f8SGaetan Rivet * If new devices have been configured, check if 385ebea83f8SGaetan Rivet * the link state has changed. 386ebea83f8SGaetan Rivet */ 387ebea83f8SGaetan Rivet if (inactive) 388ebea83f8SGaetan Rivet dev->dev_ops->link_update(dev, 1); 389ebea83f8SGaetan Rivet if (PRIV(dev)->state < DEV_STARTED) 390ebea83f8SGaetan Rivet return 0; 391ebea83f8SGaetan Rivet ret = dev->dev_ops->dev_start(dev); 392ebea83f8SGaetan Rivet if (ret) 393598fb8aeSGaetan Rivet goto err_remove; 394598fb8aeSGaetan Rivet return 0; 395598fb8aeSGaetan Rivet err_remove: 396598fb8aeSGaetan Rivet FOREACH_SUBDEV(sdev, i, dev) 397598fb8aeSGaetan Rivet if (sdev->state != PRIV(dev)->state) 398598fb8aeSGaetan Rivet sdev->remove = 1; 399ebea83f8SGaetan Rivet return ret; 400598fb8aeSGaetan Rivet } 401598fb8aeSGaetan Rivet 402598fb8aeSGaetan Rivet int 403598fb8aeSGaetan Rivet failsafe_eth_rmv_event_callback(uint8_t port_id __rte_unused, 404598fb8aeSGaetan Rivet enum rte_eth_event_type event __rte_unused, 405598fb8aeSGaetan Rivet void *cb_arg, void *out __rte_unused) 406598fb8aeSGaetan Rivet { 407598fb8aeSGaetan Rivet struct sub_device *sdev = cb_arg; 408598fb8aeSGaetan Rivet 409598fb8aeSGaetan Rivet /* Switch as soon as possible tx_dev. */ 410598fb8aeSGaetan Rivet fs_switch_dev(sdev->fs_dev, sdev); 411598fb8aeSGaetan Rivet /* Use safe bursts in any case. */ 412598fb8aeSGaetan Rivet set_burst_fn(sdev->fs_dev, 1); 413598fb8aeSGaetan Rivet /* 414598fb8aeSGaetan Rivet * Async removal, the sub-PMD will try to unregister 415598fb8aeSGaetan Rivet * the callback at the source of the current thread context. 416598fb8aeSGaetan Rivet */ 417598fb8aeSGaetan Rivet sdev->remove = 1; 418ebea83f8SGaetan Rivet return 0; 419ebea83f8SGaetan Rivet } 420ad7d6a35SGaetan Rivet 421ad7d6a35SGaetan Rivet int 422ad7d6a35SGaetan Rivet failsafe_eth_lsc_event_callback(uint8_t port_id __rte_unused, 423ad7d6a35SGaetan Rivet enum rte_eth_event_type event __rte_unused, 424ad7d6a35SGaetan Rivet void *cb_arg, void *out __rte_unused) 425ad7d6a35SGaetan Rivet { 426ad7d6a35SGaetan Rivet struct rte_eth_dev *dev = cb_arg; 427ad7d6a35SGaetan Rivet int ret; 428ad7d6a35SGaetan Rivet 429ad7d6a35SGaetan Rivet ret = dev->dev_ops->link_update(dev, 0); 430ad7d6a35SGaetan Rivet /* We must pass on the LSC event */ 431ad7d6a35SGaetan Rivet if (ret) 432ad7d6a35SGaetan Rivet return _rte_eth_dev_callback_process(dev, 433ad7d6a35SGaetan Rivet RTE_ETH_EVENT_INTR_LSC, 434ad7d6a35SGaetan Rivet NULL, NULL); 435ad7d6a35SGaetan Rivet else 436ad7d6a35SGaetan Rivet return 0; 437ad7d6a35SGaetan Rivet } 438