From eb8470db8bc018fc28901e4e3b0f48e33f1ea7df Mon Sep 17 00:00:00 2001 From: Jan Kandziora Date: Wed, 20 Sep 2017 23:52:45 +0200 Subject: wire: export w1_touch_bit The w1_ds28e17 driver from the next part of this patch needs to emit single-bit read timeslots to the DS28E17. The w1 subsystem already has this function but it is not exported outside drivers/w1/w1_io.c This subpatch exports the w1_touch_bit symbol with EXPORT_SYMBOL_GPL, same as the other exported symbols in drivers/w1/w1_io.c May be also useful later for writing drivers for other Onewire chips which do single-bit communication. Signed-off-by: Jan Kandziora Acked-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- include/linux/w1.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/w1.h b/include/linux/w1.h index 5b2972946dda..694101f744c7 100644 --- a/include/linux/w1.h +++ b/include/linux/w1.h @@ -293,6 +293,7 @@ void w1_unregister_family(struct w1_family *family); w1_unregister_family) u8 w1_triplet(struct w1_master *dev, int bdir); +u8 w1_touch_bit(struct w1_master *dev, int bit); void w1_write_8(struct w1_master *, u8); u8 w1_read_8(struct w1_master *); int w1_reset_bus(struct w1_master *); -- cgit v1.2.3-59-g8ed1b From c2e5df616e1ae6c2a074cb241ebb65a318ebaf7c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 21 Sep 2017 20:58:49 -0700 Subject: vmbus: add per-channel sysfs info This extends existing vmbus related sysfs structure to provide per-channel state information. This is useful when diagnosing issues with multiple queues in networking and storage. The existing sysfs only displayed information about the primary channel. The one place it reported multiple channels was the channel_vp_mapping file which violated the sysfs convention of one value per file. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/stable/sysfs-bus-vmbus | 56 ++++++++++ drivers/hv/channel_mgmt.c | 10 +- drivers/hv/hyperv_vmbus.h | 2 + drivers/hv/vmbus_drv.c | 185 +++++++++++++++++++++++++++++-- include/linux/hyperv.h | 6 + 5 files changed, 246 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/Documentation/ABI/stable/sysfs-bus-vmbus b/Documentation/ABI/stable/sysfs-bus-vmbus index 5d0125f7bcaf..0ebd8a1537a0 100644 --- a/Documentation/ABI/stable/sysfs-bus-vmbus +++ b/Documentation/ABI/stable/sysfs-bus-vmbus @@ -41,3 +41,59 @@ KernelVersion: 4.5 Contact: K. Y. Srinivasan Description: The 16 bit vendor ID of the device Users: tools/hv/lsvmbus and user level RDMA libraries + +What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/cpu +Date: September. 2017 +KernelVersion: 4.14 +Contact: Stephen Hemminger +Description: VCPU (sub)channel is affinitized to +Users: tools/hv/lsvmbus and other debuggig tools + +What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/cpu +Date: September. 2017 +KernelVersion: 4.14 +Contact: Stephen Hemminger +Description: VCPU (sub)channel is affinitized to +Users: tools/hv/lsvmbus and other debuggig tools + +What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/in_mask +Date: September. 2017 +KernelVersion: 4.14 +Contact: Stephen Hemminger +Description: Inbound channel signaling state +Users: Debuggig tools + +What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/latency +Date: September. 2017 +KernelVersion: 4.14 +Contact: Stephen Hemminger +Description: Channel signaling latency +Users: Debuggig tools + +What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/out_mask +Date: September. 2017 +KernelVersion: 4.14 +Contact: Stephen Hemminger +Description: Outbound channel signaling state +Users: Debuggig tools + +What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/pending +Date: September. 2017 +KernelVersion: 4.14 +Contact: Stephen Hemminger +Description: Channel interrupt pending state +Users: Debuggig tools + +What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/read_avail +Date: September. 2017 +KernelVersion: 4.14 +Contact: Stephen Hemminger +Description: Bytes availabble to read +Users: Debuggig tools + +What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/write_avail +Date: September. 2017 +KernelVersion: 4.14 +Contact: Stephen Hemminger +Description: Bytes availabble to write +Users: Debuggig tools diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 060df71c2e8b..dd2dffe816be 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -350,7 +350,7 @@ static void free_channel(struct vmbus_channel *channel) { tasklet_kill(&channel->callback_event); - kfree_rcu(channel, rcu); + kobject_put(&channel->kobj); } static void percpu_channel_enq(void *arg) @@ -513,6 +513,14 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) newchannel->state = CHANNEL_OPEN_STATE; if (!fnew) { + struct hv_device *dev + = newchannel->primary_channel->device_obj; + + if (vmbus_add_channel_kobj(dev, newchannel)) { + atomic_dec(&vmbus_connection.offer_in_progress); + goto err_free_chan; + } + if (channel->sc_creation_callback != NULL) channel->sc_creation_callback(newchannel); return; diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 49569f8fe038..de6f01df9592 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -373,6 +373,8 @@ struct hv_device *vmbus_device_create(const uuid_le *type, int vmbus_device_register(struct hv_device *child_device_obj); void vmbus_device_unregister(struct hv_device *device_obj); +int vmbus_add_channel_kobj(struct hv_device *device_obj, + struct vmbus_channel *channel); struct vmbus_channel *relid2channel(u32 relid); diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index a9d49f6f6501..a209527b09f5 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -107,28 +107,30 @@ static void print_alias_name(struct hv_device *hv_dev, char *alias_name) sprintf(&alias_name[i], "%02x", hv_dev->dev_type.b[i/2]); } -static u8 channel_monitor_group(struct vmbus_channel *channel) +static u8 channel_monitor_group(const struct vmbus_channel *channel) { return (u8)channel->offermsg.monitorid / 32; } -static u8 channel_monitor_offset(struct vmbus_channel *channel) +static u8 channel_monitor_offset(const struct vmbus_channel *channel) { return (u8)channel->offermsg.monitorid % 32; } -static u32 channel_pending(struct vmbus_channel *channel, - struct hv_monitor_page *monitor_page) +static u32 channel_pending(const struct vmbus_channel *channel, + const struct hv_monitor_page *monitor_page) { u8 monitor_group = channel_monitor_group(channel); + return monitor_page->trigger_group[monitor_group].pending; } -static u32 channel_latency(struct vmbus_channel *channel, - struct hv_monitor_page *monitor_page) +static u32 channel_latency(const struct vmbus_channel *channel, + const struct hv_monitor_page *monitor_page) { u8 monitor_group = channel_monitor_group(channel); u8 monitor_offset = channel_monitor_offset(channel); + return monitor_page->latency[monitor_group][monitor_offset]; } @@ -1134,6 +1136,145 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver) } EXPORT_SYMBOL_GPL(vmbus_driver_unregister); + +/* + * Called when last reference to channel is gone. + */ +static void vmbus_chan_release(struct kobject *kobj) +{ + struct vmbus_channel *channel + = container_of(kobj, struct vmbus_channel, kobj); + + kfree_rcu(channel, rcu); +} + +struct vmbus_chan_attribute { + struct attribute attr; + ssize_t (*show)(const struct vmbus_channel *chan, char *buf); + ssize_t (*store)(struct vmbus_channel *chan, + const char *buf, size_t count); +}; +#define VMBUS_CHAN_ATTR(_name, _mode, _show, _store) \ + struct vmbus_chan_attribute chan_attr_##_name \ + = __ATTR(_name, _mode, _show, _store) +#define VMBUS_CHAN_ATTR_RW(_name) \ + struct vmbus_chan_attribute chan_attr_##_name = __ATTR_RW(_name) +#define VMBUS_CHAN_ATTR_RO(_name) \ + struct vmbus_chan_attribute chan_attr_##_name = __ATTR_RO(_name) +#define VMBUS_CHAN_ATTR_WO(_name) \ + struct vmbus_chan_attribute chan_attr_##_name = __ATTR_WO(_name) + +static ssize_t vmbus_chan_attr_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + const struct vmbus_chan_attribute *attribute + = container_of(attr, struct vmbus_chan_attribute, attr); + const struct vmbus_channel *chan + = container_of(kobj, struct vmbus_channel, kobj); + + if (!attribute->show) + return -EIO; + + return attribute->show(chan, buf); +} + +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) +{ + const struct hv_ring_buffer_info *rbi = &channel->outbound; + + return sprintf(buf, "%u\n", rbi->ring_buffer->interrupt_mask); +} +VMBUS_CHAN_ATTR_RO(out_mask); + +static ssize_t in_mask_show(const struct vmbus_channel *channel, char *buf) +{ + const struct hv_ring_buffer_info *rbi = &channel->inbound; + + return sprintf(buf, "%u\n", rbi->ring_buffer->interrupt_mask); +} +VMBUS_CHAN_ATTR_RO(in_mask); + +static ssize_t read_avail_show(const struct vmbus_channel *channel, char *buf) +{ + const struct hv_ring_buffer_info *rbi = &channel->inbound; + + return sprintf(buf, "%u\n", hv_get_bytes_to_read(rbi)); +} +VMBUS_CHAN_ATTR_RO(read_avail); + +static ssize_t write_avail_show(const struct vmbus_channel *channel, char *buf) +{ + const struct hv_ring_buffer_info *rbi = &channel->outbound; + + return sprintf(buf, "%u\n", hv_get_bytes_to_write(rbi)); +} +VMBUS_CHAN_ATTR_RO(write_avail); + +static ssize_t show_target_cpu(const struct vmbus_channel *channel, char *buf) +{ + return sprintf(buf, "%u\n", channel->target_cpu); +} +VMBUS_CHAN_ATTR(cpu, S_IRUGO, show_target_cpu, NULL); + +static ssize_t channel_pending_show(const struct vmbus_channel *channel, + char *buf) +{ + return sprintf(buf, "%d\n", + channel_pending(channel, + vmbus_connection.monitor_pages[1])); +} +VMBUS_CHAN_ATTR(pending, S_IRUGO, channel_pending_show, NULL); + +static ssize_t channel_latency_show(const struct vmbus_channel *channel, + char *buf) +{ + return sprintf(buf, "%d\n", + channel_latency(channel, + vmbus_connection.monitor_pages[1])); +} +VMBUS_CHAN_ATTR(latency, S_IRUGO, channel_latency_show, NULL); + +static struct attribute *vmbus_chan_attrs[] = { + &chan_attr_out_mask.attr, + &chan_attr_in_mask.attr, + &chan_attr_read_avail.attr, + &chan_attr_write_avail.attr, + &chan_attr_cpu.attr, + &chan_attr_pending.attr, + &chan_attr_latency.attr, + NULL +}; + +static struct kobj_type vmbus_chan_ktype = { + .sysfs_ops = &vmbus_chan_sysfs_ops, + .release = vmbus_chan_release, + .default_attrs = vmbus_chan_attrs, +}; + +/* + * vmbus_add_channel_kobj - setup a sub-directory under device/channels + */ +int vmbus_add_channel_kobj(struct hv_device *dev, struct vmbus_channel *channel) +{ + struct kobject *kobj = &channel->kobj; + u32 relid = channel->offermsg.child_relid; + int ret; + + kobj->kset = dev->channels_kset; + ret = kobject_init_and_add(kobj, &vmbus_chan_ktype, NULL, + "%u", relid); + if (ret) + return ret; + + kobject_uevent(kobj, KOBJ_ADD); + + return 0; +} + /* * vmbus_device_create - Creates and registers a new child device * on the vmbus. @@ -1165,7 +1306,8 @@ struct hv_device *vmbus_device_create(const uuid_le *type, */ int vmbus_device_register(struct hv_device *child_device_obj) { - int ret = 0; + struct kobject *kobj = &child_device_obj->device.kobj; + int ret; dev_set_name(&child_device_obj->device, "%pUl", child_device_obj->channel->offermsg.offer.if_instance.b); @@ -1179,13 +1321,32 @@ int vmbus_device_register(struct hv_device *child_device_obj) * binding...which will eventually call vmbus_match() and vmbus_probe() */ ret = device_register(&child_device_obj->device); - - if (ret) + if (ret) { pr_err("Unable to register child device\n"); - else - pr_debug("child device %s registered\n", - dev_name(&child_device_obj->device)); + return ret; + } + + child_device_obj->channels_kset = kset_create_and_add("channels", + NULL, kobj); + if (!child_device_obj->channels_kset) { + ret = -ENOMEM; + goto err_dev_unregister; + } + + ret = vmbus_add_channel_kobj(child_device_obj, + child_device_obj->channel); + if (ret) { + pr_err("Unable to register primary channeln"); + goto err_kset_unregister; + } + + return 0; + +err_kset_unregister: + kset_unregister(child_device_obj->channels_kset); +err_dev_unregister: + device_unregister(&child_device_obj->device); return ret; } diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index c458d7b7ad19..ef16ee039850 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -828,6 +828,11 @@ struct vmbus_channel { */ struct rcu_head rcu; + /* + * For sysfs per-channel properties. + */ + struct kobject kobj; + /* * For performance critical channels (storage, networking * etc,), Hyper-V has a mechanism to enhance the throughput @@ -1089,6 +1094,7 @@ struct hv_device { struct device device; struct vmbus_channel *channel; + struct kset *channels_kset; }; -- cgit v1.2.3-59-g8ed1b From 6981fbf3780366093858c5d2dcdaadcd1fbb04be Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 29 Oct 2017 11:33:40 -0700 Subject: Drivers: hv: vmbus: Expose per-channel interrupts and events counters When investigating performance, it is useful to be able to look at the number of host and guest events per-channel. This is equivalent to per-device interrupt statistics. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/stable/sysfs-bus-vmbus | 26 ++++++++++++++++++++------ drivers/hv/connection.c | 2 ++ drivers/hv/vmbus_drv.c | 16 ++++++++++++++++ include/linux/hyperv.h | 4 ++++ 4 files changed, 42 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/Documentation/ABI/stable/sysfs-bus-vmbus b/Documentation/ABI/stable/sysfs-bus-vmbus index 0ebd8a1537a0..d4077cc60d55 100644 --- a/Documentation/ABI/stable/sysfs-bus-vmbus +++ b/Documentation/ABI/stable/sysfs-bus-vmbus @@ -61,39 +61,53 @@ Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Inbound channel signaling state -Users: Debuggig tools +Users: Debugging tools What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/latency Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Channel signaling latency -Users: Debuggig tools +Users: Debugging tools What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/out_mask Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Outbound channel signaling state -Users: Debuggig tools +Users: Debugging tools What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/pending Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Channel interrupt pending state -Users: Debuggig tools +Users: Debugging tools What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/read_avail Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Bytes availabble to read -Users: Debuggig tools +Users: Debugging tools What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/write_avail Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger Description: Bytes availabble to write -Users: Debuggig tools +Users: Debugging tools + +What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/events +Date: September. 2017 +KernelVersion: 4.14 +Contact: Stephen Hemminger +Description: Number of times we have signaled the host +Users: Debugging tools + +What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/interrupts +Date: September. 2017 +KernelVersion: 4.14 +Contact: Stephen Hemminger +Description: Number of times we have taken an interrupt (incoming) +Users: Debugging tools diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index f41901f80b64..b06a6b796819 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -409,6 +409,8 @@ void vmbus_set_event(struct vmbus_channel *channel) if (!channel->is_dedicated_interrupt) vmbus_send_interrupt(child_relid); + ++channel->sig_events; + hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, channel->sig_event); } EXPORT_SYMBOL_GPL(vmbus_set_event); diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 1da8e818f4de..bca8188f3c8c 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -944,6 +944,8 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu) if (channel->rescind) continue; + ++channel->interrupts; + switch (channel->callback_mode) { case HV_CALL_ISR: vmbus_channel_isr(channel); @@ -1237,6 +1239,18 @@ static ssize_t channel_latency_show(const struct vmbus_channel *channel, } VMBUS_CHAN_ATTR(latency, S_IRUGO, channel_latency_show, NULL); +static ssize_t channel_interrupts_show(const struct vmbus_channel *channel, char *buf) +{ + return sprintf(buf, "%llu\n", channel->interrupts); +} +VMBUS_CHAN_ATTR(interrupts, S_IRUGO, channel_interrupts_show, NULL); + +static ssize_t channel_events_show(const struct vmbus_channel *channel, char *buf) +{ + return sprintf(buf, "%llu\n", channel->sig_events); +} +VMBUS_CHAN_ATTR(events, S_IRUGO, channel_events_show, NULL); + static struct attribute *vmbus_chan_attrs[] = { &chan_attr_out_mask.attr, &chan_attr_in_mask.attr, @@ -1245,6 +1259,8 @@ static struct attribute *vmbus_chan_attrs[] = { &chan_attr_cpu.attr, &chan_attr_pending.attr, &chan_attr_latency.attr, + &chan_attr_interrupts.attr, + &chan_attr_events.attr, NULL }; diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index ea6b5586ad77..f3e97c5f94c9 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -719,6 +719,10 @@ struct vmbus_channel { struct vmbus_close_msg close_msg; + /* Statistics */ + u64 interrupts; /* Host to Guest interrupts */ + u64 sig_events; /* Guest to Host events */ + /* Channel callback's invoked in softirq context */ struct tasklet_struct callback_event; void (*onchannel_callback)(void *context); -- cgit v1.2.3-59-g8ed1b