X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fnetvsc%2Fhn_rndis.c;h=d186ddeabda9efd2a8075c09aab8a9d2b152dc42;hb=972a1bf8120d971c04c065221c46c37c266b1f62;hp=f44add726b91d1eba9b40b776a35b3aa6c4814ce;hpb=7a866f0d1b5c1957b9d03b0aaf08702394721d27;p=dpdk.git diff --git a/drivers/net/netvsc/hn_rndis.c b/drivers/net/netvsc/hn_rndis.c index f44add726b..d186ddeabd 100644 --- a/drivers/net/netvsc/hn_rndis.c +++ b/drivers/net/netvsc/hn_rndis.c @@ -10,12 +10,15 @@ #include #include #include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -32,6 +35,9 @@ #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 \ @@ -59,10 +65,9 @@ hn_rndis_rid(struct hn_data *hv) 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, PAGE_SIZE); } #ifdef RTE_LIBRTE_NETVSC_DEBUG_DUMP @@ -281,7 +286,16 @@ static int hn_nvs_send_rndis_ctrl(struct vmbus_channel *chan, &nvs_rndis, sizeof(nvs_rndis), 0U, NULL); } -void hn_rndis_link_status(struct hn_data *hv __rte_unused, const void *msg) +/* + * 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; @@ -290,15 +304,16 @@ void hn_rndis_link_status(struct hn_data *hv __rte_unused, const void *msg) PMD_DRV_LOG(DEBUG, "link status %#x", indicate->status); switch (indicate->status) { - case RNDIS_STATUS_LINK_SPEED_CHANGE: case RNDIS_STATUS_NETWORK_CHANGE: case RNDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG: /* ignore not in DPDK API */ break; + case RNDIS_STATUS_LINK_SPEED_CHANGE: case RNDIS_STATUS_MEDIA_CONNECT: case RNDIS_STATUS_MEDIA_DISCONNECT: - /* TODO handle as LSC interrupt */ + 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", @@ -343,7 +358,7 @@ void hn_rndis_receive_response(struct hn_data *hv, 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); } @@ -366,6 +381,11 @@ static int hn_rndis_exec1(struct hn_data *hv, 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, @@ -380,9 +400,26 @@ static int hn_rndis_exec1(struct hn_data *hv, } 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); } @@ -437,7 +474,7 @@ hn_rndis_query(struct hn_data *hv, uint32_t oid, uint32_t rid; reqlen = sizeof(*req) + idlen; - req = hn_rndis_alloc(hv, reqlen); + req = hn_rndis_alloc(reqlen); if (req == NULL) return -ENOMEM; @@ -512,7 +549,7 @@ hn_rndis_halt(struct hn_data *hv) { struct rndis_halt_req *halt; - halt = hn_rndis_alloc(hv, sizeof(*halt)); + halt = hn_rndis_alloc(sizeof(*halt)); if (halt == NULL) return -ENOMEM; @@ -893,7 +930,7 @@ int hn_rndis_get_offload(struct hn_data *hv, dev_info->tx_offload_capa |= DEV_TX_OFFLOAD_TCP_TSO; dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP | - DEV_RX_OFFLOAD_CRC_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; @@ -909,6 +946,37 @@ int hn_rndis_get_offload(struct hn_data *hv, return 0; } +uint32_t +hn_rndis_get_ptypes(struct hn_data *hv) +{ + struct ndis_offload hwcaps; + uint32_t ptypes; + int error; + + memset(&hwcaps, 0, sizeof(hwcaps)); + + error = hn_rndis_query_hwcaps(hv, &hwcaps); + if (error) { + PMD_DRV_LOG(ERR, "hwcaps query failed: %d", error); + return RTE_PTYPE_L2_ETHER; + } + + ptypes = RTE_PTYPE_L2_ETHER; + + if (hwcaps.ndis_csum.ndis_ip4_rxcsum & NDIS_RXCSUM_CAP_IP4) + ptypes |= RTE_PTYPE_L3_IPV4; + + if ((hwcaps.ndis_csum.ndis_ip4_rxcsum & NDIS_RXCSUM_CAP_TCP4) || + (hwcaps.ndis_csum.ndis_ip6_rxcsum & NDIS_RXCSUM_CAP_TCP6)) + ptypes |= RTE_PTYPE_L4_TCP; + + if ((hwcaps.ndis_csum.ndis_ip4_rxcsum & NDIS_RXCSUM_CAP_UDP4) || + (hwcaps.ndis_csum.ndis_ip6_rxcsum & NDIS_RXCSUM_CAP_UDP6)) + ptypes |= RTE_PTYPE_L4_UDP; + + return ptypes; +} + int hn_rndis_set_rxfilter(struct hn_data *hv, uint32_t filter) { @@ -926,62 +994,34 @@ hn_rndis_set_rxfilter(struct hn_data *hv, uint32_t filter) 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); @@ -996,7 +1036,7 @@ static int hn_rndis_init(struct hn_data *hv) 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; @@ -1058,7 +1098,7 @@ hn_rndis_get_eaddr(struct hn_data *hv, uint8_t *eaddr) uint32_t eaddr_len; int error; - eaddr_len = ETHER_ADDR_LEN; + eaddr_len = RTE_ETHER_ADDR_LEN; error = hn_rndis_query(hv, OID_802_3_PERMANENT_ADDRESS, NULL, 0, eaddr, eaddr_len); if (error) @@ -1094,6 +1134,10 @@ hn_rndis_attach(struct hn_data *hv) 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); }