mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-06 05:06:29 +00:00
Three fixes:
1. Fix for a race condition in the hyper-v ringbuffer code by Kimberly Brown. 2. Fix to show monitor data only when monitor pages are actually allocated, also by Kimberly Brown. 3. Fix cpu reference counting in the vmbus code by Dexuan Cui. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE4n5dijQDou9mhzu83qZv95d3LNwFAly2gfUACgkQ3qZv95d3 LNyAlQ/7BY4Bt0NNvn/D49uV9XoT/lAI3846kQht/0RgMymS/GaU/2z8X+elLbb0 Q0f0PvAGMCtqnHjvQyhdpeujC6umz09Se7OlfwkN0v0Dz0j2zKjOGRX7/0qVZ3/N qLXthmqTaSl0l1I0aVfZLwzwgSnP9ehv1Li6XQ3Mgx1PXv7zWCYf/RyYOGakMKFI a1jCAffikiJEZVKXyF9FlC3C5Estam7624lbEl3JNSnawYkd0ujS/Ek+pOTf5ZAj penKNA4tFMFy5AAS4YruIPO118s6ebCn0mHYWAFPO+yMnvhR4N+3ThlBuBq/L8fE cJRGVBNPd4Tmx63wvOAAUggBWAzFyAmB2pm6J0HVmFkGSk5aueWVizkzd/MMtXOv JGe3IuDPB4XpdOrznWzdu/wfa/6iSPJ9SJPtCxCn89HbAJwyY3Ms8E9YsSGfZMUO +uttl6iANtKbrLujSESndBkOQxQzZY5Ggb0f//i8xdY3cfAr2XC+7Z+sxX05CQgw QKnnUnmKfunRJa6vibKC+nXXuR5P8AthNgwEN1bqiBIj1U9GE476jH8umelKulFS UP2QIJOWCECDVOSO76tXEZo09RPkQhzVargUvYZIkJ2LCqM3ElT2+vnnF/HXZCuU SqwlCiX9JixjM3kOCrm8b/oXnnOa9pyKtIubQg3d0goYgfNN9iU= =YEC/ -----END PGP SIGNATURE----- Merge tag 'hyperv-fixes-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux into char-misc-linus Sasha writes: Three fixes: 1. Fix for a race condition in the hyper-v ringbuffer code by Kimberly Brown. 2. Fix to show monitor data only when monitor pages are actually allocated, also by Kimberly Brown. 3. Fix cpu reference counting in the vmbus code by Dexuan Cui. * tag 'hyperv-fixes-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: Drivers: hv: vmbus: Remove the undesired put_cpu_ptr() in hv_synic_cleanup() Drivers: hv: vmbus: Fix race condition with new ring_buffer_info mutex Drivers: hv: vmbus: Set ring_info field to 0 and remove memset Drivers: hv: vmbus: Refactor chan->state if statement Drivers: hv: vmbus: Expose monitor data only when monitor pages are used
This commit is contained in:
commit
5450a5f4bf
@ -81,7 +81,9 @@ What: /sys/bus/vmbus/devices/<UUID>/channels/<N>/latency
|
||||
Date: September. 2017
|
||||
KernelVersion: 4.14
|
||||
Contact: Stephen Hemminger <sthemmin@microsoft.com>
|
||||
Description: Channel signaling latency
|
||||
Description: Channel signaling latency. This file is available only for
|
||||
performance critical channels (storage, network, etc.) that use
|
||||
the monitor page mechanism.
|
||||
Users: Debugging tools
|
||||
|
||||
What: /sys/bus/vmbus/devices/<UUID>/channels/<N>/out_mask
|
||||
@ -95,7 +97,9 @@ What: /sys/bus/vmbus/devices/<UUID>/channels/<N>/pending
|
||||
Date: September. 2017
|
||||
KernelVersion: 4.14
|
||||
Contact: Stephen Hemminger <sthemmin@microsoft.com>
|
||||
Description: Channel interrupt pending state
|
||||
Description: Channel interrupt pending state. This file is available only for
|
||||
performance critical channels (storage, network, etc.) that use
|
||||
the monitor page mechanism.
|
||||
Users: Debugging tools
|
||||
|
||||
What: /sys/bus/vmbus/devices/<UUID>/channels/<N>/read_avail
|
||||
@ -137,7 +141,9 @@ What: /sys/bus/vmbus/devices/<UUID>/channels/<N>/monitor_id
|
||||
Date: January. 2018
|
||||
KernelVersion: 4.16
|
||||
Contact: Stephen Hemminger <sthemmin@microsoft.com>
|
||||
Description: Monitor bit associated with channel
|
||||
Description: Monitor bit associated with channel. This file is available only
|
||||
for performance critical channels (storage, network, etc.) that
|
||||
use the monitor page mechanism.
|
||||
Users: Debugging tools and userspace drivers
|
||||
|
||||
What: /sys/bus/vmbus/devices/<UUID>/channels/<N>/ring
|
||||
|
@ -336,6 +336,8 @@ static struct vmbus_channel *alloc_channel(void)
|
||||
tasklet_init(&channel->callback_event,
|
||||
vmbus_on_event, (unsigned long)channel);
|
||||
|
||||
hv_ringbuffer_pre_init(channel);
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
@ -345,6 +347,7 @@ static struct vmbus_channel *alloc_channel(void)
|
||||
static void free_channel(struct vmbus_channel *channel)
|
||||
{
|
||||
tasklet_kill(&channel->callback_event);
|
||||
vmbus_remove_channel_attr_group(channel);
|
||||
|
||||
kobject_put(&channel->kobj);
|
||||
}
|
||||
|
@ -408,7 +408,6 @@ int hv_synic_cleanup(unsigned int cpu)
|
||||
|
||||
clockevents_unbind_device(hv_cpu->clk_evt, cpu);
|
||||
hv_ce_shutdown(hv_cpu->clk_evt);
|
||||
put_cpu_ptr(hv_cpu);
|
||||
}
|
||||
|
||||
hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
|
||||
|
@ -193,6 +193,7 @@ extern void hv_synic_clockevents_cleanup(void);
|
||||
|
||||
/* Interface */
|
||||
|
||||
void hv_ringbuffer_pre_init(struct vmbus_channel *channel);
|
||||
|
||||
int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
|
||||
struct page *pages, u32 pagecnt);
|
||||
@ -321,6 +322,8 @@ void vmbus_device_unregister(struct hv_device *device_obj);
|
||||
int vmbus_add_channel_kobj(struct hv_device *device_obj,
|
||||
struct vmbus_channel *channel);
|
||||
|
||||
void vmbus_remove_channel_attr_group(struct vmbus_channel *channel);
|
||||
|
||||
struct vmbus_channel *relid2channel(u32 relid);
|
||||
|
||||
void vmbus_free_channels(void);
|
||||
|
@ -166,14 +166,18 @@ hv_get_ringbuffer_availbytes(const struct hv_ring_buffer_info *rbi,
|
||||
}
|
||||
|
||||
/* Get various debug metrics for the specified ring buffer. */
|
||||
int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
|
||||
int hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
|
||||
struct hv_ring_buffer_debug_info *debug_info)
|
||||
{
|
||||
u32 bytes_avail_towrite;
|
||||
u32 bytes_avail_toread;
|
||||
|
||||
if (!ring_info->ring_buffer)
|
||||
mutex_lock(&ring_info->ring_buffer_mutex);
|
||||
|
||||
if (!ring_info->ring_buffer) {
|
||||
mutex_unlock(&ring_info->ring_buffer_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hv_get_ringbuffer_availbytes(ring_info,
|
||||
&bytes_avail_toread,
|
||||
@ -184,10 +188,19 @@ int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
|
||||
debug_info->current_write_index = ring_info->ring_buffer->write_index;
|
||||
debug_info->current_interrupt_mask
|
||||
= ring_info->ring_buffer->interrupt_mask;
|
||||
mutex_unlock(&ring_info->ring_buffer_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hv_ringbuffer_get_debuginfo);
|
||||
|
||||
/* Initialize a channel's ring buffer info mutex locks */
|
||||
void hv_ringbuffer_pre_init(struct vmbus_channel *channel)
|
||||
{
|
||||
mutex_init(&channel->inbound.ring_buffer_mutex);
|
||||
mutex_init(&channel->outbound.ring_buffer_mutex);
|
||||
}
|
||||
|
||||
/* Initialize the ring buffer. */
|
||||
int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
|
||||
struct page *pages, u32 page_cnt)
|
||||
@ -197,8 +210,6 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
|
||||
|
||||
BUILD_BUG_ON((sizeof(struct hv_ring_buffer) != PAGE_SIZE));
|
||||
|
||||
memset(ring_info, 0, sizeof(struct hv_ring_buffer_info));
|
||||
|
||||
/*
|
||||
* First page holds struct hv_ring_buffer, do wraparound mapping for
|
||||
* the rest.
|
||||
@ -232,6 +243,7 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
|
||||
reciprocal_value(ring_info->ring_size / 10);
|
||||
ring_info->ring_datasize = ring_info->ring_size -
|
||||
sizeof(struct hv_ring_buffer);
|
||||
ring_info->priv_read_index = 0;
|
||||
|
||||
spin_lock_init(&ring_info->ring_lock);
|
||||
|
||||
@ -241,8 +253,10 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
|
||||
/* Cleanup the ring buffer. */
|
||||
void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info)
|
||||
{
|
||||
mutex_lock(&ring_info->ring_buffer_mutex);
|
||||
vunmap(ring_info->ring_buffer);
|
||||
ring_info->ring_buffer = NULL;
|
||||
mutex_unlock(&ring_info->ring_buffer_mutex);
|
||||
}
|
||||
|
||||
/* Write to the ring buffer. */
|
||||
|
@ -630,7 +630,36 @@ static struct attribute *vmbus_dev_attrs[] = {
|
||||
&dev_attr_driver_override.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(vmbus_dev);
|
||||
|
||||
/*
|
||||
* Device-level attribute_group callback function. Returns the permission for
|
||||
* each attribute, and returns 0 if an attribute is not visible.
|
||||
*/
|
||||
static umode_t vmbus_dev_attr_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int idx)
|
||||
{
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
const struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||
|
||||
/* Hide the monitor attributes if the monitor mechanism is not used. */
|
||||
if (!hv_dev->channel->offermsg.monitor_allocated &&
|
||||
(attr == &dev_attr_monitor_id.attr ||
|
||||
attr == &dev_attr_server_monitor_pending.attr ||
|
||||
attr == &dev_attr_client_monitor_pending.attr ||
|
||||
attr == &dev_attr_server_monitor_latency.attr ||
|
||||
attr == &dev_attr_client_monitor_latency.attr ||
|
||||
attr == &dev_attr_server_monitor_conn_id.attr ||
|
||||
attr == &dev_attr_client_monitor_conn_id.attr))
|
||||
return 0;
|
||||
|
||||
return attr->mode;
|
||||
}
|
||||
|
||||
static const struct attribute_group vmbus_dev_group = {
|
||||
.attrs = vmbus_dev_attrs,
|
||||
.is_visible = vmbus_dev_attr_is_visible
|
||||
};
|
||||
__ATTRIBUTE_GROUPS(vmbus_dev);
|
||||
|
||||
/*
|
||||
* vmbus_uevent - add uevent for our device
|
||||
@ -1381,7 +1410,7 @@ static void vmbus_chan_release(struct kobject *kobj)
|
||||
|
||||
struct vmbus_chan_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(const struct vmbus_channel *chan, char *buf);
|
||||
ssize_t (*show)(struct vmbus_channel *chan, char *buf);
|
||||
ssize_t (*store)(struct vmbus_channel *chan,
|
||||
const char *buf, size_t count);
|
||||
};
|
||||
@ -1400,15 +1429,12 @@ static ssize_t vmbus_chan_attr_show(struct kobject *kobj,
|
||||
{
|
||||
const struct vmbus_chan_attribute *attribute
|
||||
= container_of(attr, struct vmbus_chan_attribute, attr);
|
||||
const struct vmbus_channel *chan
|
||||
struct vmbus_channel *chan
|
||||
= container_of(kobj, struct vmbus_channel, kobj);
|
||||
|
||||
if (!attribute->show)
|
||||
return -EIO;
|
||||
|
||||
if (chan->state != CHANNEL_OPENED_STATE)
|
||||
return -EINVAL;
|
||||
|
||||
return attribute->show(chan, buf);
|
||||
}
|
||||
|
||||
@ -1416,45 +1442,81 @@ static const struct sysfs_ops vmbus_chan_sysfs_ops = {
|
||||
.show = vmbus_chan_attr_show,
|
||||
};
|
||||
|
||||
static ssize_t out_mask_show(const struct vmbus_channel *channel, char *buf)
|
||||
static ssize_t out_mask_show(struct vmbus_channel *channel, char *buf)
|
||||
{
|
||||
const struct hv_ring_buffer_info *rbi = &channel->outbound;
|
||||
struct hv_ring_buffer_info *rbi = &channel->outbound;
|
||||
ssize_t ret;
|
||||
|
||||
return sprintf(buf, "%u\n", rbi->ring_buffer->interrupt_mask);
|
||||
mutex_lock(&rbi->ring_buffer_mutex);
|
||||
if (!rbi->ring_buffer) {
|
||||
mutex_unlock(&rbi->ring_buffer_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = sprintf(buf, "%u\n", rbi->ring_buffer->interrupt_mask);
|
||||
mutex_unlock(&rbi->ring_buffer_mutex);
|
||||
return ret;
|
||||
}
|
||||
static VMBUS_CHAN_ATTR_RO(out_mask);
|
||||
|
||||
static ssize_t in_mask_show(const struct vmbus_channel *channel, char *buf)
|
||||
static ssize_t in_mask_show(struct vmbus_channel *channel, char *buf)
|
||||
{
|
||||
const struct hv_ring_buffer_info *rbi = &channel->inbound;
|
||||
struct hv_ring_buffer_info *rbi = &channel->inbound;
|
||||
ssize_t ret;
|
||||
|
||||
return sprintf(buf, "%u\n", rbi->ring_buffer->interrupt_mask);
|
||||
mutex_lock(&rbi->ring_buffer_mutex);
|
||||
if (!rbi->ring_buffer) {
|
||||
mutex_unlock(&rbi->ring_buffer_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = sprintf(buf, "%u\n", rbi->ring_buffer->interrupt_mask);
|
||||
mutex_unlock(&rbi->ring_buffer_mutex);
|
||||
return ret;
|
||||
}
|
||||
static VMBUS_CHAN_ATTR_RO(in_mask);
|
||||
|
||||
static ssize_t read_avail_show(const struct vmbus_channel *channel, char *buf)
|
||||
static ssize_t read_avail_show(struct vmbus_channel *channel, char *buf)
|
||||
{
|
||||
const struct hv_ring_buffer_info *rbi = &channel->inbound;
|
||||
struct hv_ring_buffer_info *rbi = &channel->inbound;
|
||||
ssize_t ret;
|
||||
|
||||
return sprintf(buf, "%u\n", hv_get_bytes_to_read(rbi));
|
||||
mutex_lock(&rbi->ring_buffer_mutex);
|
||||
if (!rbi->ring_buffer) {
|
||||
mutex_unlock(&rbi->ring_buffer_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = sprintf(buf, "%u\n", hv_get_bytes_to_read(rbi));
|
||||
mutex_unlock(&rbi->ring_buffer_mutex);
|
||||
return ret;
|
||||
}
|
||||
static VMBUS_CHAN_ATTR_RO(read_avail);
|
||||
|
||||
static ssize_t write_avail_show(const struct vmbus_channel *channel, char *buf)
|
||||
static ssize_t write_avail_show(struct vmbus_channel *channel, char *buf)
|
||||
{
|
||||
const struct hv_ring_buffer_info *rbi = &channel->outbound;
|
||||
struct hv_ring_buffer_info *rbi = &channel->outbound;
|
||||
ssize_t ret;
|
||||
|
||||
return sprintf(buf, "%u\n", hv_get_bytes_to_write(rbi));
|
||||
mutex_lock(&rbi->ring_buffer_mutex);
|
||||
if (!rbi->ring_buffer) {
|
||||
mutex_unlock(&rbi->ring_buffer_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = sprintf(buf, "%u\n", hv_get_bytes_to_write(rbi));
|
||||
mutex_unlock(&rbi->ring_buffer_mutex);
|
||||
return ret;
|
||||
}
|
||||
static VMBUS_CHAN_ATTR_RO(write_avail);
|
||||
|
||||
static ssize_t show_target_cpu(const struct vmbus_channel *channel, char *buf)
|
||||
static ssize_t show_target_cpu(struct vmbus_channel *channel, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%u\n", channel->target_cpu);
|
||||
}
|
||||
static VMBUS_CHAN_ATTR(cpu, S_IRUGO, show_target_cpu, NULL);
|
||||
|
||||
static ssize_t channel_pending_show(const struct vmbus_channel *channel,
|
||||
static ssize_t channel_pending_show(struct vmbus_channel *channel,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n",
|
||||
@ -1463,7 +1525,7 @@ static ssize_t channel_pending_show(const struct vmbus_channel *channel,
|
||||
}
|
||||
static VMBUS_CHAN_ATTR(pending, S_IRUGO, channel_pending_show, NULL);
|
||||
|
||||
static ssize_t channel_latency_show(const struct vmbus_channel *channel,
|
||||
static ssize_t channel_latency_show(struct vmbus_channel *channel,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n",
|
||||
@ -1472,19 +1534,19 @@ static ssize_t channel_latency_show(const struct vmbus_channel *channel,
|
||||
}
|
||||
static VMBUS_CHAN_ATTR(latency, S_IRUGO, channel_latency_show, NULL);
|
||||
|
||||
static ssize_t channel_interrupts_show(const struct vmbus_channel *channel, char *buf)
|
||||
static ssize_t channel_interrupts_show(struct vmbus_channel *channel, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%llu\n", channel->interrupts);
|
||||
}
|
||||
static VMBUS_CHAN_ATTR(interrupts, S_IRUGO, channel_interrupts_show, NULL);
|
||||
|
||||
static ssize_t channel_events_show(const struct vmbus_channel *channel, char *buf)
|
||||
static ssize_t channel_events_show(struct vmbus_channel *channel, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%llu\n", channel->sig_events);
|
||||
}
|
||||
static VMBUS_CHAN_ATTR(events, S_IRUGO, channel_events_show, NULL);
|
||||
|
||||
static ssize_t channel_intr_in_full_show(const struct vmbus_channel *channel,
|
||||
static ssize_t channel_intr_in_full_show(struct vmbus_channel *channel,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%llu\n",
|
||||
@ -1492,7 +1554,7 @@ static ssize_t channel_intr_in_full_show(const struct vmbus_channel *channel,
|
||||
}
|
||||
static VMBUS_CHAN_ATTR(intr_in_full, 0444, channel_intr_in_full_show, NULL);
|
||||
|
||||
static ssize_t channel_intr_out_empty_show(const struct vmbus_channel *channel,
|
||||
static ssize_t channel_intr_out_empty_show(struct vmbus_channel *channel,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%llu\n",
|
||||
@ -1500,7 +1562,7 @@ static ssize_t channel_intr_out_empty_show(const struct vmbus_channel *channel,
|
||||
}
|
||||
static VMBUS_CHAN_ATTR(intr_out_empty, 0444, channel_intr_out_empty_show, NULL);
|
||||
|
||||
static ssize_t channel_out_full_first_show(const struct vmbus_channel *channel,
|
||||
static ssize_t channel_out_full_first_show(struct vmbus_channel *channel,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%llu\n",
|
||||
@ -1508,7 +1570,7 @@ static ssize_t channel_out_full_first_show(const struct vmbus_channel *channel,
|
||||
}
|
||||
static VMBUS_CHAN_ATTR(out_full_first, 0444, channel_out_full_first_show, NULL);
|
||||
|
||||
static ssize_t channel_out_full_total_show(const struct vmbus_channel *channel,
|
||||
static ssize_t channel_out_full_total_show(struct vmbus_channel *channel,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%llu\n",
|
||||
@ -1516,14 +1578,14 @@ static ssize_t channel_out_full_total_show(const struct vmbus_channel *channel,
|
||||
}
|
||||
static VMBUS_CHAN_ATTR(out_full_total, 0444, channel_out_full_total_show, NULL);
|
||||
|
||||
static ssize_t subchannel_monitor_id_show(const struct vmbus_channel *channel,
|
||||
static ssize_t subchannel_monitor_id_show(struct vmbus_channel *channel,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%u\n", channel->offermsg.monitorid);
|
||||
}
|
||||
static VMBUS_CHAN_ATTR(monitor_id, S_IRUGO, subchannel_monitor_id_show, NULL);
|
||||
|
||||
static ssize_t subchannel_id_show(const struct vmbus_channel *channel,
|
||||
static ssize_t subchannel_id_show(struct vmbus_channel *channel,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%u\n",
|
||||
@ -1550,10 +1612,34 @@ static struct attribute *vmbus_chan_attrs[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* Channel-level attribute_group callback function. Returns the permission for
|
||||
* each attribute, and returns 0 if an attribute is not visible.
|
||||
*/
|
||||
static umode_t vmbus_chan_attr_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int idx)
|
||||
{
|
||||
const struct vmbus_channel *channel =
|
||||
container_of(kobj, struct vmbus_channel, kobj);
|
||||
|
||||
/* Hide the monitor attributes if the monitor mechanism is not used. */
|
||||
if (!channel->offermsg.monitor_allocated &&
|
||||
(attr == &chan_attr_pending.attr ||
|
||||
attr == &chan_attr_latency.attr ||
|
||||
attr == &chan_attr_monitor_id.attr))
|
||||
return 0;
|
||||
|
||||
return attr->mode;
|
||||
}
|
||||
|
||||
static struct attribute_group vmbus_chan_group = {
|
||||
.attrs = vmbus_chan_attrs,
|
||||
.is_visible = vmbus_chan_attr_is_visible
|
||||
};
|
||||
|
||||
static struct kobj_type vmbus_chan_ktype = {
|
||||
.sysfs_ops = &vmbus_chan_sysfs_ops,
|
||||
.release = vmbus_chan_release,
|
||||
.default_attrs = vmbus_chan_attrs,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1561,6 +1647,7 @@ static struct kobj_type vmbus_chan_ktype = {
|
||||
*/
|
||||
int vmbus_add_channel_kobj(struct hv_device *dev, struct vmbus_channel *channel)
|
||||
{
|
||||
const struct device *device = &dev->device;
|
||||
struct kobject *kobj = &channel->kobj;
|
||||
u32 relid = channel->offermsg.child_relid;
|
||||
int ret;
|
||||
@ -1571,11 +1658,30 @@ int vmbus_add_channel_kobj(struct hv_device *dev, struct vmbus_channel *channel)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = sysfs_create_group(kobj, &vmbus_chan_group);
|
||||
|
||||
if (ret) {
|
||||
/*
|
||||
* The calling functions' error handling paths will cleanup the
|
||||
* empty channel directory.
|
||||
*/
|
||||
dev_err(device, "Unable to set up channel sysfs files\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
kobject_uevent(kobj, KOBJ_ADD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* vmbus_remove_channel_attr_group - remove the channel's attribute group
|
||||
*/
|
||||
void vmbus_remove_channel_attr_group(struct vmbus_channel *channel)
|
||||
{
|
||||
sysfs_remove_group(&channel->kobj, &vmbus_chan_group);
|
||||
}
|
||||
|
||||
/*
|
||||
* vmbus_device_create - Creates and registers a new child device
|
||||
* on the vmbus.
|
||||
|
@ -141,6 +141,11 @@ struct hv_ring_buffer_info {
|
||||
|
||||
u32 ring_datasize; /* < ring_size */
|
||||
u32 priv_read_index;
|
||||
/*
|
||||
* The ring buffer mutex lock. This lock prevents the ring buffer from
|
||||
* being freed while the ring buffer is being accessed.
|
||||
*/
|
||||
struct mutex ring_buffer_mutex;
|
||||
};
|
||||
|
||||
|
||||
@ -1206,7 +1211,7 @@ struct hv_ring_buffer_debug_info {
|
||||
};
|
||||
|
||||
|
||||
int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
|
||||
int hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
|
||||
struct hv_ring_buffer_debug_info *debug_info);
|
||||
|
||||
/* Vmbus interface */
|
||||
|
Loading…
Reference in New Issue
Block a user