static void netvsc_hotplug_retry(void *args)
{
int ret;
- struct hn_data *hv = args;
+ struct hv_hotadd_context *hot_ctx = args;
+ struct hn_data *hv = hot_ctx->hv;
struct rte_eth_dev *dev = &rte_eth_devices[hv->port_id];
- struct rte_devargs *d = &hv->devargs;
+ struct rte_devargs *d = &hot_ctx->da;
char buf[256];
DIR *di;
int s;
PMD_DRV_LOG(DEBUG, "%s: retry count %d",
- __func__, hv->eal_hot_plug_retry);
+ __func__, hot_ctx->eal_hot_plug_retry);
- if (hv->eal_hot_plug_retry++ > NETVSC_MAX_HOTADD_RETRY)
- return;
+ if (hot_ctx->eal_hot_plug_retry++ > NETVSC_MAX_HOTADD_RETRY) {
+ PMD_DRV_LOG(NOTICE, "Failed to parse PCI device retry=%d",
+ hot_ctx->eal_hot_plug_retry);
+ goto free_hotadd_ctx;
+ }
snprintf(buf, sizeof(buf), "/sys/bus/pci/devices/%s/net", d->name);
di = opendir(buf);
}
if (req.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
closedir(di);
- return;
+ goto free_hotadd_ctx;
}
memcpy(eth_addr.addr_bytes, req.ifr_hwaddr.sa_data,
RTE_DIM(eth_addr.addr_bytes));
PMD_DRV_LOG(NOTICE,
"Found matching MAC address, adding device %s network name %s",
d->name, dir->d_name);
+
+ /* If this device has been hot removed from this
+ * parent device, restore its args.
+ */
ret = rte_eal_hotplug_add(d->bus->name, d->name,
- d->args);
+ hv->vf_devargs ?
+ hv->vf_devargs : "");
if (ret) {
PMD_DRV_LOG(ERR,
"Failed to add PCI device %s",
* the device, or its MAC address did not match.
*/
closedir(di);
- return;
+ goto free_hotadd_ctx;
}
closedir(di);
retry:
/* The device is still being initialized, retry after 1 second */
- rte_eal_alarm_set(1000000, netvsc_hotplug_retry, hv);
+ rte_eal_alarm_set(1000000, netvsc_hotplug_retry, hot_ctx);
+ return;
+
+free_hotadd_ctx:
+ rte_spinlock_lock(&hv->hotadd_lock);
+ LIST_REMOVE(hot_ctx, list);
+ rte_spinlock_unlock(&hv->hotadd_lock);
+
+ rte_free(hot_ctx);
}
static void
void *arg)
{
struct hn_data *hv = arg;
- struct rte_devargs *d = &hv->devargs;
+ struct hv_hotadd_context *hot_ctx;
+ struct rte_devargs *d;
int ret;
PMD_DRV_LOG(INFO, "Device notification type=%d device_name=%s",
if (hv->vf_ctx.vf_state > vf_removed)
break;
+ hot_ctx = rte_zmalloc("NETVSC-HOTADD", sizeof(*hot_ctx),
+ rte_mem_page_size());
+
+ if (!hot_ctx) {
+ PMD_DRV_LOG(ERR, "Failed to allocate hotadd context");
+ return;
+ }
+
+ hot_ctx->hv = hv;
+ d = &hot_ctx->da;
+
ret = rte_devargs_parse(d, device_name);
if (ret) {
PMD_DRV_LOG(ERR,
"devargs parsing failed ret=%d", ret);
- return;
+ goto free_ctx;
}
if (!strcmp(d->bus->name, "pci")) {
/* Start the process of figuring out if this
* PCI device is a VF device
*/
- hv->eal_hot_plug_retry = 0;
- rte_eal_alarm_set(1000000, netvsc_hotplug_retry, hv);
+ rte_spinlock_lock(&hv->hotadd_lock);
+ LIST_INSERT_HEAD(&hv->hotadd_list, hot_ctx, list);
+ rte_spinlock_unlock(&hv->hotadd_lock);
+ rte_eal_alarm_set(1000000, netvsc_hotplug_retry, hot_ctx);
+ return;
}
/* We will switch to VF on RDNIS configure message
* sent from VSP
*/
-
+free_ctx:
+ rte_free(hot_ctx);
break;
+
default:
break;
}
{
int ret;
struct hn_data *hv = dev->data->dev_private;
+ struct hv_hotadd_context *hot_ctx;
PMD_INIT_FUNC_TRACE();
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
return 0;
- rte_eal_alarm_cancel(netvsc_hotplug_retry, &hv->devargs);
+ rte_spinlock_lock(&hv->hotadd_lock);
+ while (!LIST_EMPTY(&hv->hotadd_list)) {
+ hot_ctx = LIST_FIRST(&hv->hotadd_list);
+ rte_eal_alarm_cancel(netvsc_hotplug_retry, hot_ctx);
+ LIST_REMOVE(hot_ctx, list);
+ rte_free(hot_ctx);
+ }
+ rte_spinlock_unlock(&hv->hotadd_lock);
ret = hn_vf_close(dev);
hn_dev_free_queues(dev);
PMD_INIT_FUNC_TRACE();
+ rte_spinlock_init(&hv->hotadd_lock);
+ LIST_INIT(&hv->hotadd_list);
+
vmbus = container_of(device, struct rte_vmbus_device, device);
eth_dev->dev_ops = &hn_eth_dev_ops;
eth_dev->rx_queue_count = hn_dev_rx_queue_count;
ret_stop = hn_dev_stop(eth_dev);
hn_dev_close(eth_dev);
+ free(hv->vf_devargs);
+ hv->vf_devargs = NULL;
+
hn_detach(hv);
hn_chim_uninit(eth_dev);
rte_vmbus_chan_close(hv->primary->chan);