Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/netvsc/hv_net_vsc.c
Show First 20 Lines • Show All 146 Lines • ▼ Show 20 Lines | |||||
* Net VSC initialize receive buffer with net VSP | * Net VSC initialize receive buffer with net VSP | ||||
* | * | ||||
* Net VSP: Network virtual services client, also known as the | * Net VSP: Network virtual services client, also known as the | ||||
* Hyper-V extensible switch and the synthetic data path. | * Hyper-V extensible switch and the synthetic data path. | ||||
*/ | */ | ||||
static int | static int | ||||
hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc) | hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc) | ||||
{ | { | ||||
struct vmbus_xact *xact; | |||||
struct hn_nvs_rxbuf_conn *conn; | |||||
const struct hn_nvs_rxbuf_connresp *resp; | |||||
size_t resp_len; | |||||
struct hn_send_ctx sndc; | struct hn_send_ctx sndc; | ||||
netvsc_dev *net_dev; | netvsc_dev *net_dev; | ||||
nvsp_msg *init_pkt; | uint32_t status; | ||||
int ret = 0; | int error; | ||||
net_dev = hv_nv_get_outbound_net_device(sc); | net_dev = hv_nv_get_outbound_net_device(sc); | ||||
if (!net_dev) { | if (!net_dev) { | ||||
return (ENODEV); | return (ENODEV); | ||||
} | } | ||||
net_dev->rx_buf = hyperv_dmamem_alloc(bus_get_dma_tag(sc->hn_dev), | net_dev->rx_buf = hyperv_dmamem_alloc(bus_get_dma_tag(sc->hn_dev), | ||||
PAGE_SIZE, 0, net_dev->rx_buf_size, &net_dev->rxbuf_dma, | PAGE_SIZE, 0, net_dev->rx_buf_size, &net_dev->rxbuf_dma, | ||||
BUS_DMA_WAITOK | BUS_DMA_ZERO); | BUS_DMA_WAITOK | BUS_DMA_ZERO); | ||||
if (net_dev->rx_buf == NULL) { | if (net_dev->rx_buf == NULL) { | ||||
device_printf(sc->hn_dev, "allocate rxbuf failed\n"); | device_printf(sc->hn_dev, "allocate rxbuf failed\n"); | ||||
return ENOMEM; | return (ENOMEM); | ||||
} | } | ||||
/* | /* | ||||
* Connect the RXBUF GPADL to the primary channel. | * Connect the RXBUF GPADL to the primary channel. | ||||
* | * | ||||
* NOTE: | * NOTE: | ||||
* Only primary channel has RXBUF connected to it. Sub-channels | * Only primary channel has RXBUF connected to it. Sub-channels | ||||
* just share this RXBUF. | * just share this RXBUF. | ||||
*/ | */ | ||||
ret = vmbus_chan_gpadl_connect(sc->hn_prichan, | error = vmbus_chan_gpadl_connect(sc->hn_prichan, | ||||
net_dev->rxbuf_dma.hv_paddr, net_dev->rx_buf_size, | net_dev->rxbuf_dma.hv_paddr, net_dev->rx_buf_size, | ||||
&net_dev->rx_buf_gpadl_handle); | &net_dev->rx_buf_gpadl_handle); | ||||
if (ret != 0) { | if (error) { | ||||
device_printf(sc->hn_dev, "rxbuf gpadl connect failed: %d\n", | if_printf(sc->hn_ifp, "rxbuf gpadl connect failed: %d\n", | ||||
ret); | error); | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
/* sema_wait(&ext->channel_init_sema); KYS CHECK */ | /* | ||||
* Connect RXBUF to NVS. | |||||
*/ | |||||
/* Notify the NetVsp of the gpadl handle */ | xact = vmbus_xact_get(sc->hn_xact, sizeof(*conn)); | ||||
init_pkt = &net_dev->channel_init_packet; | if (xact == NULL) { | ||||
if_printf(sc->hn_ifp, "no xact for nvs rxbuf conn\n"); | |||||
error = ENXIO; | |||||
goto cleanup; | |||||
} | |||||
memset(init_pkt, 0, sizeof(nvsp_msg)); | conn = vmbus_xact_req_data(xact); | ||||
conn->nvs_type = HN_NVS_TYPE_RXBUF_CONN; | |||||
conn->nvs_gpadl = net_dev->rx_buf_gpadl_handle; | |||||
conn->nvs_sig = HN_NVS_RXBUF_SIG; | |||||
init_pkt->hdr.msg_type = nvsp_msg_1_type_send_rx_buf; | hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); | ||||
init_pkt->msgs.vers_1_msgs.send_rx_buf.gpadl_handle = | vmbus_xact_activate(xact); | ||||
net_dev->rx_buf_gpadl_handle; | |||||
init_pkt->msgs.vers_1_msgs.send_rx_buf.id = | |||||
NETVSC_RECEIVE_BUFFER_ID; | |||||
/* Send the gpadl notification request */ | error = vmbus_chan_send(sc->hn_prichan, | ||||
hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL); | |||||
ret = vmbus_chan_send(sc->hn_prichan, | |||||
VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, | VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, | ||||
init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc); | conn, sizeof(*conn), (uint64_t)(uintptr_t)&sndc); | ||||
if (ret != 0) { | if (error != 0) { | ||||
if_printf(sc->hn_ifp, "send nvs rxbuf conn failed: %d\n", | |||||
error); | |||||
vmbus_xact_deactivate(xact); | |||||
vmbus_xact_put(xact); | |||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
sema_wait(&net_dev->channel_init_sema); | resp = vmbus_xact_wait(xact, &resp_len); | ||||
if (resp_len < sizeof(*resp)) { | |||||
/* Check the response */ | if_printf(sc->hn_ifp, "invalid rxbuf conn resp length %zu\n", | ||||
if (init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.status | resp_len); | ||||
!= nvsp_status_success) { | vmbus_xact_put(xact); | ||||
ret = EINVAL; | error = EINVAL; | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
if (resp->nvs_type != HN_NVS_TYPE_RXBUF_CONNRESP) { | |||||
if_printf(sc->hn_ifp, "not rxbuf conn resp, type %u\n", | |||||
resp->nvs_type); | |||||
vmbus_xact_put(xact); | |||||
error = EINVAL; | |||||
goto cleanup; | |||||
} | |||||
net_dev->rx_section_count = | status = resp->nvs_status; | ||||
init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.num_sections; | vmbus_xact_put(xact); | ||||
net_dev->rx_sections = malloc(net_dev->rx_section_count * | if (status != HN_NVS_STATUS_OK) { | ||||
sizeof(nvsp_1_rx_buf_section), M_NETVSC, M_WAITOK); | if_printf(sc->hn_ifp, "rxbuf conn failed: %x\n", status); | ||||
memcpy(net_dev->rx_sections, | error = EINVAL; | ||||
init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.sections, | |||||
net_dev->rx_section_count * sizeof(nvsp_1_rx_buf_section)); | |||||
/* | |||||
* For first release, there should only be 1 section that represents | |||||
* the entire receive buffer | |||||
*/ | |||||
if (net_dev->rx_section_count != 1 | |||||
|| net_dev->rx_sections->offset != 0) { | |||||
ret = EINVAL; | |||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
net_dev->rx_section_count = 1; | |||||
goto exit; | return (0); | ||||
cleanup: | cleanup: | ||||
hv_nv_destroy_rx_buffer(net_dev); | hv_nv_destroy_rx_buffer(net_dev); | ||||
return (error); | |||||
exit: | |||||
return (ret); | |||||
} | } | ||||
/* | /* | ||||
* Net VSC initialize send buffer with net VSP | * Net VSC initialize send buffer with net VSP | ||||
*/ | */ | ||||
static int | static int | ||||
hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc) | hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | ret = vmbus_chan_send(net_dev->sc->hn_prichan, | ||||
(uint64_t)(uintptr_t)&hn_send_ctx_none); | (uint64_t)(uintptr_t)&hn_send_ctx_none); | ||||
/* | /* | ||||
* If we failed here, we might as well return and have a leak | * If we failed here, we might as well return and have a leak | ||||
* rather than continue and a bugchk | * rather than continue and a bugchk | ||||
*/ | */ | ||||
if (ret != 0) { | if (ret != 0) { | ||||
return (ret); | return (ret); | ||||
} | } | ||||
net_dev->rx_section_count = 0; | |||||
} | } | ||||
/* Tear down the gpadl on the vsp end */ | /* Tear down the gpadl on the vsp end */ | ||||
if (net_dev->rx_buf_gpadl_handle) { | if (net_dev->rx_buf_gpadl_handle) { | ||||
ret = vmbus_chan_gpadl_disconnect(net_dev->sc->hn_prichan, | ret = vmbus_chan_gpadl_disconnect(net_dev->sc->hn_prichan, | ||||
net_dev->rx_buf_gpadl_handle); | net_dev->rx_buf_gpadl_handle); | ||||
/* | /* | ||||
* If we failed here, we might as well return and have a leak | * If we failed here, we might as well return and have a leak | ||||
* rather than continue and a bugchk | * rather than continue and a bugchk | ||||
*/ | */ | ||||
if (ret != 0) { | if (ret != 0) { | ||||
return (ret); | return (ret); | ||||
} | } | ||||
net_dev->rx_buf_gpadl_handle = 0; | net_dev->rx_buf_gpadl_handle = 0; | ||||
} | } | ||||
if (net_dev->rx_buf) { | if (net_dev->rx_buf) { | ||||
/* Free up the receive buffer */ | /* Free up the receive buffer */ | ||||
hyperv_dmamem_free(&net_dev->rxbuf_dma, net_dev->rx_buf); | hyperv_dmamem_free(&net_dev->rxbuf_dma, net_dev->rx_buf); | ||||
net_dev->rx_buf = NULL; | net_dev->rx_buf = NULL; | ||||
} | |||||
if (net_dev->rx_sections) { | |||||
free(net_dev->rx_sections, M_NETVSC); | |||||
net_dev->rx_sections = NULL; | |||||
net_dev->rx_section_count = 0; | |||||
} | } | ||||
return (ret); | return (ret); | ||||
} | } | ||||
/* | /* | ||||
* Net VSC destroy send buffer | * Net VSC destroy send buffer | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 641 Lines • Show Last 20 Lines |