hv_channel_lookup(struct hv_softc *, uint32_t);
int hv_channel_ring_create(struct hv_channel *, uint32_t);
void hv_channel_ring_destroy(struct hv_channel *);
+void hv_channel_pause(struct hv_channel *);
+uint hv_channel_unpause(struct hv_channel *);
extern void hv_attach_icdevs(struct hv_softc *);
int hv_attach_devices(struct hv_softc *);
hv_intr_signal(sc, &ch->ch_monprm);
}
+void
+hv_channel_intr(void *arg)
+{
+ struct hv_channel *ch = arg;
+ extern int ticks;
+ int start = ticks;
+
+ do {
+ ch->ch_handler(ch->ch_ctx);
+
+ if (hv_channel_unpause(ch) == 0)
+ return;
+
+ hv_channel_pause(ch);
+
+#if (defined(__amd64__) || defined(__i386__))
+ __asm volatile("pause": : : "memory");
+#endif
+ } while (ticks < start + 1);
+
+ hv_channel_schedule(ch);
+}
+
+int
+hv_channel_setdeferred(struct hv_channel *ch, const char *name)
+{
+ ch->ch_taskq = taskq_create(name, 1, IPL_NET, TASKQ_MPSAFE);
+ if (ch->ch_taskq == NULL)
+ return (-1);
+ task_set(&ch->ch_task, hv_channel_intr, ch);
+ return (0);
+}
+
+void
+hv_channel_schedule(struct hv_channel *ch)
+{
+ if (ch->ch_handler) {
+ if (!cold && (ch->ch_flags & CHF_BATCHED)) {
+ hv_channel_pause(ch);
+ task_add(ch->ch_taskq, &ch->ch_task);
+ } else
+ ch->ch_handler(ch->ch_ctx);
+ }
+}
+
static inline void
hv_ring_put(struct hv_ring_data *wrd, uint8_t *data, uint32_t datalen)
{
return (rv);
}
+static inline void
+hv_ring_mask(struct hv_ring_data *rd)
+{
+ virtio_membar_sync();
+ rd->rd_ring->br_imask = 1;
+ virtio_membar_sync();
+}
+
+static inline void
+hv_ring_unmask(struct hv_ring_data *rd)
+{
+ virtio_membar_sync();
+ rd->rd_ring->br_imask = 0;
+ virtio_membar_sync();
+}
+
+void
+hv_channel_pause(struct hv_channel *ch)
+{
+ hv_ring_mask(&ch->ch_rrd);
+}
+
+uint
+hv_channel_unpause(struct hv_channel *ch)
+{
+ uint32_t avail;
+
+ hv_ring_unmask(&ch->ch_rrd);
+ hv_ring_avail(&ch->ch_rrd, NULL, &avail);
+
+ return (avail);
+}
+
/* How many PFNs can be referenced by the header */
#define HV_NPFNHDR ((VMBUS_MSG_DSIZE_MAX - \
sizeof(struct vmbus_chanmsg_gpadl_conn)) / sizeof(uint64_t))
void (*ch_handler)(void *);
void *ch_ctx;
struct evcount ch_evcnt;
+ struct taskq *ch_taskq;
+ struct task ch_task;
uint32_t ch_flags;
#define CHF_BATCHED 0x0001
int hv_channel_open(struct hv_channel *, size_t, void *, size_t,
void (*)(void *), void *);
int hv_channel_close(struct hv_channel *);
+int hv_channel_setdeferred(struct hv_channel *, const char *);
+void hv_channel_schedule(struct hv_channel *);
void hv_evcount_attach(struct hv_channel *, const char *);
int hv_channel_send(struct hv_channel *, void *, uint32_t, uint64_t,
int, uint32_t);