Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/hyperv/vmbus/vmbus_chan.c
Context not available. | |||||
taskqueue_drain(chan->ch_tq, &chan->ch_task); | taskqueue_drain(chan->ch_tq, &chan->ch_task); | ||||
} | } | ||||
uint32_t | |||||
vmbus_chan_write_available(struct vmbus_channel *chan) | |||||
{ | |||||
return (vmbus_txbr_available(&chan->ch_txbr)); | |||||
} | |||||
void | |||||
vmbus_chan_write_signal(struct vmbus_channel *chan, | |||||
int32_t min_signal_size) | |||||
{ | |||||
if (min_signal_size >= 0 && | |||||
vmbus_chan_write_available(chan) > min_signal_size) { | |||||
return; | |||||
} | |||||
if (!vmbus_txbr_get_imask(&chan->ch_txbr)) { | |||||
/* txbr imask is not set, signal the reader */ | |||||
vmbus_chan_signal_tx(chan); | |||||
} | |||||
return; | |||||
} | |||||
int | int | ||||
vmbus_chan_iov_send(struct vmbus_channel *chan, | |||||
const struct iovec iov[], int iovlen, | |||||
vmbus_br_copy_callback_t cb, void *cbarg) | |||||
{ | |||||
int error; | |||||
boolean_t send_evt; | |||||
if (iovlen == 0) | |||||
return (0); | |||||
error = vmbus_txbr_write_call(&chan->ch_txbr, iov, iovlen, | |||||
cb, cbarg, &send_evt); | |||||
if (!error && send_evt) | |||||
vmbus_chan_signal_tx(chan); | |||||
return error; | |||||
} | |||||
int | |||||
vmbus_chan_send(struct vmbus_channel *chan, uint16_t type, uint16_t flags, | vmbus_chan_send(struct vmbus_channel *chan, uint16_t type, uint16_t flags, | ||||
void *data, int dlen, uint64_t xactid) | void *data, int dlen, uint64_t xactid) | ||||
{ | { | ||||
Context not available. | |||||
return (0); | return (0); | ||||
} | } | ||||
uint32_t | |||||
vmbus_chan_read_available(struct vmbus_channel *chan) | |||||
{ | |||||
return (vmbus_rxbr_available(&chan->ch_rxbr)); | |||||
} | |||||
/* | |||||
* This routine does: | |||||
* - Advance the channel read index for 'advance' bytes | |||||
* - Copy data_len bytes in to the buffer pointed by 'data' | |||||
* Return 0 if operation succeed. EAGAIN if operations if failed. | |||||
* If failed, the buffer pointed by 'data' is intact, and the | |||||
* channel read index is not advanced at all. | |||||
*/ | |||||
int | |||||
vmbus_chan_recv_peek(struct vmbus_channel *chan, | |||||
void *data, int data_len, uint32_t advance) | |||||
{ | |||||
if (data == NULL || data_len <= 0) | |||||
return (EINVAL); | |||||
return (vmbus_rxbr_idxadv_peek(&chan->ch_rxbr, | |||||
data, data_len, advance)); | |||||
} | |||||
/* | |||||
* This routine does: | |||||
* - Advance the channel read index for 'advance' bytes | |||||
*/ | |||||
int | |||||
vmbus_chan_recv_idxadv(struct vmbus_channel *chan, uint32_t advance) | |||||
{ | |||||
if (advance == 0) | |||||
return (EINVAL); | |||||
return (vmbus_rxbr_idxadv(&chan->ch_rxbr, advance)); | |||||
} | |||||
/* | |||||
* Caller should hold its own lock to serialize the ring buffer | |||||
* copy. | |||||
*/ | |||||
int | |||||
vmbus_chan_recv_peek_call(struct vmbus_channel *chan, int data_len, | |||||
uint32_t skip, vmbus_br_copy_callback_t cb, void *cbarg) | |||||
{ | |||||
if (!chan || data_len <= 0 || cb == NULL) | |||||
return (EINVAL); | |||||
return (vmbus_rxbr_peek_call(&chan->ch_rxbr, data_len, skip, | |||||
cb, cbarg)); | |||||
} | |||||
static void | static void | ||||
vmbus_chan_task(void *xchan, int pending __unused) | vmbus_chan_task(void *xchan, int pending __unused) | ||||
{ | { | ||||
Context not available. | |||||
1 << (offer->chm_montrig % VMBUS_MONTRIG_LEN); | 1 << (offer->chm_montrig % VMBUS_MONTRIG_LEN); | ||||
} | } | ||||
if (offer->chm_chflags & VMBUS_CHAN_TLNPI_PROVIDER_OFFER) { | |||||
/* This is HyperV socket channel */ | |||||
chan->ch_is_hvs = true; | |||||
/* The first byte != 0 means the host initiated connection. */ | |||||
chan->ch_hvs_conn_from_host = | |||||
offer->chm_udata.pipe.user_def[0]; | |||||
if (bootverbose) { | |||||
device_printf(sc->vmbus_dev, | |||||
"chan%u is hyperv socket channel " | |||||
"connected %s host\n", | |||||
chan->ch_id, | |||||
(chan->ch_hvs_conn_from_host != 0) ? | |||||
"from" : "to"); | |||||
} | |||||
} else { | |||||
chan->ch_is_hvs = false; | |||||
} | |||||
/* | /* | ||||
* Setup event flag. | * Setup event flag. | ||||
*/ | */ | ||||
Context not available. | |||||
return false; | return false; | ||||
} | } | ||||
const struct hyperv_guid * | bool | ||||
vmbus_chan_guid_inst(const struct vmbus_channel *chan) | vmbus_chan_is_hvs(const struct vmbus_channel *chan) | ||||
{ | { | ||||
return chan->ch_is_hvs; | |||||
} | |||||
bool | |||||
vmbus_chan_is_hvs_conn_from_host(const struct vmbus_channel *chan) | |||||
{ | |||||
KASSERT(vmbus_chan_is_hvs(chan) == true, | |||||
("Not a HyperV Socket channel %u", chan->ch_id)); | |||||
if (chan->ch_hvs_conn_from_host != 0) | |||||
return true; | |||||
else | |||||
return false; | |||||
} | |||||
struct hyperv_guid * | |||||
vmbus_chan_guid_type(struct vmbus_channel *chan) | |||||
{ | |||||
return &chan->ch_guid_type; | |||||
} | |||||
struct hyperv_guid * | |||||
vmbus_chan_guid_inst(struct vmbus_channel *chan) | |||||
{ | |||||
return &chan->ch_guid_inst; | return &chan->ch_guid_inst; | ||||
} | } | ||||
Context not available. |