Skip to content

Commit df92165

Browse files
longlimsftgregkh
authored andcommitted
uio_hv_generic: Set event for all channels on the device
commit d062463 upstream. Hyper-V may offer a non latency sensitive device with subchannels without monitor bit enabled. The decision is entirely on the Hyper-V host not configurable within guest. When a device has subchannels, also signal events for the subchannel if its monitor bit is disabled. This patch also removes the memory barrier when monitor bit is enabled as it is not necessary. The memory barrier is only needed between setting up interrupt mask and calling vmbus_set_event() when monitor bit is disabled. Signed-off-by: Long Li <[email protected]> Reviewed-by: Michael Kelley <[email protected]> Reviewed-by: Saurabh Sengar <[email protected]> Link: https://lore.kernel.org/r/[email protected] Fixes: 37bd91f ("uio_hv_generic: Let userspace take care of interrupt mask") Cc: <[email protected]> # 6.12.x Signed-off-by: Naman Jain <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 5a127a4 commit df92165

File tree

1 file changed

+26
-6
lines changed

1 file changed

+26
-6
lines changed

drivers/uio/uio_hv_generic.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,16 @@ struct hv_uio_private_data {
6565
char send_name[32];
6666
};
6767

68+
static void set_event(struct vmbus_channel *channel, s32 irq_state)
69+
{
70+
channel->inbound.ring_buffer->interrupt_mask = !irq_state;
71+
if (!channel->offermsg.monitor_allocated && irq_state) {
72+
/* MB is needed for host to see the interrupt mask first */
73+
virt_mb();
74+
vmbus_set_event(channel);
75+
}
76+
}
77+
6878
/*
6979
* This is the irqcontrol callback to be registered to uio_info.
7080
* It can be used to disable/enable interrupt from user space processes.
@@ -79,12 +89,15 @@ hv_uio_irqcontrol(struct uio_info *info, s32 irq_state)
7989
{
8090
struct hv_uio_private_data *pdata = info->priv;
8191
struct hv_device *dev = pdata->device;
92+
struct vmbus_channel *primary, *sc;
8293

83-
dev->channel->inbound.ring_buffer->interrupt_mask = !irq_state;
84-
virt_mb();
94+
primary = dev->channel;
95+
set_event(primary, irq_state);
8596

86-
if (!dev->channel->offermsg.monitor_allocated && irq_state)
87-
vmbus_setevent(dev->channel);
97+
mutex_lock(&vmbus_connection.channel_mutex);
98+
list_for_each_entry(sc, &primary->sc_list, sc_list)
99+
set_event(sc, irq_state);
100+
mutex_unlock(&vmbus_connection.channel_mutex);
88101

89102
return 0;
90103
}
@@ -95,11 +108,18 @@ hv_uio_irqcontrol(struct uio_info *info, s32 irq_state)
95108
static void hv_uio_channel_cb(void *context)
96109
{
97110
struct vmbus_channel *chan = context;
98-
struct hv_device *hv_dev = chan->device_obj;
99-
struct hv_uio_private_data *pdata = hv_get_drvdata(hv_dev);
111+
struct hv_device *hv_dev;
112+
struct hv_uio_private_data *pdata;
100113

101114
virt_mb();
102115

116+
/*
117+
* The callback may come from a subchannel, in which case look
118+
* for the hv device in the primary channel
119+
*/
120+
hv_dev = chan->primary_channel ?
121+
chan->primary_channel->device_obj : chan->device_obj;
122+
pdata = hv_get_drvdata(hv_dev);
103123
uio_event_notify(&pdata->info);
104124
}
105125

0 commit comments

Comments
 (0)