#include <stdio.h>
#include <errno.h>
#include <unistd.h>
+#include <time.h>
-#include <rte_ethdev_driver.h>
+#include <ethdev_driver.h>
#include <rte_ethdev.h>
#include <rte_string_fns.h>
#include <rte_memzone.h>
#include <rte_malloc.h>
#include <rte_atomic.h>
+#include <rte_alarm.h>
#include <rte_branch_prediction.h>
#include <rte_ether.h>
#include <rte_common.h>
#include "hn_rndis.h"
#include "ndis.h"
+#define RNDIS_TIMEOUT_SEC 5
+#define RNDIS_DELAY_MS 10
+
#define HN_RNDIS_XFER_SIZE 0x4000
#define HN_NDIS_TXCSUM_CAP_IP4 \
return rid;
}
-static void *hn_rndis_alloc(struct hn_data *hv, size_t size)
+static void *hn_rndis_alloc(size_t size)
{
- return rte_zmalloc_socket("RNDIS", size, PAGE_SIZE,
- hv->vmbus->device.numa_node);
+ return rte_zmalloc("RNDIS", size, rte_mem_page_size());
}
#ifdef RTE_LIBRTE_NETVSC_DEBUG_DUMP
return -EINVAL;
}
- if (unlikely(reqlen > PAGE_SIZE)) {
+ if (unlikely(reqlen > rte_mem_page_size())) {
PMD_DRV_LOG(ERR, "RNDIS request %u greater than page size",
reqlen);
return -EINVAL;
}
- sg.page = addr / PAGE_SIZE;
+ sg.page = addr / rte_mem_page_size();
sg.ofs = addr & PAGE_MASK;
sg.len = reqlen;
- if (sg.ofs + reqlen > PAGE_SIZE) {
- PMD_DRV_LOG(ERR, "RNDIS request crosses page bounary");
+ if (sg.ofs + reqlen > rte_mem_page_size()) {
+ PMD_DRV_LOG(ERR, "RNDIS request crosses page boundary");
return -EINVAL;
}
&nvs_rndis, sizeof(nvs_rndis), 0U, NULL);
}
+/*
+ * Alarm callback to process link changed notifications.
+ * Can not directly since link_status is discovered while reading ring
+ */
+static void hn_rndis_link_alarm(void *arg)
+{
+ rte_eth_dev_callback_process(arg, RTE_ETH_EVENT_INTR_LSC, NULL);
+}
+
void hn_rndis_link_status(struct rte_eth_dev *dev, const void *msg)
{
const struct rndis_status_msg *indicate = msg;
case RNDIS_STATUS_LINK_SPEED_CHANGE:
case RNDIS_STATUS_MEDIA_CONNECT:
case RNDIS_STATUS_MEDIA_DISCONNECT:
- if (dev->data->dev_conf.intr_conf.lsc &&
- hn_dev_link_update(dev, 0) == 0)
- _rte_eth_dev_callback_process(dev,
- RTE_ETH_EVENT_INTR_LSC,
- NULL);
+ if (dev->data->dev_conf.intr_conf.lsc)
+ rte_eal_alarm_set(10, hn_rndis_link_alarm, dev);
break;
default:
PMD_DRV_LOG(NOTICE, "unknown RNDIS indication: %#x",
rte_smp_wmb();
if (rte_atomic32_cmpset(&hv->rndis_pending, hdr->rid, 0) == 0) {
- PMD_DRV_LOG(ERR,
+ PMD_DRV_LOG(NOTICE,
"received id %#x pending id %#x",
hdr->rid, (uint32_t)hv->rndis_pending);
}
return -EIO;
}
+ if (rid == 0) {
+ PMD_DRV_LOG(ERR, "Invalid request id");
+ return -EINVAL;
+ }
+
if (comp != NULL &&
rte_atomic32_cmpset(&hv->rndis_pending, 0, rid) == 0) {
PMD_DRV_LOG(ERR,
}
if (comp) {
+ time_t start = time(NULL);
+
/* Poll primary channel until response received */
- while (hv->rndis_pending == rid)
+ while (hv->rndis_pending == rid) {
+ if (hv->closed)
+ return -ENETDOWN;
+
+ if (time(NULL) - start > RNDIS_TIMEOUT_SEC) {
+ PMD_DRV_LOG(ERR,
+ "RNDIS response timed out");
+
+ rte_atomic32_cmpset(&hv->rndis_pending, rid, 0);
+ return -ETIMEDOUT;
+ }
+
+ if (rte_vmbus_chan_rx_empty(hv->primary->chan))
+ rte_delay_ms(RNDIS_DELAY_MS);
+
hn_process_events(hv, 0, 1);
+ }
memcpy(comp, hv->rndis_resp, comp_len);
}
uint32_t rid;
reqlen = sizeof(*req) + idlen;
- req = hn_rndis_alloc(hv, reqlen);
+ req = hn_rndis_alloc(reqlen);
if (req == NULL)
return -ENOMEM;
comp_len = sizeof(*comp) + odlen;
- comp = rte_zmalloc("QUERY", comp_len, PAGE_SIZE);
+ comp = rte_zmalloc("QUERY", comp_len, rte_mem_page_size());
if (!comp) {
error = -ENOMEM;
goto done;
{
struct rndis_halt_req *halt;
- halt = hn_rndis_alloc(hv, sizeof(*halt));
+ halt = hn_rndis_alloc(sizeof(*halt));
if (halt == NULL)
return -ENOMEM;
int error;
reqlen = sizeof(*req) + dlen;
- req = rte_zmalloc("RNDIS_SET", reqlen, PAGE_SIZE);
+ req = rte_zmalloc("RNDIS_SET", reqlen, rte_mem_page_size());
if (!req)
return -ENOMEM;
== HN_NDIS_LSOV2_CAP_IP6)
dev_info->tx_offload_capa |= DEV_TX_OFFLOAD_TCP_TSO;
- dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP;
+ dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP |
+ DEV_RX_OFFLOAD_RSS_HASH;
if (hwcaps.ndis_csum.ndis_ip4_rxcsum & NDIS_RXCSUM_CAP_IP4)
dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_IPV4_CKSUM;
return error;
}
-/* The default RSS key.
- * This value is the same as MLX5 so that flows will be
- * received on same path for both VF ans synthetic NIC.
- */
-static const uint8_t rss_default_key[NDIS_HASH_KEYSIZE_TOEPLITZ] = {
- 0x2c, 0xc6, 0x81, 0xd1, 0x5b, 0xdb, 0xf4, 0xf7,
- 0xfc, 0xa2, 0x83, 0x19, 0xdb, 0x1a, 0x3e, 0x94,
- 0x6b, 0x9e, 0x38, 0xd9, 0x2c, 0x9c, 0x03, 0xd1,
- 0xad, 0x99, 0x44, 0xa7, 0xd9, 0x56, 0x3d, 0x59,
- 0x06, 0x3c, 0x25, 0xf3, 0xfc, 0x1f, 0xdc, 0x2a,
-};
-
-int hn_rndis_conf_rss(struct hn_data *hv,
- const struct rte_eth_rss_conf *rss_conf)
+int hn_rndis_conf_rss(struct hn_data *hv, uint32_t flags)
{
struct ndis_rssprm_toeplitz rssp;
struct ndis_rss_params *prm = &rssp.rss_params;
- const uint8_t *rss_key = rss_conf->rss_key ? : rss_default_key;
- uint32_t rss_hash;
unsigned int i;
int error;
- PMD_INIT_FUNC_TRACE();
-
memset(&rssp, 0, sizeof(rssp));
prm->ndis_hdr.ndis_type = NDIS_OBJTYPE_RSS_PARAMS;
prm->ndis_hdr.ndis_rev = NDIS_RSS_PARAMS_REV_2;
prm->ndis_hdr.ndis_size = sizeof(*prm);
- prm->ndis_flags = 0;
-
- rss_hash = NDIS_HASH_FUNCTION_TOEPLITZ;
- if (rss_conf->rss_hf & ETH_RSS_IPV4)
- rss_hash |= NDIS_HASH_IPV4;
- if (rss_conf->rss_hf & ETH_RSS_NONFRAG_IPV4_TCP)
- rss_hash |= NDIS_HASH_TCP_IPV4;
- if (rss_conf->rss_hf & ETH_RSS_IPV6)
- rss_hash |= NDIS_HASH_IPV6;
- if (rss_conf->rss_hf & ETH_RSS_NONFRAG_IPV6_TCP)
- rss_hash |= NDIS_HASH_TCP_IPV6;
-
- prm->ndis_hash = rss_hash;
+ prm->ndis_flags = flags;
+ prm->ndis_hash = hv->rss_hash;
prm->ndis_indsize = sizeof(rssp.rss_ind[0]) * NDIS_HASH_INDCNT;
prm->ndis_indoffset = offsetof(struct ndis_rssprm_toeplitz, rss_ind[0]);
prm->ndis_keysize = NDIS_HASH_KEYSIZE_TOEPLITZ;
prm->ndis_keyoffset = offsetof(struct ndis_rssprm_toeplitz, rss_key[0]);
for (i = 0; i < NDIS_HASH_INDCNT; i++)
- rssp.rss_ind[i] = i % hv->num_queues;
+ rssp.rss_ind[i] = hv->rss_ind[i];
/* Set hask key values */
- memcpy(&rssp.rss_key, rss_key, NDIS_HASH_KEYSIZE_TOEPLITZ);
+ memcpy(&rssp.rss_key, hv->rss_key, NDIS_HASH_KEYSIZE_TOEPLITZ);
error = hn_rndis_set(hv, OID_GEN_RECEIVE_SCALE_PARAMETERS,
&rssp, sizeof(rssp));
- if (error) {
+ if (error != 0) {
PMD_DRV_LOG(ERR,
"RSS config num queues=%u failed: %d",
hv->num_queues, error);
uint32_t comp_len, rid;
int error;
- req = hn_rndis_alloc(hv, sizeof(*req));
+ req = hn_rndis_alloc(sizeof(*req));
if (!req) {
PMD_DRV_LOG(ERR, "no memory for RNDIS init");
return -ENXIO;
void
hn_rndis_detach(struct hn_data *hv)
{
+ struct rte_eth_dev *dev = &rte_eth_devices[hv->port_id];
+
+ rte_eal_alarm_cancel(hn_rndis_link_alarm, dev);
+
/* Halt the RNDIS. */
hn_rndis_halt(hv);
}