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:
sephe 2016-08-10 03:11:07 +00:00
parent 6d4f67f9c6
commit 71e8fde12e
6 changed files with 221 additions and 160 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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.

View 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_ */