Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hyperv/netvsc/hv_net_vsc.c
Show First 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | |||||
static void hv_nv_on_receive_completion(struct vmbus_channel *chan, | static void hv_nv_on_receive_completion(struct vmbus_channel *chan, | ||||
uint64_t tid); | uint64_t tid); | ||||
static void hv_nv_on_receive(struct hn_softc *sc, | static void hv_nv_on_receive(struct hn_softc *sc, | ||||
struct hn_rx_ring *rxr, struct vmbus_channel *chan, | struct hn_rx_ring *rxr, struct vmbus_channel *chan, | ||||
const struct vmbus_chanpkt_hdr *pkt); | const struct vmbus_chanpkt_hdr *pkt); | ||||
static void hn_nvs_sent_none(struct hn_send_ctx *sndc, | static void hn_nvs_sent_none(struct hn_send_ctx *sndc, | ||||
struct hn_softc *, struct vmbus_channel *chan, | struct hn_softc *, struct vmbus_channel *chan, | ||||
const void *, int); | const void *, int); | ||||
static void hn_nvs_sent_xact(struct hn_send_ctx *, struct hn_softc *sc, | |||||
struct vmbus_channel *, const void *, int); | |||||
static struct hn_send_ctx hn_send_ctx_none = | static struct hn_send_ctx hn_send_ctx_none = | ||||
HN_SEND_CTX_INITIALIZER(hn_nvs_sent_none, NULL); | HN_SEND_CTX_INITIALIZER(hn_nvs_sent_none, NULL); | ||||
uint32_t | uint32_t | ||||
hn_chim_alloc(struct hn_softc *sc) | hn_chim_alloc(struct hn_softc *sc) | ||||
{ | { | ||||
int i, bmap_cnt = sc->hn_chim_bmap_cnt; | int i, bmap_cnt = sc->hn_chim_bmap_cnt; | ||||
Show All 15 Lines | if (atomic_testandset_long(&bmap[i], idx)) | ||||
continue; | continue; | ||||
ret = i * LONG_BIT + idx; | ret = i * LONG_BIT + idx; | ||||
break; | break; | ||||
} | } | ||||
return (ret); | return (ret); | ||||
} | } | ||||
const void * | |||||
hn_nvs_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact, | |||||
void *req, int reqlen, size_t *resp_len) | |||||
{ | |||||
struct hn_send_ctx sndc; | |||||
int error; | |||||
hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); | |||||
vmbus_xact_activate(xact); | |||||
error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, | |||||
req, reqlen, &sndc); | |||||
if (error) { | |||||
vmbus_xact_deactivate(xact); | |||||
return NULL; | |||||
} | |||||
return (vmbus_xact_wait(xact, resp_len)); | |||||
} | |||||
/* | /* | ||||
* 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, int rxbuf_size) | hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc, int rxbuf_size) | ||||
{ | { | ||||
struct vmbus_xact *xact; | struct vmbus_xact *xact = NULL; | ||||
struct hn_nvs_rxbuf_conn *conn; | struct hn_nvs_rxbuf_conn *conn; | ||||
const struct hn_nvs_rxbuf_connresp *resp; | const struct hn_nvs_rxbuf_connresp *resp; | ||||
size_t resp_len; | size_t resp_len; | ||||
struct hn_send_ctx sndc; | |||||
uint32_t status; | uint32_t status; | ||||
int error; | int error; | ||||
KASSERT(rxbuf_size <= NETVSC_RECEIVE_BUFFER_SIZE, | KASSERT(rxbuf_size <= NETVSC_RECEIVE_BUFFER_SIZE, | ||||
("invalid rxbuf size %d", rxbuf_size)); | ("invalid rxbuf size %d", rxbuf_size)); | ||||
/* | /* | ||||
* Connect the RXBUF GPADL to the primary channel. | * Connect the RXBUF GPADL to the primary channel. | ||||
Show All 15 Lines | hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc, int rxbuf_size) | ||||
*/ | */ | ||||
xact = vmbus_xact_get(sc->hn_xact, sizeof(*conn)); | xact = vmbus_xact_get(sc->hn_xact, sizeof(*conn)); | ||||
if (xact == NULL) { | if (xact == NULL) { | ||||
if_printf(sc->hn_ifp, "no xact for nvs rxbuf conn\n"); | if_printf(sc->hn_ifp, "no xact for nvs rxbuf conn\n"); | ||||
error = ENXIO; | error = ENXIO; | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
conn = vmbus_xact_req_data(xact); | conn = vmbus_xact_req_data(xact); | ||||
conn->nvs_type = HN_NVS_TYPE_RXBUF_CONN; | conn->nvs_type = HN_NVS_TYPE_RXBUF_CONN; | ||||
conn->nvs_gpadl = sc->hn_rxbuf_gpadl; | conn->nvs_gpadl = sc->hn_rxbuf_gpadl; | ||||
conn->nvs_sig = HN_NVS_RXBUF_SIG; | conn->nvs_sig = HN_NVS_RXBUF_SIG; | ||||
hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); | resp = hn_nvs_xact_execute(sc, xact, conn, sizeof(*conn), &resp_len); | ||||
vmbus_xact_activate(xact); | if (resp == NULL) { | ||||
if_printf(sc->hn_ifp, "exec rxbuf conn failed\n"); | |||||
error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, | error = EIO; | ||||
conn, sizeof(*conn), &sndc); | |||||
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; | ||||
} | } | ||||
resp = vmbus_xact_wait(xact, &resp_len); | |||||
if (resp_len < sizeof(*resp)) { | if (resp_len < sizeof(*resp)) { | ||||
if_printf(sc->hn_ifp, "invalid rxbuf conn resp length %zu\n", | if_printf(sc->hn_ifp, "invalid rxbuf conn resp length %zu\n", | ||||
resp_len); | resp_len); | ||||
vmbus_xact_put(xact); | |||||
error = EINVAL; | error = EINVAL; | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
if (resp->nvs_type != HN_NVS_TYPE_RXBUF_CONNRESP) { | if (resp->nvs_type != HN_NVS_TYPE_RXBUF_CONNRESP) { | ||||
if_printf(sc->hn_ifp, "not rxbuf conn resp, type %u\n", | if_printf(sc->hn_ifp, "not rxbuf conn resp, type %u\n", | ||||
resp->nvs_type); | resp->nvs_type); | ||||
vmbus_xact_put(xact); | |||||
error = EINVAL; | error = EINVAL; | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
status = resp->nvs_status; | status = resp->nvs_status; | ||||
vmbus_xact_put(xact); | vmbus_xact_put(xact); | ||||
xact = NULL; | |||||
if (status != HN_NVS_STATUS_OK) { | if (status != HN_NVS_STATUS_OK) { | ||||
if_printf(sc->hn_ifp, "rxbuf conn failed: %x\n", status); | if_printf(sc->hn_ifp, "rxbuf conn failed: %x\n", status); | ||||
error = EIO; | error = EIO; | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
sc->hn_flags |= HN_FLAG_RXBUF_CONNECTED; | sc->hn_flags |= HN_FLAG_RXBUF_CONNECTED; | ||||
return (0); | return (0); | ||||
cleanup: | cleanup: | ||||
if (xact != NULL) | |||||
vmbus_xact_put(xact); | |||||
hv_nv_destroy_rx_buffer(sc); | hv_nv_destroy_rx_buffer(sc); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* 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) | ||||
{ | { | ||||
struct hn_send_ctx sndc; | struct vmbus_xact *xact = NULL; | ||||
struct vmbus_xact *xact; | |||||
struct hn_nvs_chim_conn *chim; | struct hn_nvs_chim_conn *chim; | ||||
const struct hn_nvs_chim_connresp *resp; | const struct hn_nvs_chim_connresp *resp; | ||||
size_t resp_len; | size_t resp_len; | ||||
uint32_t status, sectsz; | uint32_t status, sectsz; | ||||
int error; | int error; | ||||
/* | /* | ||||
* Connect chimney sending buffer GPADL to the primary channel. | * Connect chimney sending buffer GPADL to the primary channel. | ||||
Show All 16 Lines | hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc) | ||||
*/ | */ | ||||
xact = vmbus_xact_get(sc->hn_xact, sizeof(*chim)); | xact = vmbus_xact_get(sc->hn_xact, sizeof(*chim)); | ||||
if (xact == NULL) { | if (xact == NULL) { | ||||
if_printf(sc->hn_ifp, "no xact for nvs chim conn\n"); | if_printf(sc->hn_ifp, "no xact for nvs chim conn\n"); | ||||
error = ENXIO; | error = ENXIO; | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
chim = vmbus_xact_req_data(xact); | chim = vmbus_xact_req_data(xact); | ||||
chim->nvs_type = HN_NVS_TYPE_CHIM_CONN; | chim->nvs_type = HN_NVS_TYPE_CHIM_CONN; | ||||
chim->nvs_gpadl = sc->hn_chim_gpadl; | chim->nvs_gpadl = sc->hn_chim_gpadl; | ||||
chim->nvs_sig = HN_NVS_CHIM_SIG; | chim->nvs_sig = HN_NVS_CHIM_SIG; | ||||
hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); | resp = hn_nvs_xact_execute(sc, xact, chim, sizeof(*chim), &resp_len); | ||||
vmbus_xact_activate(xact); | if (resp == NULL) { | ||||
if_printf(sc->hn_ifp, "exec chim conn failed\n"); | |||||
error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, | error = EIO; | ||||
chim, sizeof(*chim), &sndc); | |||||
if (error) { | |||||
if_printf(sc->hn_ifp, "send nvs chim conn failed: %d\n", | |||||
error); | |||||
vmbus_xact_deactivate(xact); | |||||
vmbus_xact_put(xact); | |||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
resp = vmbus_xact_wait(xact, &resp_len); | |||||
if (resp_len < sizeof(*resp)) { | if (resp_len < sizeof(*resp)) { | ||||
if_printf(sc->hn_ifp, "invalid chim conn resp length %zu\n", | if_printf(sc->hn_ifp, "invalid chim conn resp length %zu\n", | ||||
resp_len); | resp_len); | ||||
vmbus_xact_put(xact); | |||||
error = EINVAL; | error = EINVAL; | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
if (resp->nvs_type != HN_NVS_TYPE_CHIM_CONNRESP) { | if (resp->nvs_type != HN_NVS_TYPE_CHIM_CONNRESP) { | ||||
if_printf(sc->hn_ifp, "not chim conn resp, type %u\n", | if_printf(sc->hn_ifp, "not chim conn resp, type %u\n", | ||||
resp->nvs_type); | resp->nvs_type); | ||||
vmbus_xact_put(xact); | |||||
error = EINVAL; | error = EINVAL; | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
status = resp->nvs_status; | status = resp->nvs_status; | ||||
sectsz = resp->nvs_sectsz; | sectsz = resp->nvs_sectsz; | ||||
vmbus_xact_put(xact); | vmbus_xact_put(xact); | ||||
xact = NULL; | |||||
if (status != HN_NVS_STATUS_OK) { | if (status != HN_NVS_STATUS_OK) { | ||||
if_printf(sc->hn_ifp, "chim conn failed: %x\n", status); | if_printf(sc->hn_ifp, "chim conn failed: %x\n", status); | ||||
error = EIO; | error = EIO; | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
if (sectsz == 0) { | if (sectsz == 0) { | ||||
if_printf(sc->hn_ifp, "zero chimney sending buffer " | if_printf(sc->hn_ifp, "zero chimney sending buffer " | ||||
Show All 20 Lines | hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc) | ||||
sc->hn_flags |= HN_FLAG_CHIM_CONNECTED; | sc->hn_flags |= HN_FLAG_CHIM_CONNECTED; | ||||
if (bootverbose) { | if (bootverbose) { | ||||
if_printf(sc->hn_ifp, "chimney sending buffer %d/%d\n", | if_printf(sc->hn_ifp, "chimney sending buffer %d/%d\n", | ||||
sc->hn_chim_szmax, sc->hn_chim_cnt); | sc->hn_chim_szmax, sc->hn_chim_cnt); | ||||
} | } | ||||
return 0; | return 0; | ||||
cleanup: | cleanup: | ||||
if (xact != NULL) | |||||
vmbus_xact_put(xact); | |||||
hv_nv_destroy_send_buffer(sc); | hv_nv_destroy_send_buffer(sc); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Net VSC destroy receive buffer | * Net VSC destroy receive buffer | ||||
*/ | */ | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | hv_nv_destroy_send_buffer(struct hn_softc *sc) | ||||
} | } | ||||
return (ret); | return (ret); | ||||
} | } | ||||
static int | static int | ||||
hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, uint32_t nvs_ver) | hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, uint32_t nvs_ver) | ||||
{ | { | ||||
struct hn_send_ctx sndc; | |||||
struct vmbus_xact *xact; | struct vmbus_xact *xact; | ||||
struct hn_nvs_init *init; | struct hn_nvs_init *init; | ||||
const struct hn_nvs_init_resp *resp; | const struct hn_nvs_init_resp *resp; | ||||
size_t resp_len; | size_t resp_len; | ||||
uint32_t status; | uint32_t status; | ||||
int error; | |||||
xact = vmbus_xact_get(sc->hn_xact, sizeof(*init)); | xact = vmbus_xact_get(sc->hn_xact, sizeof(*init)); | ||||
if (xact == NULL) { | if (xact == NULL) { | ||||
if_printf(sc->hn_ifp, "no xact for nvs init\n"); | if_printf(sc->hn_ifp, "no xact for nvs init\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
init = vmbus_xact_req_data(xact); | init = vmbus_xact_req_data(xact); | ||||
init->nvs_type = HN_NVS_TYPE_INIT; | init->nvs_type = HN_NVS_TYPE_INIT; | ||||
init->nvs_ver_min = nvs_ver; | init->nvs_ver_min = nvs_ver; | ||||
init->nvs_ver_max = nvs_ver; | init->nvs_ver_max = nvs_ver; | ||||
vmbus_xact_activate(xact); | resp = hn_nvs_xact_execute(sc, xact, init, sizeof(*init), &resp_len); | ||||
hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact); | if (resp == NULL) { | ||||
if_printf(sc->hn_ifp, "exec init failed\n"); | |||||
error = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC, | |||||
init, sizeof(*init), &sndc); | |||||
if (error) { | |||||
if_printf(sc->hn_ifp, "send nvs init failed: %d\n", error); | |||||
vmbus_xact_deactivate(xact); | |||||
vmbus_xact_put(xact); | vmbus_xact_put(xact); | ||||
return (error); | return (EIO); | ||||
} | } | ||||
resp = vmbus_xact_wait(xact, &resp_len); | |||||
if (resp_len < sizeof(*resp)) { | if (resp_len < sizeof(*resp)) { | ||||
if_printf(sc->hn_ifp, "invalid init resp length %zu\n", | if_printf(sc->hn_ifp, "invalid init resp length %zu\n", | ||||
resp_len); | resp_len); | ||||
vmbus_xact_put(xact); | vmbus_xact_put(xact); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
if (resp->nvs_type != HN_NVS_TYPE_INIT_RESP) { | if (resp->nvs_type != HN_NVS_TYPE_INIT_RESP) { | ||||
if_printf(sc->hn_ifp, "not init resp, type %u\n", | if_printf(sc->hn_ifp, "not init resp, type %u\n", | ||||
▲ Show 20 Lines • Show All 188 Lines • ▼ Show 20 Lines | hv_nv_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel) | ||||
/* Now, we can close the channel safely */ | /* Now, we can close the channel safely */ | ||||
vmbus_chan_close(sc->hn_prichan); | vmbus_chan_close(sc->hn_prichan); | ||||
return (0); | return (0); | ||||
} | } | ||||
void | static void | ||||
hn_nvs_sent_xact(struct hn_send_ctx *sndc, | hn_nvs_sent_xact(struct hn_send_ctx *sndc, | ||||
struct hn_softc *sc __unused, struct vmbus_channel *chan __unused, | struct hn_softc *sc __unused, struct vmbus_channel *chan __unused, | ||||
const void *data, int dlen) | const void *data, int dlen) | ||||
{ | { | ||||
vmbus_xact_wakeup(sndc->hn_cbarg, data, dlen); | vmbus_xact_wakeup(sndc->hn_cbarg, data, dlen); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 234 Lines • Show Last 20 Lines |