X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fnetvsc%2Fhn_ethdev.c;h=9e2a405973498a2419ee36fe16d35e74d0cda74e;hb=eeded2044af5bbe88220120b14933536cbb3edb6;hp=d5c4252f0a489829a5840ee75ba9de2d9a397a92;hpb=62024eb8275696bead35b38a6062a2513f1f7c58;p=dpdk.git diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c index d5c4252f0a..9e2a405973 100644 --- a/drivers/net/netvsc/hn_ethdev.c +++ b/drivers/net/netvsc/hn_ethdev.c @@ -9,6 +9,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include @@ -20,13 +25,14 @@ #include #include #include -#include +#include #include #include #include #include #include #include +#include #include "hn_logs.h" #include "hn_var.h" @@ -45,6 +51,14 @@ DEV_RX_OFFLOAD_VLAN_STRIP | \ DEV_RX_OFFLOAD_RSS_HASH) +#define NETVSC_ARG_LATENCY "latency" +#define NETVSC_ARG_RXBREAK "rx_copybreak" +#define NETVSC_ARG_TXBREAK "tx_copybreak" +#define NETVSC_ARG_RX_EXTMBUF_ENABLE "rx_extmbuf_enable" + +/* The max number of retry when hot adding a VF device */ +#define NETVSC_MAX_HOTADD_RETRY 10 + struct hn_xstats_name_off { char name[RTE_ETH_XSTATS_NAME_SIZE]; unsigned int offset; @@ -136,24 +150,36 @@ eth_dev_vmbus_release(struct rte_eth_dev *eth_dev) eth_dev->intr_handle = NULL; } -/* handle "latency=X" from devargs */ -static int hn_set_latency(const char *key, const char *value, void *opaque) +static int hn_set_parameter(const char *key, const char *value, void *opaque) { struct hn_data *hv = opaque; char *endp = NULL; - unsigned long lat; - - errno = 0; - lat = strtoul(value, &endp, 0); + unsigned long v; + v = strtoul(value, &endp, 0); if (*value == '\0' || *endp != '\0') { PMD_DRV_LOG(ERR, "invalid parameter %s=%s", key, value); return -EINVAL; } - PMD_DRV_LOG(DEBUG, "set latency %lu usec", lat); + if (!strcmp(key, NETVSC_ARG_LATENCY)) { + /* usec to nsec */ + hv->latency = v * 1000; + PMD_DRV_LOG(DEBUG, "set latency %u usec", hv->latency); + } else if (!strcmp(key, NETVSC_ARG_RXBREAK)) { + hv->rx_copybreak = v; + PMD_DRV_LOG(DEBUG, "rx copy break set to %u", + hv->rx_copybreak); + } else if (!strcmp(key, NETVSC_ARG_TXBREAK)) { + hv->tx_copybreak = v; + PMD_DRV_LOG(DEBUG, "tx copy break set to %u", + hv->tx_copybreak); + } else if (!strcmp(key, NETVSC_ARG_RX_EXTMBUF_ENABLE)) { + hv->rx_extmbuf_enable = v; + PMD_DRV_LOG(DEBUG, "rx extmbuf enable set to %u", + hv->rx_extmbuf_enable); + } - hv->latency = lat * 1000; /* usec to nsec */ return 0; } @@ -163,7 +189,10 @@ static int hn_parse_args(const struct rte_eth_dev *dev) struct hn_data *hv = dev->data->dev_private; struct rte_devargs *devargs = dev->device->devargs; static const char * const valid_keys[] = { - "latency", + NETVSC_ARG_LATENCY, + NETVSC_ARG_RXBREAK, + NETVSC_ARG_TXBREAK, + NETVSC_ARG_RX_EXTMBUF_ENABLE, NULL }; struct rte_kvargs *kvlist; @@ -177,15 +206,13 @@ static int hn_parse_args(const struct rte_eth_dev *dev) kvlist = rte_kvargs_parse(devargs->args, valid_keys); if (!kvlist) { - PMD_DRV_LOG(NOTICE, "invalid parameters"); + PMD_DRV_LOG(ERR, "invalid parameters"); return -EINVAL; } - ret = rte_kvargs_process(kvlist, "latency", hn_set_latency, hv); - if (ret) - PMD_DRV_LOG(ERR, "Unable to process latency arg\n"); - + ret = rte_kvargs_process(kvlist, NULL, hn_set_parameter, hv); rte_kvargs_free(kvlist); + return ret; } @@ -524,6 +551,129 @@ static int hn_subchan_configure(struct hn_data *hv, return err; } +static void netvsc_hotplug_retry(void *args) +{ + int ret; + struct hn_data *hv = args; + struct rte_eth_dev *dev = &rte_eth_devices[hv->port_id]; + struct rte_devargs *d = &hv->devargs; + char buf[256]; + + DIR *di; + struct dirent *dir; + struct ifreq req; + struct rte_ether_addr eth_addr; + int s; + + PMD_DRV_LOG(DEBUG, "%s: retry count %d", + __func__, hv->eal_hot_plug_retry); + + if (hv->eal_hot_plug_retry++ > NETVSC_MAX_HOTADD_RETRY) + return; + + snprintf(buf, sizeof(buf), "/sys/bus/pci/devices/%s/net", d->name); + di = opendir(buf); + if (!di) { + PMD_DRV_LOG(DEBUG, "%s: can't open directory %s, " + "retrying in 1 second", __func__, buf); + goto retry; + } + + while ((dir = readdir(di))) { + /* Skip . and .. directories */ + if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, "..")) + continue; + + /* trying to get mac address if this is a network device*/ + s = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); + if (s == -1) { + PMD_DRV_LOG(ERR, "Failed to create socket errno %d", + errno); + break; + } + strlcpy(req.ifr_name, dir->d_name, sizeof(req.ifr_name)); + ret = ioctl(s, SIOCGIFHWADDR, &req); + close(s); + if (ret == -1) { + PMD_DRV_LOG(ERR, + "Failed to send SIOCGIFHWADDR for device %s", + dir->d_name); + break; + } + if (req.ifr_hwaddr.sa_family != ARPHRD_ETHER) { + closedir(di); + return; + } + memcpy(eth_addr.addr_bytes, req.ifr_hwaddr.sa_data, + RTE_DIM(eth_addr.addr_bytes)); + + if (rte_is_same_ether_addr(ð_addr, dev->data->mac_addrs)) { + PMD_DRV_LOG(NOTICE, + "Found matching MAC address, adding device %s network name %s", + d->name, dir->d_name); + ret = rte_eal_hotplug_add(d->bus->name, d->name, + d->args); + if (ret) { + PMD_DRV_LOG(ERR, + "Failed to add PCI device %s", + d->name); + break; + } + } + /* When the code reaches here, we either have already added + * the device, or its MAC address did not match. + */ + closedir(di); + return; + } + closedir(di); +retry: + /* The device is still being initialized, retry after 1 second */ + rte_eal_alarm_set(1000000, netvsc_hotplug_retry, hv); +} + +static void +netvsc_hotadd_callback(const char *device_name, enum rte_dev_event_type type, + void *arg) +{ + struct hn_data *hv = arg; + struct rte_devargs *d = &hv->devargs; + int ret; + + PMD_DRV_LOG(INFO, "Device notification type=%d device_name=%s", + type, device_name); + + switch (type) { + case RTE_DEV_EVENT_ADD: + /* if we already has a VF, don't check on hot add */ + if (hv->vf_ctx.vf_state > vf_removed) + break; + + ret = rte_devargs_parse(d, device_name); + if (ret) { + PMD_DRV_LOG(ERR, + "devargs parsing failed ret=%d", ret); + return; + } + + 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); + } + + /* We will switch to VF on RDNIS configure message + * sent from VSP + */ + + break; + default: + break; + } +} + static int hn_dev_configure(struct rte_eth_dev *dev) { struct rte_eth_conf *dev_conf = &dev->data->dev_conf; @@ -599,7 +749,7 @@ static int hn_dev_configure(struct rte_eth_dev *dev) } } - return hn_vf_configure(dev, dev_conf); + return hn_vf_configure_locked(dev, dev_conf); } static int hn_dev_stats_get(struct rte_eth_dev *dev, @@ -809,6 +959,14 @@ hn_dev_start(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); + /* Register to monitor hot plug events */ + error = rte_dev_event_callback_register(NULL, netvsc_hotadd_callback, + hv); + if (error) { + PMD_DRV_LOG(ERR, "failed to register device event callback"); + return error; + } + error = hn_rndis_set_rxfilter(hv, NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_ALL_MULTICAST | @@ -835,6 +993,7 @@ hn_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); dev->data->dev_started = 0; + rte_dev_event_callback_unregister(NULL, netvsc_hotadd_callback, hv); hn_rndis_set_rxfilter(hv, 0); return hn_vf_stop(dev); } @@ -843,11 +1002,14 @@ static int hn_dev_close(struct rte_eth_dev *dev) { int ret; + struct hn_data *hv = dev->data->dev_private; PMD_INIT_FUNC_TRACE(); if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; + rte_eal_alarm_cancel(netvsc_hotplug_retry, &hv->devargs); + ret = hn_vf_close(dev); hn_dev_free_queues(dev); @@ -950,6 +1112,8 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; + eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; + /* Since Hyper-V only supports one MAC address */ eth_dev->data->mac_addrs = rte_calloc("hv_mac", HN_MAX_MAC_ADDRS, sizeof(struct rte_ether_addr), 0); @@ -964,9 +1128,16 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) hv->chim_res = &vmbus->resource[HV_SEND_BUF_MAP]; hv->port_id = eth_dev->data->port_id; hv->latency = HN_CHAN_LATENCY_NS; + hv->rx_copybreak = HN_RXCOPY_THRESHOLD; + hv->tx_copybreak = HN_TXCOPY_THRESHOLD; + hv->rx_extmbuf_enable = HN_RX_EXTMBUF_ENABLE; hv->max_queues = 1; + rte_rwlock_init(&hv->vf_lock); - hv->vf_port = HN_INVALID_PORT; + hv->vf_ctx.vf_vsc_switched = false; + hv->vf_ctx.vf_vsp_reported = false; + hv->vf_ctx.vf_attached = false; + hv->vf_ctx.vf_state = vf_unknown; err = hn_parse_args(eth_dev); if (err) @@ -1020,12 +1191,10 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) hv->max_queues = RTE_MIN(rxr_cnt, (unsigned int)max_chan); /* If VF was reported but not added, do it now */ - if (hv->vf_present && !hn_vf_attached(hv)) { + if (hv->vf_ctx.vf_vsp_reported && !hv->vf_ctx.vf_vsc_switched) { PMD_INIT_LOG(DEBUG, "Adding VF device"); err = hn_vf_add(eth_dev, hv); - if (err) - hv->vf_present = 0; } return 0; @@ -1071,15 +1240,23 @@ static int eth_hn_probe(struct rte_vmbus_driver *drv __rte_unused, PMD_INIT_FUNC_TRACE(); + ret = rte_dev_event_monitor_start(); + if (ret) { + PMD_DRV_LOG(ERR, "Failed to start device event monitoring"); + return ret; + } + eth_dev = eth_dev_vmbus_allocate(dev, sizeof(struct hn_data)); if (!eth_dev) return -ENOMEM; ret = eth_hn_dev_init(eth_dev); - if (ret) + if (ret) { eth_dev_vmbus_release(eth_dev); - else + rte_dev_event_monitor_stop(); + } else { rte_eth_dev_probing_finish(eth_dev); + } return ret; } @@ -1100,6 +1277,7 @@ static int eth_hn_remove(struct rte_vmbus_device *dev) return ret; eth_dev_vmbus_release(eth_dev); + rte_dev_event_monitor_stop(); return 0; } @@ -1118,5 +1296,10 @@ static struct rte_vmbus_driver rte_netvsc_pmd = { RTE_PMD_REGISTER_VMBUS(net_netvsc, rte_netvsc_pmd); RTE_PMD_REGISTER_KMOD_DEP(net_netvsc, "* uio_hv_generic"); -RTE_LOG_REGISTER(hn_logtype_init, pmd.net.netvsc.init, NOTICE); -RTE_LOG_REGISTER(hn_logtype_driver, pmd.net.netvsc.driver, NOTICE); +RTE_LOG_REGISTER_SUFFIX(hn_logtype_init, init, NOTICE); +RTE_LOG_REGISTER_SUFFIX(hn_logtype_driver, driver, NOTICE); +RTE_PMD_REGISTER_PARAM_STRING(net_netvsc, + NETVSC_ARG_LATENCY "= " + NETVSC_ARG_RXBREAK "= " + NETVSC_ARG_TXBREAK "= " + NETVSC_ARG_RX_EXTMBUF_ENABLE "=<0|1>");