Commit f43a4852 authored by Darek Stojaczyk's avatar Darek Stojaczyk
Browse files

env_dpdk/pci: make spdk_pci_device_detach() synchronous again



By making dpdk device detach asynchronous we have
actually broken some cases where devices are re-attached
immediately after and fail since they were not detached
yet, so now we're making device detach synchronous again.

For that we'll simply wait inside spdk_pci_device_detach()
for the background dpdk thread to perform all necessary
actions before we return. We'll also print an error msg
if DPDK failed the detach (probably because of some
internal error).

Change-Id: I7657ac1b169169eae3325de2d28c2cc311e7d901
Signed-off-by: default avatarDarek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/460286


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatar <jacek.kalwas@intel.com>
parent 79b56181
Loading
Loading
Loading
Loading
+37 −2
Original line number Diff line number Diff line
@@ -123,14 +123,49 @@ spdk_detach_rte_cb(void *_dev)
static void
spdk_detach_rte(struct spdk_pci_device *dev)
{
	struct rte_pci_device *rte_dev = dev->dev_handle;
	int i;
	bool removed;

	/* The device was already marked as available and could be attached
	 * again while we go asynchronous, so we explicitly forbid that.
	 */
	dev->internal.pending_removal = true;
	if (spdk_process_is_primary() && !pthread_equal(g_dpdk_tid, pthread_self())) {
		rte_eal_alarm_set(10, spdk_detach_rte_cb, dev->dev_handle);
		rte_eal_alarm_set(1, spdk_detach_rte_cb, rte_dev);
		/* wait up to 20ms for the cb to start executing */
		for (i = 20; i > 0; i--) {

			spdk_delay_us(1000);
			pthread_mutex_lock(&g_pci_mutex);
			removed = dev->internal.removed;
			pthread_mutex_unlock(&g_pci_mutex);

			if (removed) {
				break;
			}
		}

		/* besides checking the removed flag, we also need to wait
		 * for the dpdk detach function to unwind, as it's doing some
		 * operations even after calling our detach callback. Simply
		 * cancell the alarm - if it started executing already, this
		 * call will block and wait for it to finish.
		 */
		rte_eal_alarm_cancel(spdk_detach_rte_cb, rte_dev);

		/* the device could have been finally removed, so just check
		 * it again.
		 */
		pthread_mutex_lock(&g_pci_mutex);
		removed = dev->internal.removed;
		pthread_mutex_unlock(&g_pci_mutex);
		if (!removed) {
			fprintf(stderr, "Timeout waiting for DPDK to remove PCI device %s.\n",
				rte_dev->name);
		}
	} else {
		spdk_detach_rte_cb(dev->dev_handle);
		spdk_detach_rte_cb(rte_dev);
	}
}