hyperv/hn: Reorganize send done callback.
MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7450
This commit is contained in:
parent
6d4f67f9c6
commit
71e8fde12e
@ -68,6 +68,12 @@ static void hv_nv_on_receive_completion(struct vmbus_channel *chan,
|
||||
static void hv_nv_on_receive(netvsc_dev *net_dev,
|
||||
struct hn_rx_ring *rxr, struct vmbus_channel *chan,
|
||||
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);
|
||||
|
||||
/*
|
||||
*
|
||||
@ -141,6 +147,7 @@ hv_nv_get_next_send_section(netvsc_dev *net_dev)
|
||||
static int
|
||||
hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc)
|
||||
{
|
||||
struct hn_send_ctx sndc;
|
||||
netvsc_dev *net_dev;
|
||||
nvsp_msg *init_pkt;
|
||||
int ret = 0;
|
||||
@ -189,9 +196,10 @@ hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc)
|
||||
|
||||
/* Send the gpadl notification request */
|
||||
|
||||
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,
|
||||
init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt);
|
||||
init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc);
|
||||
if (ret != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
@ -240,6 +248,7 @@ hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc)
|
||||
static int
|
||||
hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc)
|
||||
{
|
||||
struct hn_send_ctx sndc;
|
||||
netvsc_dev *net_dev;
|
||||
nvsp_msg *init_pkt;
|
||||
int ret = 0;
|
||||
@ -287,9 +296,10 @@ hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc)
|
||||
|
||||
/* Send the gpadl notification request */
|
||||
|
||||
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,
|
||||
init_pkt, sizeof(nvsp_msg), (uint64_t)init_pkt);
|
||||
init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc);
|
||||
if (ret != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
@ -348,8 +358,7 @@ hv_nv_destroy_rx_buffer(netvsc_dev *net_dev)
|
||||
|
||||
ret = vmbus_chan_send(net_dev->sc->hn_prichan,
|
||||
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
|
||||
* rather than continue and a bugchk
|
||||
@ -414,9 +423,8 @@ hv_nv_destroy_send_buffer(netvsc_dev *net_dev)
|
||||
NETVSC_SEND_BUFFER_ID;
|
||||
|
||||
ret = vmbus_chan_send(net_dev->sc->hn_prichan,
|
||||
VMBUS_CHANPKT_TYPE_INBAND, 0,
|
||||
revoke_pkt, sizeof(nvsp_msg),
|
||||
(uint64_t)(uintptr_t)revoke_pkt);
|
||||
VMBUS_CHANPKT_TYPE_INBAND, 0, revoke_pkt, sizeof(nvsp_msg),
|
||||
(uint64_t)(uintptr_t)&hn_send_ctx_none);
|
||||
/*
|
||||
* If we failed here, we might as well return and have a leak
|
||||
* rather than continue and a bugchk
|
||||
@ -466,6 +474,7 @@ static int
|
||||
hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, netvsc_dev *net_dev,
|
||||
uint32_t nvsp_ver)
|
||||
{
|
||||
struct hn_send_ctx sndc;
|
||||
nvsp_msg *init_pkt;
|
||||
int ret;
|
||||
|
||||
@ -480,9 +489,10 @@ hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, netvsc_dev *net_dev,
|
||||
init_pkt->msgs.init_msgs.init.protocol_version_2 = nvsp_ver;
|
||||
|
||||
/* Send the init request */
|
||||
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,
|
||||
init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt);
|
||||
init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc);
|
||||
if (ret != 0)
|
||||
return (-1);
|
||||
|
||||
@ -524,7 +534,7 @@ hv_nv_send_ndis_config(struct hn_softc *sc, uint32_t mtu)
|
||||
|
||||
/* Send the configuration packet */
|
||||
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)
|
||||
return (-EINVAL);
|
||||
|
||||
@ -602,7 +612,7 @@ hv_nv_connect_to_vsp(struct hn_softc *sc)
|
||||
/* Send the init request */
|
||||
|
||||
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) {
|
||||
goto cleanup;
|
||||
}
|
||||
@ -731,6 +741,43 @@ hv_nv_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel)
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
hn_nvs_sent_wakeup(struct hn_send_ctx *sndc __unused,
|
||||
struct netvsc_dev_ *net_dev, struct vmbus_channel *chan __unused,
|
||||
const struct nvsp_msg_ *msg)
|
||||
{
|
||||
/* Copy the response back */
|
||||
memcpy(&net_dev->channel_init_packet, msg, sizeof(nvsp_msg));
|
||||
sema_post(&net_dev->channel_init_sema);
|
||||
}
|
||||
|
||||
static void
|
||||
hn_nvs_sent_none(struct hn_send_ctx *sndc __unused,
|
||||
struct netvsc_dev_ *net_dev __unused, struct vmbus_channel *chan __unused,
|
||||
const struct nvsp_msg_ *msg __unused)
|
||||
{
|
||||
/* EMPTY */
|
||||
}
|
||||
|
||||
void
|
||||
hn_chim_free(struct netvsc_dev_ *net_dev, uint32_t chim_idx)
|
||||
{
|
||||
u_long mask;
|
||||
uint32_t idx;
|
||||
|
||||
idx = chim_idx / BITS_PER_LONG;
|
||||
KASSERT(idx < net_dev->bitsmap_words,
|
||||
("invalid chimney index 0x%x", chim_idx));
|
||||
|
||||
mask = 1UL << (chim_idx % BITS_PER_LONG);
|
||||
KASSERT(net_dev->send_section_bitsmap[idx] & mask,
|
||||
("index bitmap 0x%lx, chimney index %u, "
|
||||
"bitmap idx %d, bitmask 0x%lx",
|
||||
net_dev->send_section_bitsmap[idx], chim_idx, idx, mask));
|
||||
|
||||
atomic_clear_long(&net_dev->send_section_bitsmap[idx], mask);
|
||||
}
|
||||
|
||||
/*
|
||||
* Net VSC on send completion
|
||||
*/
|
||||
@ -738,59 +785,15 @@ static void
|
||||
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;
|
||||
struct hn_send_ctx *sndc;
|
||||
|
||||
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 */
|
||||
memcpy(&net_dev->channel_init_packet, nvsp_msg_pkt,
|
||||
sizeof(nvsp_msg));
|
||||
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 */
|
||||
net_vsc_pkt =
|
||||
(netvsc_packet *)(unsigned long)pkt->cph_xactid;
|
||||
if (NULL != net_vsc_pkt) {
|
||||
if (net_vsc_pkt->send_buf_section_idx !=
|
||||
NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
|
||||
u_long mask;
|
||||
int idx;
|
||||
|
||||
idx = net_vsc_pkt->send_buf_section_idx /
|
||||
BITS_PER_LONG;
|
||||
KASSERT(idx < net_dev->bitsmap_words,
|
||||
("invalid section index %u",
|
||||
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,
|
||||
("index bitmap 0x%lx, section index %u, "
|
||||
"bitmap idx %d, bitmask 0x%lx",
|
||||
net_dev->send_section_bitsmap[idx],
|
||||
net_vsc_pkt->send_buf_section_idx,
|
||||
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_pkt->compl.send.send_completion_context);
|
||||
|
||||
}
|
||||
}
|
||||
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.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
@ -799,14 +802,14 @@ hv_nv_on_send_completion(netvsc_dev *net_dev, struct vmbus_channel *chan,
|
||||
* Returns 0 on success, non-zero on failure.
|
||||
*/
|
||||
int
|
||||
hv_nv_on_send(struct vmbus_channel *chan,
|
||||
netvsc_packet *pkt, struct vmbus_gpa *gpa, int gpa_cnt)
|
||||
hv_nv_on_send(struct vmbus_channel *chan, bool is_data_pkt,
|
||||
struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt)
|
||||
{
|
||||
nvsp_msg send_msg;
|
||||
int ret;
|
||||
|
||||
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 */
|
||||
send_msg.msgs.vers_1_msgs.send_rndis_pkt.chan_type = 0;
|
||||
} else {
|
||||
@ -815,17 +818,17 @@ hv_nv_on_send(struct vmbus_channel *chan,
|
||||
}
|
||||
|
||||
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 =
|
||||
pkt->send_buf_section_size;
|
||||
sndc->hn_chim_sz;
|
||||
|
||||
if (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 {
|
||||
ret = vmbus_chan_send(chan,
|
||||
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);
|
||||
|
@ -1112,29 +1112,8 @@ typedef void (*pfn_on_send_rx_completion)(struct vmbus_channel *, void *);
|
||||
#endif
|
||||
|
||||
typedef struct netvsc_packet_ {
|
||||
uint8_t is_data_pkt; /* One byte */
|
||||
uint16_t vlan_tci;
|
||||
uint32_t status;
|
||||
|
||||
/* Completion */
|
||||
union {
|
||||
struct {
|
||||
uint64_t rx_completion_tid;
|
||||
void *rx_completion_context;
|
||||
/* This is no longer used */
|
||||
pfn_on_send_rx_completion on_rx_completion;
|
||||
} rx;
|
||||
struct {
|
||||
uint64_t send_completion_tid;
|
||||
void *send_completion_context;
|
||||
/* Still used in netvsc and filter code */
|
||||
pfn_on_send_rx_completion on_send_completion;
|
||||
} send;
|
||||
} compl;
|
||||
uint32_t send_buf_section_idx;
|
||||
uint32_t send_buf_section_size;
|
||||
|
||||
void *rndis_mesg;
|
||||
uint16_t vlan_tci;
|
||||
uint32_t status;
|
||||
uint32_t tot_data_buf_len;
|
||||
void *data;
|
||||
} netvsc_packet;
|
||||
@ -1270,14 +1249,15 @@ typedef struct hn_softc {
|
||||
* Externs
|
||||
*/
|
||||
extern int hv_promisc_mode;
|
||||
struct hn_send_ctx;
|
||||
|
||||
void netvsc_linkstatus_callback(struct hn_softc *sc, uint32_t status);
|
||||
netvsc_dev *hv_nv_on_device_add(struct hn_softc *sc,
|
||||
void *additional_info, struct hn_rx_ring *rxr);
|
||||
int hv_nv_on_device_remove(struct hn_softc *sc,
|
||||
boolean_t destroy_channel);
|
||||
int hv_nv_on_send(struct vmbus_channel *chan, netvsc_packet *pkt,
|
||||
struct vmbus_gpa *gpa, int gpa_cnt);
|
||||
int hv_nv_on_send(struct vmbus_channel *chan, bool is_data_pkt,
|
||||
struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt);
|
||||
int hv_nv_get_next_send_section(netvsc_dev *net_dev);
|
||||
void hv_nv_subchan_attach(struct vmbus_channel *chan,
|
||||
struct hn_rx_ring *rxr);
|
||||
|
@ -166,7 +166,7 @@ struct hn_txdesc {
|
||||
struct hn_tx_ring *txr;
|
||||
int refs;
|
||||
uint32_t flags; /* HN_TXD_FLAG_ */
|
||||
netvsc_packet netvsc_pkt; /* XXX to be removed */
|
||||
struct hn_send_ctx send_ctx;
|
||||
|
||||
bus_dmamap_t data_dmap;
|
||||
|
||||
@ -781,14 +781,14 @@ hn_txeof(struct hn_tx_ring *txr)
|
||||
}
|
||||
|
||||
static void
|
||||
hn_tx_done(struct vmbus_channel *chan, void *xpkt)
|
||||
hn_tx_done(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev,
|
||||
struct vmbus_channel *chan, const struct nvsp_msg_ *msg __unused)
|
||||
{
|
||||
netvsc_packet *packet = xpkt;
|
||||
struct hn_txdesc *txd;
|
||||
struct hn_txdesc *txd = sndc->hn_cbarg;
|
||||
struct hn_tx_ring *txr;
|
||||
|
||||
txd = (struct hn_txdesc *)(uintptr_t)
|
||||
packet->compl.send.send_completion_tid;
|
||||
if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX)
|
||||
hn_chim_free(net_dev, sndc->hn_chim_idx);
|
||||
|
||||
txr = txd->txr;
|
||||
KASSERT(txr->hn_chan == chan,
|
||||
@ -835,16 +835,14 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0)
|
||||
bus_dma_segment_t segs[HN_TX_DATA_SEGCNT_MAX];
|
||||
int error, nsegs, i;
|
||||
struct mbuf *m_head = *m_head0;
|
||||
netvsc_packet *packet;
|
||||
rndis_msg *rndis_mesg;
|
||||
rndis_packet *rndis_pkt;
|
||||
rndis_per_packet_info *rppi;
|
||||
struct rndis_hash_value *hash_value;
|
||||
uint32_t rndis_msg_size;
|
||||
uint32_t rndis_msg_size, tot_data_buf_len, send_buf_section_idx;
|
||||
int send_buf_section_size;
|
||||
|
||||
packet = &txd->netvsc_pkt;
|
||||
packet->is_data_pkt = TRUE;
|
||||
packet->tot_data_buf_len = m_head->m_pkthdr.len;
|
||||
tot_data_buf_len = m_head->m_pkthdr.len;
|
||||
|
||||
/*
|
||||
* extension points to the area reserved for the
|
||||
@ -859,7 +857,7 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0)
|
||||
|
||||
rndis_pkt = &rndis_mesg->msg.packet;
|
||||
rndis_pkt->data_offset = sizeof(rndis_packet);
|
||||
rndis_pkt->data_length = packet->tot_data_buf_len;
|
||||
rndis_pkt->data_length = tot_data_buf_len;
|
||||
rndis_pkt->per_pkt_info_offset = sizeof(rndis_packet);
|
||||
|
||||
rndis_msg_size = RNDIS_MESSAGE_SIZE(rndis_packet);
|
||||
@ -967,15 +965,14 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0)
|
||||
}
|
||||
}
|
||||
|
||||
rndis_mesg->msg_len = packet->tot_data_buf_len + rndis_msg_size;
|
||||
packet->tot_data_buf_len = rndis_mesg->msg_len;
|
||||
rndis_mesg->msg_len = tot_data_buf_len + rndis_msg_size;
|
||||
tot_data_buf_len = rndis_mesg->msg_len;
|
||||
|
||||
/*
|
||||
* Chimney send, if the packet could fit into one chimney buffer.
|
||||
*/
|
||||
if (packet->tot_data_buf_len < txr->hn_tx_chimney_size) {
|
||||
if (tot_data_buf_len < txr->hn_tx_chimney_size) {
|
||||
netvsc_dev *net_dev = txr->hn_sc->net_dev;
|
||||
uint32_t send_buf_section_idx;
|
||||
|
||||
txr->hn_tx_chimney_tried++;
|
||||
send_buf_section_idx =
|
||||
@ -990,9 +987,7 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0)
|
||||
dest += rndis_msg_size;
|
||||
m_copydata(m_head, 0, m_head->m_pkthdr.len, dest);
|
||||
|
||||
packet->send_buf_section_idx = send_buf_section_idx;
|
||||
packet->send_buf_section_size =
|
||||
packet->tot_data_buf_len;
|
||||
send_buf_section_size = tot_data_buf_len;
|
||||
txr->hn_gpa_cnt = 0;
|
||||
txr->hn_tx_chimney++;
|
||||
goto done;
|
||||
@ -1039,16 +1034,14 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0)
|
||||
gpa->gpa_len = segs[i].ds_len;
|
||||
}
|
||||
|
||||
packet->send_buf_section_idx =
|
||||
NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
|
||||
packet->send_buf_section_size = 0;
|
||||
send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
|
||||
send_buf_section_size = 0;
|
||||
done:
|
||||
txd->m = m_head;
|
||||
|
||||
/* Set the completion routine */
|
||||
packet->compl.send.on_send_completion = hn_tx_done;
|
||||
packet->compl.send.send_completion_context = packet;
|
||||
packet->compl.send.send_completion_tid = (uint64_t)(uintptr_t)txd;
|
||||
hn_send_ctx_init(&txd->send_ctx, hn_tx_done, txd,
|
||||
send_buf_section_idx, send_buf_section_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1068,7 +1061,7 @@ hn_send_pkt(struct ifnet *ifp, struct hn_tx_ring *txr, struct hn_txdesc *txd)
|
||||
* Make sure that txd is not freed before ETHER_BPF_MTAP.
|
||||
*/
|
||||
hn_txdesc_hold(txd);
|
||||
error = hv_nv_on_send(txr->hn_chan, &txd->netvsc_pkt,
|
||||
error = hv_nv_on_send(txr->hn_chan, true, &txd->send_ctx,
|
||||
txr->hn_gpa, txr->hn_gpa_cnt);
|
||||
if (!error) {
|
||||
ETHER_BPF_MTAP(ifp, txd->m);
|
||||
|
@ -85,11 +85,17 @@ static int hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter);
|
||||
static int hv_rf_init_device(rndis_device *device);
|
||||
static int hv_rf_open_device(rndis_device *device);
|
||||
static int hv_rf_close_device(rndis_device *device);
|
||||
static void hv_rf_on_send_request_completion(struct vmbus_channel *, void *context);
|
||||
static void hv_rf_on_send_request_halt_completion(struct vmbus_channel *, void *context);
|
||||
int
|
||||
hv_rf_send_offload_request(struct hn_softc *sc,
|
||||
rndis_offload_params *offloads);
|
||||
|
||||
static void hn_rndis_sent_halt(struct hn_send_ctx *sndc,
|
||||
struct netvsc_dev_ *net_dev, struct vmbus_channel *chan,
|
||||
const struct nvsp_msg_ *msg);
|
||||
static void hn_rndis_sent_cb(struct hn_send_ctx *sndc,
|
||||
struct netvsc_dev_ *net_dev, struct vmbus_channel *chan,
|
||||
const struct nvsp_msg_ *msg);
|
||||
|
||||
/*
|
||||
* Set the Per-Packet-Info with the specified type
|
||||
*/
|
||||
@ -238,17 +244,14 @@ static int
|
||||
hv_rf_send_request(rndis_device *device, rndis_request *request,
|
||||
uint32_t message_type)
|
||||
{
|
||||
netvsc_packet *packet;
|
||||
netvsc_dev *net_dev = device->net_dev;
|
||||
int send_buf_section_idx;
|
||||
uint32_t send_buf_section_idx, tot_data_buf_len;
|
||||
struct vmbus_gpa gpa[2];
|
||||
int gpa_cnt;
|
||||
int gpa_cnt, send_buf_section_size;
|
||||
hn_sent_callback_t cb;
|
||||
|
||||
/* Set up the packet to send it */
|
||||
packet = &request->pkt;
|
||||
|
||||
packet->is_data_pkt = FALSE;
|
||||
packet->tot_data_buf_len = request->request_msg.msg_len;
|
||||
tot_data_buf_len = request->request_msg.msg_len;
|
||||
|
||||
gpa_cnt = 1;
|
||||
gpa[0].gpa_page = hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
|
||||
@ -265,16 +268,12 @@ hv_rf_send_request(rndis_device *device, rndis_request *request,
|
||||
gpa[1].gpa_len = request->request_msg.msg_len - gpa[0].gpa_len;
|
||||
}
|
||||
|
||||
packet->compl.send.send_completion_context = request; /* packet */
|
||||
if (message_type != REMOTE_NDIS_HALT_MSG) {
|
||||
packet->compl.send.on_send_completion =
|
||||
hv_rf_on_send_request_completion;
|
||||
} else {
|
||||
packet->compl.send.on_send_completion =
|
||||
hv_rf_on_send_request_halt_completion;
|
||||
}
|
||||
packet->compl.send.send_completion_tid = (unsigned long)device;
|
||||
if (packet->tot_data_buf_len < net_dev->send_section_size) {
|
||||
if (message_type != REMOTE_NDIS_HALT_MSG)
|
||||
cb = hn_rndis_sent_cb;
|
||||
else
|
||||
cb = hn_rndis_sent_halt;
|
||||
|
||||
if (tot_data_buf_len < net_dev->send_section_size) {
|
||||
send_buf_section_idx = hv_nv_get_next_send_section(net_dev);
|
||||
if (send_buf_section_idx !=
|
||||
NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
|
||||
@ -282,19 +281,20 @@ hv_rf_send_request(rndis_device *device, rndis_request *request,
|
||||
send_buf_section_idx * net_dev->send_section_size);
|
||||
|
||||
memcpy(dest, &request->request_msg, request->request_msg.msg_len);
|
||||
packet->send_buf_section_idx = send_buf_section_idx;
|
||||
packet->send_buf_section_size = packet->tot_data_buf_len;
|
||||
send_buf_section_size = tot_data_buf_len;
|
||||
gpa_cnt = 0;
|
||||
goto sendit;
|
||||
}
|
||||
/* Failed to allocate chimney send buffer; move on */
|
||||
}
|
||||
packet->send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
|
||||
packet->send_buf_section_size = 0;
|
||||
send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
|
||||
send_buf_section_size = 0;
|
||||
|
||||
sendit:
|
||||
return hv_nv_on_send(device->net_dev->sc->hn_prichan, packet,
|
||||
gpa, gpa_cnt);
|
||||
hn_send_ctx_init(&request->send_ctx, cb, request,
|
||||
send_buf_section_idx, send_buf_section_size);
|
||||
return hv_nv_on_send(device->net_dev->sc->hn_prichan, false,
|
||||
&request->send_ctx, gpa, gpa_cnt);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1056,6 +1056,7 @@ int
|
||||
hv_rf_on_device_add(struct hn_softc *sc, void *additl_info,
|
||||
int nchan, struct hn_rx_ring *rxr)
|
||||
{
|
||||
struct hn_send_ctx sndc;
|
||||
int ret;
|
||||
netvsc_dev *net_dev;
|
||||
rndis_device *rndis_dev;
|
||||
@ -1162,9 +1163,10 @@ hv_rf_on_device_add(struct hn_softc *sc, void *additl_info,
|
||||
init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels =
|
||||
net_dev->num_channel - 1;
|
||||
|
||||
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,
|
||||
init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt);
|
||||
init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc);
|
||||
if (ret != 0) {
|
||||
device_printf(dev, "Fail to allocate subchannel\n");
|
||||
goto out;
|
||||
@ -1235,23 +1237,22 @@ hv_rf_on_close(struct hn_softc *sc)
|
||||
return (hv_rf_close_device((rndis_device *)net_dev->extension));
|
||||
}
|
||||
|
||||
/*
|
||||
* RNDIS filter on send request completion callback
|
||||
*/
|
||||
static void
|
||||
hv_rf_on_send_request_completion(struct vmbus_channel *chan __unused,
|
||||
void *context __unused)
|
||||
static void
|
||||
hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev,
|
||||
struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg __unused)
|
||||
{
|
||||
if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX)
|
||||
hn_chim_free(net_dev, sndc->hn_chim_idx);
|
||||
}
|
||||
|
||||
/*
|
||||
* RNDIS filter on send request (halt only) completion callback
|
||||
*/
|
||||
static void
|
||||
hv_rf_on_send_request_halt_completion(struct vmbus_channel *chan __unused,
|
||||
void *context)
|
||||
static void
|
||||
hn_rndis_sent_halt(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev,
|
||||
struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg __unused)
|
||||
{
|
||||
rndis_request *request = context;
|
||||
rndis_request *request = sndc->hn_cbarg;
|
||||
|
||||
if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX)
|
||||
hn_chim_free(net_dev, sndc->hn_chim_idx);
|
||||
|
||||
/*
|
||||
* Notify hv_rf_halt_device() about halt completion.
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <dev/hyperv/netvsc/if_hnvar.h>
|
||||
|
||||
/*
|
||||
* Defines
|
||||
@ -75,7 +76,7 @@ typedef struct rndis_request_ {
|
||||
uint8_t buf_resp[PAGE_SIZE];
|
||||
|
||||
/* Simplify allocation by having a netvsc packet inline */
|
||||
netvsc_packet pkt;
|
||||
struct hn_send_ctx send_ctx;
|
||||
|
||||
/*
|
||||
* The max request size is sizeof(rndis_msg) + PAGE_SIZE.
|
||||
|
83
sys/dev/hyperv/netvsc/if_hnvar.h
Normal file
83
sys/dev/hyperv/netvsc/if_hnvar.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Microsoft Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice unmodified, this list of conditions, and the following
|
||||
* disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _IF_HNVAR_H_
|
||||
#define _IF_HNVAR_H_
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <dev/hyperv/netvsc/hv_net_vsc.h>
|
||||
|
||||
struct netvsc_dev_;
|
||||
struct nvsp_msg_;
|
||||
|
||||
struct vmbus_channel;
|
||||
struct hn_send_ctx;
|
||||
|
||||
typedef void (*hn_sent_callback_t)
|
||||
(struct hn_send_ctx *, struct netvsc_dev_ *,
|
||||
struct vmbus_channel *, const struct nvsp_msg_ *);
|
||||
|
||||
struct hn_send_ctx {
|
||||
hn_sent_callback_t hn_cb;
|
||||
void *hn_cbarg;
|
||||
uint32_t hn_chim_idx;
|
||||
int hn_chim_sz;
|
||||
};
|
||||
|
||||
#define HN_SEND_CTX_INITIALIZER(cb, cbarg) \
|
||||
{ \
|
||||
.hn_cb = cb, \
|
||||
.hn_cbarg = cbarg, \
|
||||
.hn_chim_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX, \
|
||||
.hn_chim_sz = 0 \
|
||||
}
|
||||
|
||||
static __inline void
|
||||
hn_send_ctx_init(struct hn_send_ctx *sndc, hn_sent_callback_t cb,
|
||||
void *cbarg, uint32_t chim_idx, int chim_sz)
|
||||
{
|
||||
sndc->hn_cb = cb;
|
||||
sndc->hn_cbarg = cbarg;
|
||||
sndc->hn_chim_idx = chim_idx;
|
||||
sndc->hn_chim_sz = chim_sz;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
hn_send_ctx_init_simple(struct hn_send_ctx *sndc, hn_sent_callback_t cb,
|
||||
void *cbarg)
|
||||
{
|
||||
hn_send_ctx_init(sndc, cb, cbarg,
|
||||
NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX, 0);
|
||||
}
|
||||
|
||||
void hn_nvs_sent_wakeup(struct hn_send_ctx *sndc,
|
||||
struct netvsc_dev_ *net_dev, struct vmbus_channel *chan,
|
||||
const struct nvsp_msg_ *msg);
|
||||
void hn_chim_free(struct netvsc_dev_ *net_dev, uint32_t chim_idx);
|
||||
|
||||
#endif /* !_IF_HNVAR_H_ */
|
Loading…
Reference in New Issue
Block a user