* Remove a device from the specific data core linked list and from the * main linked list. Synchronization occurs through the use of the * lcore dev_removal_flag. Device is made volatile here to avoid re-ordering * of dev->remove=1 which can cause an infinite loop in the rte_pause loop. */
| 1573 | * of dev->remove=1 which can cause an infinite loop in the rte_pause loop. |
| 1574 | */ |
| 1575 | static void |
| 1576 | destroy_device(int vid) |
| 1577 | { |
| 1578 | struct vhost_dev *vdev = NULL; |
| 1579 | int lcore; |
| 1580 | uint16_t i; |
| 1581 | |
| 1582 | TAILQ_FOREACH(vdev, &vhost_dev_list, global_vdev_entry) { |
| 1583 | if (vdev->vid == vid) |
| 1584 | break; |
| 1585 | } |
| 1586 | if (!vdev) |
| 1587 | return; |
| 1588 | /*set the remove flag. */ |
| 1589 | vdev->remove = 1; |
| 1590 | while(vdev->ready != DEVICE_SAFE_REMOVE) { |
| 1591 | rte_pause(); |
| 1592 | } |
| 1593 | |
| 1594 | for (i = 0; i < RTE_MAX_LCORE; i++) |
| 1595 | rte_free(vhost_txbuff[i * RTE_MAX_VHOST_DEVICE + vid]); |
| 1596 | |
| 1597 | if (builtin_net_driver) |
| 1598 | vs_vhost_net_remove(vdev); |
| 1599 | |
| 1600 | TAILQ_REMOVE(&lcore_info[vdev->coreid].vdev_list, vdev, |
| 1601 | lcore_vdev_entry); |
| 1602 | TAILQ_REMOVE(&vhost_dev_list, vdev, global_vdev_entry); |
| 1603 | |
| 1604 | |
| 1605 | /* Set the dev_removal_flag on each lcore. */ |
| 1606 | RTE_LCORE_FOREACH_WORKER(lcore) |
| 1607 | lcore_info[lcore].dev_removal_flag = REQUEST_DEV_REMOVAL; |
| 1608 | |
| 1609 | /* |
| 1610 | * Once each core has set the dev_removal_flag to ACK_DEV_REMOVAL |
| 1611 | * we can be sure that they can no longer access the device removed |
| 1612 | * from the linked lists and that the devices are no longer in use. |
| 1613 | */ |
| 1614 | RTE_LCORE_FOREACH_WORKER(lcore) { |
| 1615 | while (lcore_info[lcore].dev_removal_flag != ACK_DEV_REMOVAL) |
| 1616 | rte_pause(); |
| 1617 | } |
| 1618 | |
| 1619 | lcore_info[vdev->coreid].device_num--; |
| 1620 | |
| 1621 | RTE_LOG(INFO, VHOST_DATA, |
| 1622 | "(%d) device has been removed from data core\n", |
| 1623 | vdev->vid); |
| 1624 | |
| 1625 | if (dma_bind[vid].dmas[VIRTIO_RXQ].async_enabled) { |
| 1626 | vhost_clear_queue(vdev, VIRTIO_RXQ); |
| 1627 | rte_vhost_async_channel_unregister(vid, VIRTIO_RXQ); |
| 1628 | dma_bind[vid].dmas[VIRTIO_RXQ].async_enabled = false; |
| 1629 | } |
| 1630 | |
| 1631 | if (dma_bind[vid].dmas[VIRTIO_TXQ].async_enabled) { |
| 1632 | vhost_clear_queue(vdev, VIRTIO_TXQ); |
nothing calls this directly
no test coverage detected