Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/hyperv/netvsc/hv_net_vsc.c
Show First 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | |||||
static int hv_nv_connect_to_vsp(struct hn_softc *sc); | static int hv_nv_connect_to_vsp(struct hn_softc *sc); | ||||
static void hv_nv_on_send_completion(netvsc_dev *net_dev, | static void hv_nv_on_send_completion(netvsc_dev *net_dev, | ||||
struct vmbus_channel *, const struct vmbus_chanpkt_hdr *pkt); | struct vmbus_channel *, const struct vmbus_chanpkt_hdr *pkt); | ||||
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, uint32_t status); | uint64_t tid, uint32_t status); | ||||
static void hv_nv_on_receive(netvsc_dev *net_dev, | static void hv_nv_on_receive(netvsc_dev *net_dev, | ||||
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, | |||||
struct netvsc_dev_ *net_dev, struct vmbus_channel *chan, | |||||
const struct nvsp_msg_ *msg); | |||||
static struct hn_send_ctx hn_send_ctx_none = | |||||
HN_SEND_CTX_INITIALIZER(hn_nvs_sent_none, NULL); | |||||
/* | /* | ||||
* | * | ||||
*/ | */ | ||||
static inline netvsc_dev * | static inline netvsc_dev * | ||||
hv_nv_alloc_net_device(struct hn_softc *sc) | hv_nv_alloc_net_device(struct hn_softc *sc) | ||||
{ | { | ||||
netvsc_dev *net_dev; | netvsc_dev *net_dev; | ||||
▲ Show 20 Lines • Show All 56 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 hn_send_ctx sndc; | |||||
netvsc_dev *net_dev; | netvsc_dev *net_dev; | ||||
nvsp_msg *init_pkt; | nvsp_msg *init_pkt; | ||||
int ret = 0; | int ret = 0; | ||||
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); | ||||
} | } | ||||
Show All 32 Lines | hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc) | ||||
init_pkt->hdr.msg_type = nvsp_msg_1_type_send_rx_buf; | init_pkt->hdr.msg_type = nvsp_msg_1_type_send_rx_buf; | ||||
init_pkt->msgs.vers_1_msgs.send_rx_buf.gpadl_handle = | init_pkt->msgs.vers_1_msgs.send_rx_buf.gpadl_handle = | ||||
net_dev->rx_buf_gpadl_handle; | net_dev->rx_buf_gpadl_handle; | ||||
init_pkt->msgs.vers_1_msgs.send_rx_buf.id = | init_pkt->msgs.vers_1_msgs.send_rx_buf.id = | ||||
NETVSC_RECEIVE_BUFFER_ID; | NETVSC_RECEIVE_BUFFER_ID; | ||||
/* Send the gpadl notification request */ | /* Send the gpadl notification request */ | ||||
hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL); | |||||
ret = vmbus_chan_send(sc->hn_prichan, | 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)init_pkt); | init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
sema_wait(&net_dev->channel_init_sema); | sema_wait(&net_dev->channel_init_sema); | ||||
/* Check the response */ | /* Check the response */ | ||||
if (init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.status | if (init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.status | ||||
Show All 32 Lines | |||||
} | } | ||||
/* | /* | ||||
* 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; | |||||
netvsc_dev *net_dev; | netvsc_dev *net_dev; | ||||
nvsp_msg *init_pkt; | nvsp_msg *init_pkt; | ||||
int ret = 0; | int ret = 0; | ||||
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); | ||||
} | } | ||||
Show All 31 Lines | hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc) | ||||
init_pkt->hdr.msg_type = nvsp_msg_1_type_send_send_buf; | init_pkt->hdr.msg_type = nvsp_msg_1_type_send_send_buf; | ||||
init_pkt->msgs.vers_1_msgs.send_rx_buf.gpadl_handle = | init_pkt->msgs.vers_1_msgs.send_rx_buf.gpadl_handle = | ||||
net_dev->send_buf_gpadl_handle; | net_dev->send_buf_gpadl_handle; | ||||
init_pkt->msgs.vers_1_msgs.send_rx_buf.id = | init_pkt->msgs.vers_1_msgs.send_rx_buf.id = | ||||
NETVSC_SEND_BUFFER_ID; | NETVSC_SEND_BUFFER_ID; | ||||
/* Send the gpadl notification request */ | /* Send the gpadl notification request */ | ||||
hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL); | |||||
ret = vmbus_chan_send(sc->hn_prichan, | 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)init_pkt); | init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
sema_wait(&net_dev->channel_init_sema); | sema_wait(&net_dev->channel_init_sema); | ||||
/* Check the response */ | /* Check the response */ | ||||
if (init_pkt->msgs.vers_1_msgs.send_send_buf_complete.status | if (init_pkt->msgs.vers_1_msgs.send_send_buf_complete.status | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | if (net_dev->rx_section_count) { | ||||
memset(revoke_pkt, 0, sizeof(nvsp_msg)); | memset(revoke_pkt, 0, sizeof(nvsp_msg)); | ||||
revoke_pkt->hdr.msg_type = nvsp_msg_1_type_revoke_rx_buf; | revoke_pkt->hdr.msg_type = nvsp_msg_1_type_revoke_rx_buf; | ||||
revoke_pkt->msgs.vers_1_msgs.revoke_rx_buf.id = | revoke_pkt->msgs.vers_1_msgs.revoke_rx_buf.id = | ||||
NETVSC_RECEIVE_BUFFER_ID; | NETVSC_RECEIVE_BUFFER_ID; | ||||
ret = vmbus_chan_send(net_dev->sc->hn_prichan, | ret = vmbus_chan_send(net_dev->sc->hn_prichan, | ||||
VMBUS_CHANPKT_TYPE_INBAND, 0, revoke_pkt, sizeof(nvsp_msg), | VMBUS_CHANPKT_TYPE_INBAND, 0, revoke_pkt, sizeof(nvsp_msg), | ||||
(uint64_t)(uintptr_t)revoke_pkt); | (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); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | if (net_dev->send_section_size) { | ||||
memset(revoke_pkt, 0, sizeof(nvsp_msg)); | memset(revoke_pkt, 0, sizeof(nvsp_msg)); | ||||
revoke_pkt->hdr.msg_type = | revoke_pkt->hdr.msg_type = | ||||
nvsp_msg_1_type_revoke_send_buf; | nvsp_msg_1_type_revoke_send_buf; | ||||
revoke_pkt->msgs.vers_1_msgs.revoke_send_buf.id = | revoke_pkt->msgs.vers_1_msgs.revoke_send_buf.id = | ||||
NETVSC_SEND_BUFFER_ID; | NETVSC_SEND_BUFFER_ID; | ||||
ret = vmbus_chan_send(net_dev->sc->hn_prichan, | ret = vmbus_chan_send(net_dev->sc->hn_prichan, | ||||
VMBUS_CHANPKT_TYPE_INBAND, 0, | VMBUS_CHANPKT_TYPE_INBAND, 0, revoke_pkt, sizeof(nvsp_msg), | ||||
revoke_pkt, sizeof(nvsp_msg), | (uint64_t)(uintptr_t)&hn_send_ctx_none); | ||||
(uint64_t)(uintptr_t)revoke_pkt); | |||||
/* | /* | ||||
* 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); | ||||
} | } | ||||
} | } | ||||
Show All 33 Lines | |||||
* For NVSP v2, Server 2008 R2 does not set | * For NVSP v2, Server 2008 R2 does not set | ||||
* init_pkt->msgs.init_msgs.init_compl.negotiated_prot_vers | * init_pkt->msgs.init_msgs.init_compl.negotiated_prot_vers | ||||
* to the negotiated version, so we cannot rely on that. | * to the negotiated version, so we cannot rely on that. | ||||
*/ | */ | ||||
static int | static int | ||||
hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, netvsc_dev *net_dev, | hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, netvsc_dev *net_dev, | ||||
uint32_t nvsp_ver) | uint32_t nvsp_ver) | ||||
{ | { | ||||
struct hn_send_ctx sndc; | |||||
nvsp_msg *init_pkt; | nvsp_msg *init_pkt; | ||||
int ret; | int ret; | ||||
init_pkt = &net_dev->channel_init_packet; | init_pkt = &net_dev->channel_init_packet; | ||||
memset(init_pkt, 0, sizeof(nvsp_msg)); | memset(init_pkt, 0, sizeof(nvsp_msg)); | ||||
init_pkt->hdr.msg_type = nvsp_msg_type_init; | init_pkt->hdr.msg_type = nvsp_msg_type_init; | ||||
/* | /* | ||||
* Specify parameter as the only acceptable protocol version | * Specify parameter as the only acceptable protocol version | ||||
*/ | */ | ||||
init_pkt->msgs.init_msgs.init.p1.protocol_version = nvsp_ver; | init_pkt->msgs.init_msgs.init.p1.protocol_version = nvsp_ver; | ||||
init_pkt->msgs.init_msgs.init.protocol_version_2 = nvsp_ver; | init_pkt->msgs.init_msgs.init.protocol_version_2 = nvsp_ver; | ||||
/* Send the init request */ | /* Send the init request */ | ||||
hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL); | |||||
ret = vmbus_chan_send(sc->hn_prichan, | 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)init_pkt); | init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc); | ||||
if (ret != 0) | if (ret != 0) | ||||
return (-1); | return (-1); | ||||
sema_wait(&net_dev->channel_init_sema); | sema_wait(&net_dev->channel_init_sema); | ||||
if (init_pkt->msgs.init_msgs.init_compl.status != nvsp_status_success) | if (init_pkt->msgs.init_msgs.init_compl.status != nvsp_status_success) | ||||
return (EINVAL); | return (EINVAL); | ||||
Show All 25 Lines | hv_nv_send_ndis_config(struct hn_softc *sc, uint32_t mtu) | ||||
init_pkt->hdr.msg_type = nvsp_msg_2_type_send_ndis_config; | init_pkt->hdr.msg_type = nvsp_msg_2_type_send_ndis_config; | ||||
init_pkt->msgs.vers_2_msgs.send_ndis_config.mtu = mtu; | init_pkt->msgs.vers_2_msgs.send_ndis_config.mtu = mtu; | ||||
init_pkt-> | init_pkt-> | ||||
msgs.vers_2_msgs.send_ndis_config.capabilities.u1.u2.ieee8021q | msgs.vers_2_msgs.send_ndis_config.capabilities.u1.u2.ieee8021q | ||||
= 1; | = 1; | ||||
/* Send the configuration packet */ | /* Send the configuration packet */ | ||||
ret = vmbus_chan_send(sc->hn_prichan, VMBUS_CHANPKT_TYPE_INBAND, 0, | ret = vmbus_chan_send(sc->hn_prichan, VMBUS_CHANPKT_TYPE_INBAND, 0, | ||||
init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt); | init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&hn_send_ctx_none); | ||||
if (ret != 0) | if (ret != 0) | ||||
return (-EINVAL); | return (-EINVAL); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Net VSC connect to VSP | * Net VSC connect to VSP | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | hv_nv_connect_to_vsp(struct hn_softc *sc) | ||||
init_pkt->msgs.vers_1_msgs.send_ndis_vers.ndis_major_vers = | init_pkt->msgs.vers_1_msgs.send_ndis_vers.ndis_major_vers = | ||||
(ndis_version & 0xFFFF0000) >> 16; | (ndis_version & 0xFFFF0000) >> 16; | ||||
init_pkt->msgs.vers_1_msgs.send_ndis_vers.ndis_minor_vers = | init_pkt->msgs.vers_1_msgs.send_ndis_vers.ndis_minor_vers = | ||||
ndis_version & 0xFFFF; | ndis_version & 0xFFFF; | ||||
/* Send the init request */ | /* Send the init request */ | ||||
ret = vmbus_chan_send(sc->hn_prichan, VMBUS_CHANPKT_TYPE_INBAND, 0, | ret = vmbus_chan_send(sc->hn_prichan, VMBUS_CHANPKT_TYPE_INBAND, 0, | ||||
init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt); | init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&hn_send_ctx_none); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
/* | /* | ||||
* TODO: BUGBUG - We have to wait for the above msg since the netvsp | * TODO: BUGBUG - We have to wait for the above msg since the netvsp | ||||
* uses KMCL which acknowledges packet (completion packet) | * uses KMCL which acknowledges packet (completion packet) | ||||
* since our Vmbus always set the VMBUS_CHANPKT_FLAG_RC flag | * since our Vmbus always set the VMBUS_CHANPKT_FLAG_RC flag | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | hv_nv_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel) | ||||
vmbus_chan_close(sc->hn_prichan); | vmbus_chan_close(sc->hn_prichan); | ||||
sema_destroy(&net_dev->channel_init_sema); | sema_destroy(&net_dev->channel_init_sema); | ||||
free(net_dev, M_NETVSC); | free(net_dev, M_NETVSC); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | void | ||||
* Net VSC on send completion | hn_nvs_sent_wakeup(struct hn_send_ctx *sndc __unused, | ||||
*/ | struct netvsc_dev_ *net_dev, struct vmbus_channel *chan __unused, | ||||
static void | const struct nvsp_msg_ *msg) | ||||
hv_nv_on_send_completion(netvsc_dev *net_dev, struct vmbus_channel *chan, | |||||
const struct vmbus_chanpkt_hdr *pkt) | |||||
{ | { | ||||
const nvsp_msg *nvsp_msg_pkt; | |||||
netvsc_packet *net_vsc_pkt; | |||||
nvsp_msg_pkt = VMBUS_CHANPKT_CONST_DATA(pkt); | |||||
if (nvsp_msg_pkt->hdr.msg_type == nvsp_msg_type_init_complete | |||||
|| nvsp_msg_pkt->hdr.msg_type | |||||
== nvsp_msg_1_type_send_rx_buf_complete | |||||
|| nvsp_msg_pkt->hdr.msg_type | |||||
== nvsp_msg_1_type_send_send_buf_complete | |||||
|| nvsp_msg_pkt->hdr.msg_type | |||||
== nvsp_msg5_type_subchannel) { | |||||
/* Copy the response back */ | /* Copy the response back */ | ||||
memcpy(&net_dev->channel_init_packet, nvsp_msg_pkt, | memcpy(&net_dev->channel_init_packet, msg, sizeof(nvsp_msg)); | ||||
sizeof(nvsp_msg)); | |||||
sema_post(&net_dev->channel_init_sema); | sema_post(&net_dev->channel_init_sema); | ||||
} else if (nvsp_msg_pkt->hdr.msg_type == | } | ||||
nvsp_msg_1_type_send_rndis_pkt_complete) { | |||||
/* Get the send context */ | static void | ||||
net_vsc_pkt = | hn_nvs_sent_none(struct hn_send_ctx *sndc __unused, | ||||
(netvsc_packet *)(unsigned long)pkt->cph_xactid; | struct netvsc_dev_ *net_dev __unused, struct vmbus_channel *chan __unused, | ||||
if (NULL != net_vsc_pkt) { | const struct nvsp_msg_ *msg __unused) | ||||
if (net_vsc_pkt->send_buf_section_idx != | { | ||||
NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) { | /* EMPTY */ | ||||
} | |||||
void | |||||
hn_chim_free(struct netvsc_dev_ *net_dev, uint32_t chim_idx) | |||||
{ | |||||
u_long mask; | u_long mask; | ||||
int idx; | uint32_t idx; | ||||
idx = net_vsc_pkt->send_buf_section_idx / | idx = chim_idx / BITS_PER_LONG; | ||||
BITS_PER_LONG; | |||||
KASSERT(idx < net_dev->bitsmap_words, | KASSERT(idx < net_dev->bitsmap_words, | ||||
("invalid section index %u", | ("invalid chimney index 0x%x", chim_idx)); | ||||
net_vsc_pkt->send_buf_section_idx)); | |||||
mask = 1UL << | |||||
(net_vsc_pkt->send_buf_section_idx % | |||||
BITS_PER_LONG); | |||||
KASSERT(net_dev->send_section_bitsmap[idx] & | mask = 1UL << (chim_idx % BITS_PER_LONG); | ||||
mask, | KASSERT(net_dev->send_section_bitsmap[idx] & mask, | ||||
("index bitmap 0x%lx, section index %u, " | ("index bitmap 0x%lx, chimney index %u, " | ||||
"bitmap idx %d, bitmask 0x%lx", | "bitmap idx %d, bitmask 0x%lx", | ||||
net_dev->send_section_bitsmap[idx], | net_dev->send_section_bitsmap[idx], chim_idx, idx, mask)); | ||||
net_vsc_pkt->send_buf_section_idx, | |||||
idx, mask)); | atomic_clear_long(&net_dev->send_section_bitsmap[idx], mask); | ||||
atomic_clear_long( | |||||
&net_dev->send_section_bitsmap[idx], mask); | |||||
} | } | ||||
/* Notify the layer above us */ | /* | ||||
net_vsc_pkt->compl.send.on_send_completion(chan, | * Net VSC on send completion | ||||
net_vsc_pkt->compl.send.send_completion_context); | */ | ||||
static void | |||||
hv_nv_on_send_completion(netvsc_dev *net_dev, struct vmbus_channel *chan, | |||||
const struct vmbus_chanpkt_hdr *pkt) | |||||
{ | |||||
struct hn_send_ctx *sndc; | |||||
sndc = (struct hn_send_ctx *)(uintptr_t)pkt->cph_xactid; | |||||
sndc->hn_cb(sndc, net_dev, chan, VMBUS_CHANPKT_CONST_DATA(pkt)); | |||||
/* | |||||
* NOTE: | |||||
* 'sndc' CAN NOT be accessed anymore, since it can be freed by | |||||
* its callback. | |||||
*/ | |||||
} | } | ||||
} | |||||
} | |||||
/* | /* | ||||
* Net VSC on send | * Net VSC on send | ||||
* Sends a packet on the specified Hyper-V device. | * Sends a packet on the specified Hyper-V device. | ||||
* Returns 0 on success, non-zero on failure. | * Returns 0 on success, non-zero on failure. | ||||
*/ | */ | ||||
int | int | ||||
hv_nv_on_send(struct vmbus_channel *chan, | hv_nv_on_send(struct vmbus_channel *chan, bool is_data_pkt, | ||||
netvsc_packet *pkt, struct vmbus_gpa *gpa, int gpa_cnt) | struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt) | ||||
{ | { | ||||
nvsp_msg send_msg; | nvsp_msg send_msg; | ||||
int ret; | int ret; | ||||
send_msg.hdr.msg_type = nvsp_msg_1_type_send_rndis_pkt; | send_msg.hdr.msg_type = nvsp_msg_1_type_send_rndis_pkt; | ||||
if (pkt->is_data_pkt) { | if (is_data_pkt) { | ||||
/* 0 is RMC_DATA */ | /* 0 is RMC_DATA */ | ||||
send_msg.msgs.vers_1_msgs.send_rndis_pkt.chan_type = 0; | send_msg.msgs.vers_1_msgs.send_rndis_pkt.chan_type = 0; | ||||
} else { | } else { | ||||
/* 1 is RMC_CONTROL */ | /* 1 is RMC_CONTROL */ | ||||
send_msg.msgs.vers_1_msgs.send_rndis_pkt.chan_type = 1; | send_msg.msgs.vers_1_msgs.send_rndis_pkt.chan_type = 1; | ||||
} | } | ||||
send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_idx = | send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_idx = | ||||
pkt->send_buf_section_idx; | sndc->hn_chim_idx; | ||||
send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_size = | send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_size = | ||||
pkt->send_buf_section_size; | sndc->hn_chim_sz; | ||||
if (gpa_cnt) { | if (gpa_cnt) { | ||||
ret = vmbus_chan_send_sglist(chan, gpa, gpa_cnt, | ret = vmbus_chan_send_sglist(chan, gpa, gpa_cnt, | ||||
&send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)pkt); | &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)sndc); | ||||
} else { | } else { | ||||
ret = vmbus_chan_send(chan, | ret = vmbus_chan_send(chan, | ||||
VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, | VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, | ||||
&send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)pkt); | &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)sndc); | ||||
} | } | ||||
return (ret); | return (ret); | ||||
} | } | ||||
/* | /* | ||||
* Net VSC on receive | * Net VSC on receive | ||||
* | * | ||||
▲ Show 20 Lines • Show All 204 Lines • Show Last 20 Lines |