Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
Show First 20 Lines • Show All 1,029 Lines • ▼ Show 20 Lines | hv_rf_close_device(rndis_device *device) | ||||
return (ret); | return (ret); | ||||
} | } | ||||
/* | /* | ||||
* RNDIS filter on device add | * RNDIS filter on device add | ||||
*/ | */ | ||||
int | int | ||||
hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, | hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, | ||||
int nchan, struct hn_rx_ring *rxr) | int *nchan0, struct hn_rx_ring *rxr) | ||||
{ | { | ||||
struct hn_send_ctx sndc; | struct hn_send_ctx sndc; | ||||
int ret; | int ret; | ||||
netvsc_dev *net_dev; | netvsc_dev *net_dev; | ||||
rndis_device *rndis_dev; | rndis_device *rndis_dev; | ||||
rndis_offload_params offloads; | rndis_offload_params offloads; | ||||
struct rndis_recv_scale_cap rsscaps; | struct rndis_recv_scale_cap rsscaps; | ||||
uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap); | uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap); | ||||
netvsc_device_info *dev_info = (netvsc_device_info *)additl_info; | netvsc_device_info *dev_info = (netvsc_device_info *)additl_info; | ||||
device_t dev = sc->hn_dev; | device_t dev = sc->hn_dev; | ||||
struct hn_nvs_subch_req *req; | struct hn_nvs_subch_req *req; | ||||
const struct hn_nvs_subch_resp *resp; | const struct hn_nvs_subch_resp *resp; | ||||
size_t resp_len; | size_t resp_len; | ||||
struct vmbus_xact *xact; | struct vmbus_xact *xact; | ||||
uint32_t status, nsubch; | uint32_t status, nsubch; | ||||
int nchan = *nchan0; | |||||
rndis_dev = hv_get_rndis_device(); | rndis_dev = hv_get_rndis_device(); | ||||
if (rndis_dev == NULL) { | if (rndis_dev == NULL) { | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
/* | /* | ||||
* Let the inner driver handle this first to create the netvsc channel | * Let the inner driver handle this first to create the netvsc channel | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, | ||||
} | } | ||||
memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, ETHER_ADDR_LEN); | memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, ETHER_ADDR_LEN); | ||||
hv_rf_query_device_link_status(rndis_dev); | hv_rf_query_device_link_status(rndis_dev); | ||||
dev_info->link_state = rndis_dev->link_status; | dev_info->link_state = rndis_dev->link_status; | ||||
net_dev->num_channel = 1; | |||||
if (sc->hn_nvs_ver < NVSP_PROTOCOL_VERSION_5 || nchan == 1) | if (sc->hn_nvs_ver < NVSP_PROTOCOL_VERSION_5 || nchan == 1) | ||||
return (0); | return (0); | ||||
memset(&rsscaps, 0, rsscaps_size); | memset(&rsscaps, 0, rsscaps_size); | ||||
ret = hv_rf_query_device(rndis_dev, | ret = hv_rf_query_device(rndis_dev, | ||||
RNDIS_OID_GEN_RSS_CAPABILITIES, | RNDIS_OID_GEN_RSS_CAPABILITIES, | ||||
&rsscaps, &rsscaps_size); | &rsscaps, &rsscaps_size); | ||||
if ((ret != 0) || (rsscaps.num_recv_que < 2)) { | if ((ret != 0) || (rsscaps.num_recv_que < 2)) { | ||||
device_printf(dev, "hv_rf_query_device failed or " | device_printf(dev, "hv_rf_query_device failed or " | ||||
"rsscaps.num_recv_que < 2 \n"); | "rsscaps.num_recv_que < 2 \n"); | ||||
goto out; | goto out; | ||||
} | } | ||||
device_printf(dev, "channel, offered %u, requested %d\n", | device_printf(dev, "channel, offered %u, requested %d\n", | ||||
rsscaps.num_recv_que, nchan); | rsscaps.num_recv_que, nchan); | ||||
if (nchan > rsscaps.num_recv_que) | if (nchan > rsscaps.num_recv_que) | ||||
nchan = rsscaps.num_recv_que; | nchan = rsscaps.num_recv_que; | ||||
net_dev->num_channel = nchan; | |||||
if (net_dev->num_channel == 1) { | if (nchan == 1) { | ||||
device_printf(dev, "net_dev->num_channel == 1 under VRSS\n"); | device_printf(dev, "only 1 channel is supported, no vRSS\n"); | ||||
goto out; | goto out; | ||||
} | } | ||||
/* | /* | ||||
* Ask NVS to allocate sub-channels. | * Ask NVS to allocate sub-channels. | ||||
*/ | */ | ||||
xact = vmbus_xact_get(sc->hn_xact, sizeof(*req)); | xact = vmbus_xact_get(sc->hn_xact, sizeof(*req)); | ||||
if (xact == NULL) { | if (xact == NULL) { | ||||
if_printf(sc->hn_ifp, "no xact for nvs subch req\n"); | if_printf(sc->hn_ifp, "no xact for nvs subch req\n"); | ||||
ret = ENXIO; | ret = ENXIO; | ||||
goto out; | goto out; | ||||
} | } | ||||
req = vmbus_xact_req_data(xact); | req = vmbus_xact_req_data(xact); | ||||
req->nvs_type = HN_NVS_TYPE_SUBCH_REQ; | req->nvs_type = HN_NVS_TYPE_SUBCH_REQ; | ||||
req->nvs_op = HN_NVS_SUBCH_OP_ALLOC; | req->nvs_op = HN_NVS_SUBCH_OP_ALLOC; | ||||
req->nvs_nsubch = net_dev->num_channel - 1; | req->nvs_nsubch = nchan - 1; | ||||
hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); | hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); | ||||
vmbus_xact_activate(xact); | vmbus_xact_activate(xact); | ||||
ret = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, | ret = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, | ||||
req, sizeof(*req), &sndc); | req, sizeof(*req), &sndc); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
if_printf(sc->hn_ifp, "send nvs subch req failed: %d\n", ret); | if_printf(sc->hn_ifp, "send nvs subch req failed: %d\n", ret); | ||||
Show All 22 Lines | hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, | ||||
nsubch = resp->nvs_nsubch; | nsubch = resp->nvs_nsubch; | ||||
vmbus_xact_put(xact); | vmbus_xact_put(xact); | ||||
if (status != HN_NVS_STATUS_OK) { | if (status != HN_NVS_STATUS_OK) { | ||||
if_printf(sc->hn_ifp, "subch req failed: %x\n", status); | if_printf(sc->hn_ifp, "subch req failed: %x\n", status); | ||||
ret = EIO; | ret = EIO; | ||||
goto out; | goto out; | ||||
} | } | ||||
if (nsubch > net_dev->num_channel - 1) { | if (nsubch > nchan - 1) { | ||||
if_printf(sc->hn_ifp, "%u subchans are allocated, requested %u\n", | if_printf(sc->hn_ifp, "%u subchans are allocated, requested %u\n", | ||||
nsubch, net_dev->num_channel - 1); | nsubch, nchan - 1); | ||||
nsubch = net_dev->num_channel - 1; | nsubch = nchan - 1; | ||||
} | } | ||||
net_dev->num_channel = nsubch + 1; | nchan = nsubch + 1; | ||||
ret = hv_rf_set_rss_param(rndis_dev, net_dev->num_channel); | ret = hv_rf_set_rss_param(rndis_dev, nchan); | ||||
*nchan0 = nchan; | |||||
out: | out: | ||||
if (ret) | |||||
net_dev->num_channel = 1; | |||||
return (ret); | return (ret); | ||||
} | } | ||||
/* | /* | ||||
* RNDIS filter on device remove | * RNDIS filter on device remove | ||||
*/ | */ | ||||
int | int | ||||
hv_rf_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel) | hv_rf_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel) | ||||
▲ Show 20 Lines • Show All 72 Lines • Show Last 20 Lines |