From 6113e3d28149dee33f10e92df6a16efb2b9cf473 Mon Sep 17 00:00:00 2001 From: Alex Ng Date: Sun, 30 Apr 2017 16:21:14 -0700 Subject: Tools: hv: vss: Thaw the filesystem and continue if freeze call has timed out If a FREEZE operation takes too long, the driver may time out and move on to another operation. The daemon is unaware of this and attempts to notify the driver that the FREEZE succeeded. This results in an error from the driver and the daemon leaves the filesystem in frozen state. Fix this by thawing the filesystem and continuing. Signed-off-by: Michael Gissing Signed-off-by: Alex Ng Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- tools/hv/hv_vss_daemon.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c index e0829809c897..7ba54195934c 100644 --- a/tools/hv/hv_vss_daemon.c +++ b/tools/hv/hv_vss_daemon.c @@ -261,7 +261,9 @@ int main(int argc, char *argv[]) if (len != sizeof(struct hv_vss_msg)) { syslog(LOG_ERR, "write failed; error: %d %s", errno, strerror(errno)); - exit(EXIT_FAILURE); + + if (op == VSS_OP_FREEZE) + vss_operate(VSS_OP_THAW); } } -- cgit v1.2.3 From a1a7ea6bd6d55b6620c9c0a43bf684d6c427172a Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Sun, 30 Apr 2017 16:21:15 -0700 Subject: tools: hv: properly handle long paths Paths can be up to PATH_MAX long and PATH_MAX is usually greater than 256. While on it, simplify path reconstruction to a simple snprintf(), define and reuse KVP_NET_DIR. Suggested-by: Tomas Hozza Signed-off-by: Vitaly Kuznetsov Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- tools/hv/hv_kvp_daemon.c | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index f1758fcbc37d..88b20e007c05 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -39,6 +39,7 @@ #include #include #include +#include #include /* @@ -97,6 +98,8 @@ static struct utsname uts_buf; #define KVP_SCRIPTS_PATH "/usr/libexec/hypervkvpd/" #endif +#define KVP_NET_DIR "/sys/class/net/" + #define MAX_FILE_NAME 100 #define ENTRIES_PER_BLOCK 50 @@ -596,26 +599,21 @@ static char *kvp_get_if_name(char *guid) DIR *dir; struct dirent *entry; FILE *file; - char *p, *q, *x; + char *p, *x; char *if_name = NULL; char buf[256]; - char *kvp_net_dir = "/sys/class/net/"; - char dev_id[256]; + char dev_id[PATH_MAX]; - dir = opendir(kvp_net_dir); + dir = opendir(KVP_NET_DIR); if (dir == NULL) return NULL; - snprintf(dev_id, sizeof(dev_id), "%s", kvp_net_dir); - q = dev_id + strlen(kvp_net_dir); - while ((entry = readdir(dir)) != NULL) { /* * Set the state for the next pass. */ - *q = '\0'; - strcat(dev_id, entry->d_name); - strcat(dev_id, "/device/device_id"); + snprintf(dev_id, sizeof(dev_id), "%s%s/device/device_id", + KVP_NET_DIR, entry->d_name); file = fopen(dev_id, "r"); if (file == NULL) @@ -653,12 +651,12 @@ static char *kvp_if_name_to_mac(char *if_name) FILE *file; char *p, *x; char buf[256]; - char addr_file[256]; + char addr_file[PATH_MAX]; unsigned int i; char *mac_addr = NULL; - snprintf(addr_file, sizeof(addr_file), "%s%s%s", "/sys/class/net/", - if_name, "/address"); + snprintf(addr_file, sizeof(addr_file), "%s%s%s", KVP_NET_DIR, + if_name, "/address"); file = fopen(addr_file, "r"); if (file == NULL) @@ -688,28 +686,22 @@ static char *kvp_mac_to_if_name(char *mac) DIR *dir; struct dirent *entry; FILE *file; - char *p, *q, *x; + char *p, *x; char *if_name = NULL; char buf[256]; - char *kvp_net_dir = "/sys/class/net/"; - char dev_id[256]; + char dev_id[PATH_MAX]; unsigned int i; - dir = opendir(kvp_net_dir); + dir = opendir(KVP_NET_DIR); if (dir == NULL) return NULL; - snprintf(dev_id, sizeof(dev_id), "%s", kvp_net_dir); - q = dev_id + strlen(kvp_net_dir); - while ((entry = readdir(dir)) != NULL) { /* * Set the state for the next pass. */ - *q = '\0'; - - strcat(dev_id, entry->d_name); - strcat(dev_id, "/address"); + snprintf(dev_id, sizeof(dev_id), "%s%s/address", KVP_NET_DIR, + entry->d_name); file = fopen(dev_id, "r"); if (file == NULL) @@ -1218,9 +1210,9 @@ static int process_ip_string(FILE *f, char *ip_string, int type) static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) { int error = 0; - char if_file[128]; + char if_file[PATH_MAX]; FILE *file; - char cmd[512]; + char cmd[PATH_MAX]; char *mac_addr; /* -- cgit v1.2.3 From 48f4ccdfc46906627f77fda94d80f2db1bd23ba3 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sun, 30 Apr 2017 16:21:16 -0700 Subject: Drivers: hv: vmbus: Fix error code returned by vmbus_post_msg() ENOBUFS is a more approrpiate error code to be returned when the hypervisor cannot post the message because of insufficient buffers. Make the adjustment. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index fce27fb141cc..a938fcfe9bc9 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -370,7 +370,7 @@ int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep) break; case HV_STATUS_INSUFFICIENT_MEMORY: case HV_STATUS_INSUFFICIENT_BUFFERS: - ret = -ENOMEM; + ret = -ENOBUFS; break; case HV_STATUS_SUCCESS: return ret; -- cgit v1.2.3 From 1e052a16eb2caf6727b594cad0744ccdfddf4254 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sun, 30 Apr 2017 16:21:17 -0700 Subject: Drivers: hv: util: Make hv_poll_channel() a little more efficient The current code unconditionally sends an IPI. If we are running on the correct CPU and are in interrupt level, we don't need an IPI. Make this adjustment. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/hyperv_vmbus.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 6113e915c50e..fa514be7679c 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -411,6 +411,10 @@ static inline void hv_poll_channel(struct vmbus_channel *channel, if (!channel) return; + if (in_interrupt() && (channel->target_cpu == smp_processor_id())) { + cb(channel); + return; + } smp_call_function_single(channel->target_cpu, cb, channel, true); } -- cgit v1.2.3 From 54a66265d6754b37fb4baf1d970ec88a6225a988 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sun, 30 Apr 2017 16:21:18 -0700 Subject: Drivers: hv: vmbus: Fix rescind handling Fix the rescind handling. This patch addresses the following rescind scenario that is currently not handled correctly: If a rescind were to be received while the offer is still being peocessed, we will be blocked indefinitely since the rescind message is handled on the same work element as the offer message. Fix this issue. I would like to thank Dexuan Cui and Long Li for working with me on this patch. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel.c | 8 ++++-- drivers/hv/channel_mgmt.c | 69 ++++++++++++++++++++++++++++++++++++----------- drivers/hv/connection.c | 7 +++-- drivers/hv/hyperv_vmbus.h | 7 +++++ drivers/hv/vmbus_drv.c | 29 +++++++++++++++++++- 5 files changed, 99 insertions(+), 21 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 736ac76d2a6a..e9bf0bb87ac4 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -630,9 +630,13 @@ void vmbus_close(struct vmbus_channel *channel) */ list_for_each_safe(cur, tmp, &channel->sc_list) { cur_channel = list_entry(cur, struct vmbus_channel, sc_list); - if (cur_channel->state != CHANNEL_OPENED_STATE) - continue; vmbus_close_internal(cur_channel); + if (cur_channel->rescind) { + mutex_lock(&vmbus_connection.channel_mutex); + hv_process_channel_removal(cur_channel, + cur_channel->offermsg.child_relid); + mutex_unlock(&vmbus_connection.channel_mutex); + } } /* * Now close the primary. diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 735f9363f2e4..0fabd410efd9 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -428,7 +428,6 @@ void vmbus_free_channels(void) { struct vmbus_channel *channel, *tmp; - mutex_lock(&vmbus_connection.channel_mutex); list_for_each_entry_safe(channel, tmp, &vmbus_connection.chn_list, listentry) { /* hv_process_channel_removal() needs this */ @@ -436,7 +435,6 @@ void vmbus_free_channels(void) vmbus_device_unregister(channel->device_obj); } - mutex_unlock(&vmbus_connection.channel_mutex); } /* @@ -483,8 +481,10 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) list_add_tail(&newchannel->sc_list, &channel->sc_list); channel->num_sc++; spin_unlock_irqrestore(&channel->lock, flags); - } else + } else { + atomic_dec(&vmbus_connection.offer_in_progress); goto err_free_chan; + } } dev_type = hv_get_dev_type(newchannel); @@ -511,6 +511,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) if (!fnew) { if (channel->sc_creation_callback != NULL) channel->sc_creation_callback(newchannel); + atomic_dec(&vmbus_connection.offer_in_progress); return; } @@ -532,9 +533,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) * binding which eventually invokes the device driver's AddDevice() * method. */ - mutex_lock(&vmbus_connection.channel_mutex); ret = vmbus_device_register(newchannel->device_obj); - mutex_unlock(&vmbus_connection.channel_mutex); if (ret != 0) { pr_err("unable to add child device object (relid %d)\n", @@ -542,6 +541,8 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) kfree(newchannel->device_obj); goto err_deq_chan; } + + atomic_dec(&vmbus_connection.offer_in_progress); return; err_deq_chan: @@ -797,6 +798,7 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) newchannel = alloc_channel(); if (!newchannel) { vmbus_release_relid(offer->child_relid); + atomic_dec(&vmbus_connection.offer_in_progress); pr_err("Unable to allocate channel object\n"); return; } @@ -843,16 +845,38 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) rescind = (struct vmbus_channel_rescind_offer *)hdr; + /* + * The offer msg and the corresponding rescind msg + * from the host are guranteed to be ordered - + * offer comes in first and then the rescind. + * Since we process these events in work elements, + * and with preemption, we may end up processing + * the events out of order. Given that we handle these + * work elements on the same CPU, this is possible only + * in the case of preemption. In any case wait here + * until the offer processing has moved beyond the + * point where the channel is discoverable. + */ + + while (atomic_read(&vmbus_connection.offer_in_progress) != 0) { + /* + * We wait here until any channel offer is currently + * being processed. + */ + msleep(1); + } + mutex_lock(&vmbus_connection.channel_mutex); channel = relid2channel(rescind->child_relid); + mutex_unlock(&vmbus_connection.channel_mutex); if (channel == NULL) { /* - * This is very impossible, because in - * vmbus_process_offer(), we have already invoked - * vmbus_release_relid() on error. + * We failed in processing the offer message; + * we would have cleaned up the relid in that + * failure path. */ - goto out; + return; } spin_lock_irqsave(&channel->lock, flags); @@ -864,7 +888,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) if (channel->device_obj) { if (channel->chn_rescind_callback) { channel->chn_rescind_callback(channel); - goto out; + return; } /* * We will have to unregister this device from the @@ -875,13 +899,26 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) vmbus_device_unregister(channel->device_obj); put_device(dev); } - } else { - hv_process_channel_removal(channel, - channel->offermsg.child_relid); } - -out: - mutex_unlock(&vmbus_connection.channel_mutex); + if (channel->primary_channel != NULL) { + /* + * Sub-channel is being rescinded. Following is the channel + * close sequence when initiated from the driveri (refer to + * vmbus_close() for details): + * 1. Close all sub-channels first + * 2. Then close the primary channel. + */ + if (channel->state == CHANNEL_OPEN_STATE) { + /* + * The channel is currently not open; + * it is safe for us to cleanup the channel. + */ + mutex_lock(&vmbus_connection.channel_mutex); + hv_process_channel_removal(channel, + channel->offermsg.child_relid); + mutex_unlock(&vmbus_connection.channel_mutex); + } + } } void vmbus_hvsock_device_unregister(struct vmbus_channel *channel) diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index a938fcfe9bc9..c2d74ee95f60 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -93,10 +93,13 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, * all the CPUs. This is needed for kexec to work correctly where * the CPU attempting to connect may not be CPU 0. */ - if (version >= VERSION_WIN8_1) + if (version >= VERSION_WIN8_1) { msg->target_vcpu = hv_context.vp_index[smp_processor_id()]; - else + vmbus_connection.connect_cpu = smp_processor_id(); + } else { msg->target_vcpu = 0; + vmbus_connection.connect_cpu = 0; + } /* * Add to list before we send the request since we may diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index fa514be7679c..1b6a5e0dfa75 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -303,6 +303,13 @@ enum vmbus_connect_state { #define MAX_SIZE_CHANNEL_MESSAGE HV_MESSAGE_PAYLOAD_BYTE_COUNT struct vmbus_connection { + /* + * CPU on which the initial host contact was made. + */ + int connect_cpu; + + atomic_t offer_in_progress; + enum vmbus_connect_state conn_state; atomic_t next_gpadl_handle; diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 0087b49095eb..59bb3efa6e10 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -798,8 +798,10 @@ static void vmbus_device_release(struct device *device) struct hv_device *hv_dev = device_to_hv_device(device); struct vmbus_channel *channel = hv_dev->channel; + mutex_lock(&vmbus_connection.channel_mutex); hv_process_channel_removal(channel, channel->offermsg.child_relid); + mutex_unlock(&vmbus_connection.channel_mutex); kfree(hv_dev); } @@ -877,7 +879,32 @@ void vmbus_on_msg_dpc(unsigned long data) INIT_WORK(&ctx->work, vmbus_onmessage_work); memcpy(&ctx->msg, msg, sizeof(*msg)); - queue_work(vmbus_connection.work_queue, &ctx->work); + /* + * The host can generate a rescind message while we + * may still be handling the original offer. We deal with + * this condition by ensuring the processing is done on the + * same CPU. + */ + switch (hdr->msgtype) { + case CHANNELMSG_RESCIND_CHANNELOFFER: + /* + * If we are handling the rescind message; + * schedule the work on the global work queue. + */ + schedule_work_on(vmbus_connection.connect_cpu, + &ctx->work); + break; + + case CHANNELMSG_OFFERCHANNEL: + atomic_inc(&vmbus_connection.offer_in_progress); + queue_work_on(vmbus_connection.connect_cpu, + vmbus_connection.work_queue, + &ctx->work); + break; + + default: + queue_work(vmbus_connection.work_queue, &ctx->work); + } } else entry->message_handler(hdr); -- cgit v1.2.3 From a3ade8cc474d848676278660e65f5af1e9e094d9 Mon Sep 17 00:00:00 2001 From: Long Li Date: Sun, 30 Apr 2017 16:21:19 -0700 Subject: HV: properly delay KVP packets when negotiation is in progress The host may send multiple negotiation packets (due to timeout) before the KVP user-mode daemon is connected. KVP user-mode daemon is connected. We need to defer processing those packets until the daemon is negotiated and connected. It's okay for guest to respond to all negotiation packets. In addition, the host may send multiple staged KVP requests as soon as negotiation is done. We need to properly process those packets using one tasklet for exclusive access to ring buffer. This patch is based on the work of Nick Meier . Signed-off-by: Long Li Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/hv_kvp.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index e99ff2ddad40..9a90b915b5be 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c @@ -112,7 +112,7 @@ static void kvp_poll_wrapper(void *channel) { /* Transaction is finished, reset the state here to avoid races. */ kvp_transaction.state = HVUTIL_READY; - hv_kvp_onchannelcallback(channel); + tasklet_schedule(&((struct vmbus_channel *)channel)->callback_event); } static void kvp_register_done(void) @@ -159,7 +159,7 @@ static void kvp_timeout_func(struct work_struct *dummy) static void kvp_host_handshake_func(struct work_struct *dummy) { - hv_poll_channel(kvp_transaction.recv_channel, hv_kvp_onchannelcallback); + tasklet_schedule(&kvp_transaction.recv_channel->callback_event); } static int kvp_handle_handshake(struct hv_kvp_msg *msg) @@ -625,16 +625,17 @@ void hv_kvp_onchannelcallback(void *context) NEGO_IN_PROGRESS, NEGO_FINISHED} host_negotiatied = NEGO_NOT_STARTED; - if (host_negotiatied == NEGO_NOT_STARTED && - kvp_transaction.state < HVUTIL_READY) { + if (kvp_transaction.state < HVUTIL_READY) { /* * If userspace daemon is not connected and host is asking * us to negotiate we need to delay to not lose messages. * This is important for Failover IP setting. */ - host_negotiatied = NEGO_IN_PROGRESS; - schedule_delayed_work(&kvp_host_handshake_work, + if (host_negotiatied == NEGO_NOT_STARTED) { + host_negotiatied = NEGO_IN_PROGRESS; + schedule_delayed_work(&kvp_host_handshake_work, HV_UTIL_NEGO_TIMEOUT * HZ); + } return; } if (kvp_transaction.state > HVUTIL_READY) @@ -702,6 +703,7 @@ void hv_kvp_onchannelcallback(void *context) VM_PKT_DATA_INBAND, 0); host_negotiatied = NEGO_FINISHED; + hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper); } } -- cgit v1.2.3 From df2aa81a44a904c34473f0974d67c5b257163e86 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 15 May 2017 11:08:09 +0200 Subject: ipack: Delete an error message for a failed memory allocation in ipack_device_read_id() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Omit an extra message for a memory allocation failure in this function. This issue was detected by using the Coccinelle software. Link: http://events.linuxfoundation.org/sites/events/files/slides/LCJ16-Refactor_Strings-WSang_0.pdf Signed-off-by: Markus Elfring Acked-by: Samuel Iglesias Gonsálvez Signed-off-by: Greg Kroah-Hartman --- drivers/ipack/ipack.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/ipack/ipack.c b/drivers/ipack/ipack.c index 12102448fddd..575c4f29e0f7 100644 --- a/drivers/ipack/ipack.c +++ b/drivers/ipack/ipack.c @@ -402,7 +402,6 @@ static int ipack_device_read_id(struct ipack_device *dev) * ID ROM contents */ dev->id = kmalloc(dev->id_avail, GFP_KERNEL); if (!dev->id) { - dev_err(&dev->dev, "dev->id alloc failed.\n"); ret = -ENOMEM; goto out; } -- cgit v1.2.3 From ff35eb23de9be50fbe3405f35244b5e82eadc5fa Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 15 May 2017 11:08:10 +0200 Subject: ipack: Improve a size determination in ipack_bus_register() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the specification of a data structure by a pointer dereference as the parameter for the operator "sizeof" to make the corresponding size determination a bit safer according to the Linux coding style convention. Signed-off-by: Markus Elfring Acked-by: Samuel Iglesias Gonsálvez Signed-off-by: Greg Kroah-Hartman --- drivers/ipack/ipack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ipack/ipack.c b/drivers/ipack/ipack.c index 575c4f29e0f7..a1e07a77d4e6 100644 --- a/drivers/ipack/ipack.c +++ b/drivers/ipack/ipack.c @@ -212,7 +212,7 @@ struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots, int bus_nr; struct ipack_bus_device *bus; - bus = kzalloc(sizeof(struct ipack_bus_device), GFP_KERNEL); + bus = kzalloc(sizeof(*bus), GFP_KERNEL); if (!bus) return NULL; -- cgit v1.2.3 From f4660cc994e12bae60d6f49895636fba662ce0a1 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 10 May 2017 10:19:18 -0400 Subject: vhost/vsock: use static minor number Vhost-vsock is a software device so there is no probe call that causes the driver to register its misc char device node. This creates a chicken and egg problem: userspace applications must open /dev/vhost-vsock to use the driver but the file doesn't exist until the kernel module has been loaded. Use the devname modalias mechanism so that /dev/vhost-vsock is created at boot. The vhost_vsock kernel module is automatically loaded when the first application opens /dev/host-vsock. Note that the "reserved for local use" range in Documentation/admin-guide/devices.txt is incorrect. The userio driver already occupies part of that range. I've updated the documentation accordingly. Cc: device@lanana.org Signed-off-by: Stefan Hajnoczi Signed-off-by: Greg Kroah-Hartman --- Documentation/admin-guide/devices.txt | 4 +++- drivers/vhost/vsock.c | 4 +++- include/linux/miscdevice.h | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Documentation/admin-guide/devices.txt b/Documentation/admin-guide/devices.txt index c9cea2e39c21..6b71852dadc2 100644 --- a/Documentation/admin-guide/devices.txt +++ b/Documentation/admin-guide/devices.txt @@ -369,8 +369,10 @@ 237 = /dev/loop-control Loopback control device 238 = /dev/vhost-net Host kernel accelerator for virtio net 239 = /dev/uhid User-space I/O driver support for HID subsystem + 240 = /dev/userio Serio driver testing device + 241 = /dev/vhost-vsock Host kernel driver for virtio vsock - 240-254 Reserved for local use + 242-254 Reserved for local use 255 Reserved for MISC_DYNAMIC_MINOR 11 char Raw keyboard device (Linux/SPARC only) diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index 3acef3c5d8ed..3f63e03de8e8 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -706,7 +706,7 @@ static const struct file_operations vhost_vsock_fops = { }; static struct miscdevice vhost_vsock_misc = { - .minor = MISC_DYNAMIC_MINOR, + .minor = VHOST_VSOCK_MINOR, .name = "vhost-vsock", .fops = &vhost_vsock_fops, }; @@ -778,3 +778,5 @@ module_exit(vhost_vsock_exit); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Asias He"); MODULE_DESCRIPTION("vhost transport for vsock "); +MODULE_ALIAS_MISCDEV(VHOST_VSOCK_MINOR); +MODULE_ALIAS("devname:vhost-vsock"); diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index 762b5fec3383..58751eae5f77 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -54,6 +54,7 @@ #define VHOST_NET_MINOR 238 #define UHID_MINOR 239 #define USERIO_MINOR 240 +#define VHOST_VSOCK_MINOR 241 #define MISC_DYNAMIC_MINOR 255 struct device; -- cgit v1.2.3 From 98e959d44bcaac70c3056578122b5ce777ff42f0 Mon Sep 17 00:00:00 2001 From: Vincent Legoll Date: Tue, 11 Apr 2017 16:26:41 +0200 Subject: drivers: pps: Make PPS into a menuconfig to ease disabling So that there's no need to get into the submenu to disable all related config entries. The BROKEN PPS_GENERATOR_PARPORT now also depends on PPS Signed-off-by: Vincent Legoll Acked-by: Rodolfo Giometti Signed-off-by: Greg Kroah-Hartman --- drivers/pps/Kconfig | 12 +++--------- drivers/pps/clients/Kconfig | 6 ++---- drivers/pps/generators/Kconfig | 3 ++- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/pps/Kconfig b/drivers/pps/Kconfig index 564a51abeece..4b29a7182d7b 100644 --- a/drivers/pps/Kconfig +++ b/drivers/pps/Kconfig @@ -2,9 +2,7 @@ # PPS support configuration # -menu "PPS support" - -config PPS +menuconfig PPS tristate "PPS support" ---help--- PPS (Pulse Per Second) is a special pulse provided by some GPS @@ -20,10 +18,10 @@ config PPS To compile this driver as a module, choose M here: the module will be called pps_core.ko. -if PPS config PPS_DEBUG bool "PPS debugging messages" + depends on PPS help Say Y here if you want the PPS support to produce a bunch of debug messages to the system log. Select this if you are having a @@ -31,17 +29,13 @@ config PPS_DEBUG config NTP_PPS bool "PPS kernel consumer support" - depends on !NO_HZ_COMMON + depends on PPS && !NO_HZ_COMMON help This option adds support for direct in-kernel time synchronization using an external PPS signal. It doesn't work on tickless systems at the moment. -endif - source drivers/pps/clients/Kconfig source drivers/pps/generators/Kconfig - -endmenu diff --git a/drivers/pps/clients/Kconfig b/drivers/pps/clients/Kconfig index 0c9f2805d076..efec021ce662 100644 --- a/drivers/pps/clients/Kconfig +++ b/drivers/pps/clients/Kconfig @@ -2,12 +2,12 @@ # PPS clients configuration # -if PPS - comment "PPS clients support" + depends on PPS config PPS_CLIENT_KTIMER tristate "Kernel timer client (Testing client, use for debug)" + depends on PPS help If you say yes here you get support for a PPS debugging client which uses a kernel timer to generate the PPS signal. @@ -37,5 +37,3 @@ config PPS_CLIENT_GPIO GPIO. To be useful you must also register a platform device specifying the GPIO pin and other options, usually in your board setup. - -endif diff --git a/drivers/pps/generators/Kconfig b/drivers/pps/generators/Kconfig index e4c4f3dc0728..86b59378e71f 100644 --- a/drivers/pps/generators/Kconfig +++ b/drivers/pps/generators/Kconfig @@ -3,10 +3,11 @@ # comment "PPS generators support" + depends on PPS config PPS_GENERATOR_PARPORT tristate "Parallel port PPS signal generator" - depends on PARPORT && BROKEN + depends on PPS && PARPORT && BROKEN help If you say yes here you get support for a PPS signal generator which utilizes STROBE pin of a parallel port to send PPS signals. It uses -- cgit v1.2.3 From acec09e67dc450d09a912735855326c3f1146a37 Mon Sep 17 00:00:00 2001 From: Jim Harris Date: Tue, 2 May 2017 07:20:59 -0700 Subject: uio/uio_pci_generic: don't fail probe if pdev->irq == NULL Some userspace drivers and frameworks only poll and do not require interrupts to be available and enabled on the PCI device. So remove the requirement that an IRQ is assigned. If an IRQ is not assigned and a userspace driver tries to read()/write(), the generic uio framework will just return -EIO. This allows binding uio_pci_generic to devices which cannot get an IRQ assigned, such as an NVMe controller behind Intel Volume Management Device (VMD), since VMD does not support INTx interrupts. Signed-off-by: Jim Harris Acked-by: Michael S. Tsirkin Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio_pci_generic.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c index d0b508b68f3c..a56fdf972dbe 100644 --- a/drivers/uio/uio_pci_generic.c +++ b/drivers/uio/uio_pci_generic.c @@ -66,14 +66,7 @@ static int probe(struct pci_dev *pdev, return err; } - if (!pdev->irq) { - dev_warn(&pdev->dev, "No IRQ assigned to device: " - "no support for interrupts?\n"); - pci_disable_device(pdev); - return -ENODEV; - } - - if (!pci_intx_mask_supported(pdev)) { + if (pdev->irq && !pci_intx_mask_supported(pdev)) { err = -ENODEV; goto err_verify; } @@ -86,10 +79,15 @@ static int probe(struct pci_dev *pdev, gdev->info.name = "uio_pci_generic"; gdev->info.version = DRIVER_VERSION; - gdev->info.irq = pdev->irq; - gdev->info.irq_flags = IRQF_SHARED; - gdev->info.handler = irqhandler; gdev->pdev = pdev; + if (pdev->irq) { + gdev->info.irq = pdev->irq; + gdev->info.irq_flags = IRQF_SHARED; + gdev->info.handler = irqhandler; + } else { + dev_warn(&pdev->dev, "No IRQ assigned to device: " + "no support for interrupts?\n"); + } err = uio_register_device(&pdev->dev, &gdev->info); if (err) -- cgit v1.2.3 From 7918cfc46cfad784b2aafdbbc690a96af0ae78d0 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Tue, 2 May 2017 15:16:29 -0700 Subject: firmware: google: memconsole: Make memconsole interface more flexible This patch redesigns the interface between the generic memconsole driver and its implementations to become more flexible than a flat memory buffer with unchanging bounds. This allows memconsoles like coreboot's to include lines that were added by runtime firmware after the driver was initialized. Since the console log size is thus no longer static, this means that the /sys/firmware/log file has to become unseekable. Signed-off-by: Julius Werner Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/google/memconsole-coreboot.c | 12 +++++++++--- drivers/firmware/google/memconsole-x86-legacy.c | 18 +++++++++++++++--- drivers/firmware/google/memconsole.c | 14 ++++++-------- drivers/firmware/google/memconsole.h | 7 ++++--- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/drivers/firmware/google/memconsole-coreboot.c b/drivers/firmware/google/memconsole-coreboot.c index 02711114dece..d48a80c3042d 100644 --- a/drivers/firmware/google/memconsole-coreboot.c +++ b/drivers/firmware/google/memconsole-coreboot.c @@ -33,6 +33,14 @@ struct cbmem_cons { static struct cbmem_cons __iomem *cbmem_console; +static ssize_t memconsole_coreboot_read(char *buf, loff_t pos, size_t count) +{ + return memory_read_from_buffer(buf, count, &pos, + cbmem_console->buffer_body, + min(cbmem_console->buffer_cursor, + cbmem_console->buffer_size)); +} + static int memconsole_coreboot_init(phys_addr_t physaddr) { struct cbmem_cons __iomem *tmp_cbmc; @@ -50,9 +58,7 @@ static int memconsole_coreboot_init(phys_addr_t physaddr) if (!cbmem_console) return -ENOMEM; - memconsole_setup(cbmem_console->buffer_body, - min(cbmem_console->buffer_cursor, cbmem_console->buffer_size)); - + memconsole_setup(memconsole_coreboot_read); return 0; } diff --git a/drivers/firmware/google/memconsole-x86-legacy.c b/drivers/firmware/google/memconsole-x86-legacy.c index 1f279ee883b9..8c1bf6dbdaa6 100644 --- a/drivers/firmware/google/memconsole-x86-legacy.c +++ b/drivers/firmware/google/memconsole-x86-legacy.c @@ -48,6 +48,15 @@ struct biosmemcon_ebda { }; } __packed; +static char *memconsole_baseaddr; +static size_t memconsole_length; + +static ssize_t memconsole_read(char *buf, loff_t pos, size_t count) +{ + return memory_read_from_buffer(buf, count, &pos, memconsole_baseaddr, + memconsole_length); +} + static void found_v1_header(struct biosmemcon_ebda *hdr) { pr_info("memconsole: BIOS console v1 EBDA structure found at %p\n", @@ -56,7 +65,9 @@ static void found_v1_header(struct biosmemcon_ebda *hdr) hdr->v1.buffer_addr, hdr->v1.start, hdr->v1.end, hdr->v1.num_chars); - memconsole_setup(phys_to_virt(hdr->v1.buffer_addr), hdr->v1.num_chars); + memconsole_baseaddr = phys_to_virt(hdr->v1.buffer_addr); + memconsole_length = hdr->v1.num_chars; + memconsole_setup(memconsole_read); } static void found_v2_header(struct biosmemcon_ebda *hdr) @@ -67,8 +78,9 @@ static void found_v2_header(struct biosmemcon_ebda *hdr) hdr->v2.buffer_addr, hdr->v2.start, hdr->v2.end, hdr->v2.num_bytes); - memconsole_setup(phys_to_virt(hdr->v2.buffer_addr + hdr->v2.start), - hdr->v2.end - hdr->v2.start); + memconsole_baseaddr = phys_to_virt(hdr->v2.buffer_addr + hdr->v2.start); + memconsole_length = hdr->v2.end - hdr->v2.start; + memconsole_setup(memconsole_read); } /* diff --git a/drivers/firmware/google/memconsole.c b/drivers/firmware/google/memconsole.c index 94e200ddb4fa..166f07c68c02 100644 --- a/drivers/firmware/google/memconsole.c +++ b/drivers/firmware/google/memconsole.c @@ -22,15 +22,15 @@ #include "memconsole.h" -static char *memconsole_baseaddr; -static size_t memconsole_length; +static ssize_t (*memconsole_read_func)(char *, loff_t, size_t); static ssize_t memconsole_read(struct file *filp, struct kobject *kobp, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t count) { - return memory_read_from_buffer(buf, count, &pos, memconsole_baseaddr, - memconsole_length); + if (WARN_ON_ONCE(!memconsole_read_func)) + return -EIO; + return memconsole_read_func(buf, pos, count); } static struct bin_attribute memconsole_bin_attr = { @@ -38,16 +38,14 @@ static struct bin_attribute memconsole_bin_attr = { .read = memconsole_read, }; -void memconsole_setup(void *baseaddr, size_t length) +void memconsole_setup(ssize_t (*read_func)(char *, loff_t, size_t)) { - memconsole_baseaddr = baseaddr; - memconsole_length = length; + memconsole_read_func = read_func; } EXPORT_SYMBOL(memconsole_setup); int memconsole_sysfs_init(void) { - memconsole_bin_attr.size = memconsole_length; return sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr); } EXPORT_SYMBOL(memconsole_sysfs_init); diff --git a/drivers/firmware/google/memconsole.h b/drivers/firmware/google/memconsole.h index 190fc03a51ae..ff1592dc7d1a 100644 --- a/drivers/firmware/google/memconsole.h +++ b/drivers/firmware/google/memconsole.h @@ -18,13 +18,14 @@ #ifndef __FIRMWARE_GOOGLE_MEMCONSOLE_H #define __FIRMWARE_GOOGLE_MEMCONSOLE_H +#include + /* * memconsole_setup * - * Initialize the memory console from raw (virtual) base - * address and length. + * Initialize the memory console, passing the function to handle read accesses. */ -void memconsole_setup(void *baseaddr, size_t length); +void memconsole_setup(ssize_t (*read_func)(char *, loff_t, size_t)); /* * memconsole_sysfs_init -- cgit v1.2.3 From a5061d028594a31dbf70f4554e0b7d83e5ce770f Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Tue, 2 May 2017 15:16:30 -0700 Subject: firmware: google: memconsole: Adapt to new coreboot ring buffer format The upstream coreboot implementation of memconsole was enhanced from a single-boot console to a persistent ring buffer (https://review.coreboot.org/#/c/18301). This patch changes the kernel memconsole driver to be able to read the new format in all cases. Signed-off-by: Julius Werner Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/google/memconsole-coreboot.c | 47 ++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/drivers/firmware/google/memconsole-coreboot.c b/drivers/firmware/google/memconsole-coreboot.c index d48a80c3042d..7d39f4ef5d9e 100644 --- a/drivers/firmware/google/memconsole-coreboot.c +++ b/drivers/firmware/google/memconsole-coreboot.c @@ -26,19 +26,50 @@ /* CBMEM firmware console log descriptor. */ struct cbmem_cons { - u32 buffer_size; - u32 buffer_cursor; - u8 buffer_body[0]; + u32 size; + u32 cursor; + u8 body[0]; } __packed; +#define CURSOR_MASK ((1 << 28) - 1) +#define OVERFLOW (1 << 31) + static struct cbmem_cons __iomem *cbmem_console; +/* + * The cbmem_console structure is read again on every access because it may + * change at any time if runtime firmware logs new messages. This may rarely + * lead to race conditions where the firmware overwrites the beginning of the + * ring buffer with more lines after we have already read |cursor|. It should be + * rare and harmless enough that we don't spend extra effort working around it. + */ static ssize_t memconsole_coreboot_read(char *buf, loff_t pos, size_t count) { - return memory_read_from_buffer(buf, count, &pos, - cbmem_console->buffer_body, - min(cbmem_console->buffer_cursor, - cbmem_console->buffer_size)); + u32 cursor = cbmem_console->cursor & CURSOR_MASK; + u32 flags = cbmem_console->cursor & ~CURSOR_MASK; + u32 size = cbmem_console->size; + struct seg { /* describes ring buffer segments in logical order */ + u32 phys; /* physical offset from start of mem buffer */ + u32 len; /* length of segment */ + } seg[2] = { {0}, {0} }; + size_t done = 0; + int i; + + if (flags & OVERFLOW) { + if (cursor > size) /* Shouldn't really happen, but... */ + cursor = 0; + seg[0] = (struct seg){.phys = cursor, .len = size - cursor}; + seg[1] = (struct seg){.phys = 0, .len = cursor}; + } else { + seg[0] = (struct seg){.phys = 0, .len = min(cursor, size)}; + } + + for (i = 0; i < ARRAY_SIZE(seg) && count > done; i++) { + done += memory_read_from_buffer(buf + done, count - done, &pos, + cbmem_console->body + seg[i].phys, seg[i].len); + pos -= seg[i].len; + } + return done; } static int memconsole_coreboot_init(phys_addr_t physaddr) @@ -51,7 +82,7 @@ static int memconsole_coreboot_init(phys_addr_t physaddr) return -ENOMEM; cbmem_console = memremap(physaddr, - tmp_cbmc->buffer_size + sizeof(*cbmem_console), + tmp_cbmc->size + sizeof(*cbmem_console), MEMREMAP_WB); memunmap(tmp_cbmc); -- cgit v1.2.3 From 34cfb106d1f8a746fcccbe61c852f705dcdceaa2 Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 18 May 2017 10:07:06 -0500 Subject: misc: sram-exec: Use aligned fncpy instead of memcpy Currently the sram-exec functionality, which allows allocation of executable memory and provides an API to move code to it, is only selected in configs for the ARM architecture. Based on commit 5756e9dd0de6 ("ARM: 6640/1: Thumb-2: Symbol manipulation macros for function body copying") simply copying a C function pointer address using memcpy without consideration of alignment and Thumb is unsafe on ARM platforms. The aforementioned patch introduces the fncpy macro which is a safe way to copy executable code on ARM platforms, so let's make use of that here rather than the unsafe plain memcpy that was previously used by sram_exec_copy. Now sram_exec_copy will move the code to "dst" and return an address that is guaranteed to be safely callable. In the future, architectures hoping to make use of the sram-exec functionality must define an fncpy macro just as ARM has done to guarantee or check for safe copying to executable memory before allowing the arch to select CONFIG_SRAM_EXEC. Acked-by: Tony Lindgren Acked-by: Russell King Reviewed-by: Alexandre Belloni Signed-off-by: Dave Gerlach Signed-off-by: Greg Kroah-Hartman --- drivers/misc/sram-exec.c | 27 ++++++++++++++++++++------- include/linux/sram.h | 8 ++++---- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/misc/sram-exec.c b/drivers/misc/sram-exec.c index 3d528a13b8fc..426ad912b441 100644 --- a/drivers/misc/sram-exec.c +++ b/drivers/misc/sram-exec.c @@ -19,6 +19,7 @@ #include #include +#include #include #include "sram.h" @@ -58,20 +59,32 @@ int sram_add_protect_exec(struct sram_partition *part) * @src: Source address for the data to copy * @size: Size of copy to perform, which starting from dst, must reside in pool * + * Return: Address for copied data that can safely be called through function + * pointer, or NULL if problem. + * * This helper function allows sram driver to act as central control location * of 'protect-exec' pools which are normal sram pools but are always set * read-only and executable except when copying data to them, at which point * they are set to read-write non-executable, to make sure no memory is * writeable and executable at the same time. This region must be page-aligned * and is checked during probe, otherwise page attribute manipulation would - * not be possible. + * not be possible. Care must be taken to only call the returned address as + * dst address is not guaranteed to be safely callable. + * + * NOTE: This function uses the fncpy macro to move code to the executable + * region. Some architectures have strict requirements for relocating + * executable code, so fncpy is a macro that must be defined by any arch + * making use of this functionality that guarantees a safe copy of exec + * data and returns a safe address that can be called as a C function + * pointer. */ -int sram_exec_copy(struct gen_pool *pool, void *dst, void *src, - size_t size) +void *sram_exec_copy(struct gen_pool *pool, void *dst, void *src, + size_t size) { struct sram_partition *part = NULL, *p; unsigned long base; int pages; + void *dst_cpy; mutex_lock(&exec_pool_list_mutex); list_for_each_entry(p, &exec_pool_list, list) { @@ -81,10 +94,10 @@ int sram_exec_copy(struct gen_pool *pool, void *dst, void *src, mutex_unlock(&exec_pool_list_mutex); if (!part) - return -EINVAL; + return NULL; if (!addr_in_gen_pool(pool, (unsigned long)dst, size)) - return -EINVAL; + return NULL; base = (unsigned long)part->base; pages = PAGE_ALIGN(size) / PAGE_SIZE; @@ -94,13 +107,13 @@ int sram_exec_copy(struct gen_pool *pool, void *dst, void *src, set_memory_nx((unsigned long)base, pages); set_memory_rw((unsigned long)base, pages); - memcpy(dst, src, size); + dst_cpy = fncpy(dst, src, size); set_memory_ro((unsigned long)base, pages); set_memory_x((unsigned long)base, pages); mutex_unlock(&part->lock); - return 0; + return dst_cpy; } EXPORT_SYMBOL_GPL(sram_exec_copy); diff --git a/include/linux/sram.h b/include/linux/sram.h index c97dcbe8ce25..4fb405fb0480 100644 --- a/include/linux/sram.h +++ b/include/linux/sram.h @@ -16,12 +16,12 @@ struct gen_pool; #ifdef CONFIG_SRAM_EXEC -int sram_exec_copy(struct gen_pool *pool, void *dst, void *src, size_t size); +void *sram_exec_copy(struct gen_pool *pool, void *dst, void *src, size_t size); #else -static inline int sram_exec_copy(struct gen_pool *pool, void *dst, void *src, - size_t size) +static inline void *sram_exec_copy(struct gen_pool *pool, void *dst, void *src, + size_t size) { - return -ENODEV; + return NULL; } #endif /* CONFIG_SRAM_EXEC */ #endif /* __LINUX_SRAM_H__ */ -- cgit v1.2.3 From 40fbb23881291bb57e4e25e859de8e2287426dac Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Tue, 23 May 2017 16:48:17 -0700 Subject: firmware: google: memconsole: Prevent overrun attack on coreboot console The recent coreboot memory console update (firmware: google: memconsole: Adapt to new coreboot ring buffer format) introduced a small security issue in the driver: The new driver implementation parses the memory console structure again on every access. This is intentional so that additional lines added concurrently by runtime firmware can be read out. However, if an attacker can write to the structure, they could increase the size value to a point where the driver would read potentially sensitive memory areas from outside the original console buffer during the next access. This can be done through /dev/mem, since the console buffer usually resides in firmware-reserved memory that is not covered by STRICT_DEVMEM. This patch resolves that problem by reading the buffer's size value only once during boot (where we can still trust the structure). Other parts of the structure can still be modified at runtime, but the driver's bounds checks make sure that it will never read outside the buffer. Fixes: a5061d028 ("firmware: google: memconsole: Adapt to new coreboot ring buffer format") Signed-off-by: Julius Werner Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/google/memconsole-coreboot.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/google/memconsole-coreboot.c b/drivers/firmware/google/memconsole-coreboot.c index 7d39f4ef5d9e..52738887735c 100644 --- a/drivers/firmware/google/memconsole-coreboot.c +++ b/drivers/firmware/google/memconsole-coreboot.c @@ -26,7 +26,7 @@ /* CBMEM firmware console log descriptor. */ struct cbmem_cons { - u32 size; + u32 size_dont_access_after_boot; u32 cursor; u8 body[0]; } __packed; @@ -35,6 +35,7 @@ struct cbmem_cons { #define OVERFLOW (1 << 31) static struct cbmem_cons __iomem *cbmem_console; +static u32 cbmem_console_size; /* * The cbmem_console structure is read again on every access because it may @@ -47,7 +48,7 @@ static ssize_t memconsole_coreboot_read(char *buf, loff_t pos, size_t count) { u32 cursor = cbmem_console->cursor & CURSOR_MASK; u32 flags = cbmem_console->cursor & ~CURSOR_MASK; - u32 size = cbmem_console->size; + u32 size = cbmem_console_size; struct seg { /* describes ring buffer segments in logical order */ u32 phys; /* physical offset from start of mem buffer */ u32 len; /* length of segment */ @@ -81,8 +82,10 @@ static int memconsole_coreboot_init(phys_addr_t physaddr) if (!tmp_cbmc) return -ENOMEM; + /* Read size only once to prevent overrun attack through /dev/mem. */ + cbmem_console_size = tmp_cbmc->size_dont_access_after_boot; cbmem_console = memremap(physaddr, - tmp_cbmc->size + sizeof(*cbmem_console), + cbmem_console_size + sizeof(*cbmem_console), MEMREMAP_WB); memunmap(tmp_cbmc); -- cgit v1.2.3 From 3eec6a1c0cf31b982cad560c16e19fdb1851ae91 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 23 May 2017 17:07:42 -0700 Subject: firmware: vpd: use kdtrndup when copying section key Instead of open-coding kstrndup with kzalloc + memcpy, let's use the helper. Signed-off-by: Dmitry Torokhov Reviewed-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/google/vpd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c index 1e7860f02f4f..8bd51eaededd 100644 --- a/drivers/firmware/google/vpd.c +++ b/drivers/firmware/google/vpd.c @@ -118,14 +118,13 @@ static int vpd_section_attrib_add(const u8 *key, s32 key_len, info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - info->key = kzalloc(key_len + 1, GFP_KERNEL); + + info->key = kstrndup(key, key_len, GFP_KERNEL); if (!info->key) { ret = -ENOMEM; goto free_info; } - memcpy(info->key, key, key_len); - sysfs_bin_attr_init(&info->bin_attr); info->bin_attr.attr.name = info->key; info->bin_attr.attr.mode = 0444; -- cgit v1.2.3 From 9920a33e3573a207cd49895080e2806134e5e56f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 23 May 2017 17:07:45 -0700 Subject: firmware: vpd: use kasprintf() when forming name of 'raw' attribute When creating name for the "raw" attribute, let's switch to using kaspeintf() instead of doing it by hand. Also make sure we handle errors. Signed-off-by: Dmitry Torokhov Reviewed-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/google/vpd.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c index 8bd51eaededd..66fd0230605e 100644 --- a/drivers/firmware/google/vpd.c +++ b/drivers/firmware/google/vpd.c @@ -190,8 +190,7 @@ static int vpd_section_create_attribs(struct vpd_section *sec) static int vpd_section_init(const char *name, struct vpd_section *sec, phys_addr_t physaddr, size_t size) { - int ret; - int raw_len; + int err; sec->baseaddr = memremap(physaddr, size, MEMREMAP_WB); if (!sec->baseaddr) @@ -200,10 +199,11 @@ static int vpd_section_init(const char *name, struct vpd_section *sec, sec->name = name; /* We want to export the raw partion with name ${name}_raw */ - raw_len = strlen(name) + 5; - sec->raw_name = kzalloc(raw_len, GFP_KERNEL); - strncpy(sec->raw_name, name, raw_len); - strncat(sec->raw_name, "_raw", raw_len); + sec->raw_name = kasprintf(GFP_KERNEL, "%s_raw", name); + if (!sec->raw_name) { + err = -ENOMEM; + goto err_iounmap; + } sysfs_bin_attr_init(&sec->bin_attr); sec->bin_attr.attr.name = sec->raw_name; @@ -212,14 +212,14 @@ static int vpd_section_init(const char *name, struct vpd_section *sec, sec->bin_attr.read = vpd_section_read; sec->bin_attr.private = sec; - ret = sysfs_create_bin_file(vpd_kobj, &sec->bin_attr); - if (ret) - goto free_sec; + err = sysfs_create_bin_file(vpd_kobj, &sec->bin_attr); + if (err) + goto err_free_raw_name; sec->kobj = kobject_create_and_add(name, vpd_kobj); if (!sec->kobj) { - ret = -EINVAL; - goto sysfs_remove; + err = -EINVAL; + goto err_sysfs_remove; } INIT_LIST_HEAD(&sec->attribs); @@ -229,14 +229,13 @@ static int vpd_section_init(const char *name, struct vpd_section *sec, return 0; -sysfs_remove: +err_sysfs_remove: sysfs_remove_bin_file(vpd_kobj, &sec->bin_attr); - -free_sec: +err_free_raw_name: kfree(sec->raw_name); +err_iounmap: iounmap(sec->baseaddr); - - return ret; + return err; } static int vpd_section_destroy(struct vpd_section *sec) -- cgit v1.2.3 From dd246486f94694edb86e898a24a61ebf2f2fdba4 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 23 May 2017 17:07:46 -0700 Subject: firmware: vpd: do not clear statically allocated data ro_vpd and rw_vpd are static module-scope variables that are guaranteed to be initialized with zeroes, there is no need for explicit memset(). Signed-off-by: Dmitry Torokhov Reviewed-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/google/vpd.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c index 66fd0230605e..4f8f99edbbfa 100644 --- a/drivers/firmware/google/vpd.c +++ b/drivers/firmware/google/vpd.c @@ -317,9 +317,6 @@ static int __init vpd_platform_init(void) if (!vpd_kobj) return -ENOMEM; - memset(&ro_vpd, 0, sizeof(ro_vpd)); - memset(&rw_vpd, 0, sizeof(rw_vpd)); - platform_driver_register(&vpd_driver); return 0; -- cgit v1.2.3 From 7975bd4cca05a99aa14964cfa22366ee64da50ad Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 23 May 2017 17:07:47 -0700 Subject: firmware: vpd: remove platform driver There is no reason why VPD should register platform device and driver, given that we do not use their respective kobjects to attach attributes, nor do we need suspend/resume hooks, or any other features of device core. Signed-off-by: Dmitry Torokhov Reviewed-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/google/vpd.c | 44 ++++++++++++++++--------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c index 4f8f99edbbfa..d28f62fed50f 100644 --- a/drivers/firmware/google/vpd.c +++ b/drivers/firmware/google/vpd.c @@ -22,8 +22,6 @@ #include #include #include -#include -#include #include #include @@ -279,47 +277,37 @@ static int vpd_sections_init(phys_addr_t physaddr) ret = vpd_section_init("rw", &rw_vpd, physaddr + sizeof(struct vpd_cbmem) + header.ro_size, header.rw_size); - if (ret) + if (ret) { + vpd_section_destroy(&ro_vpd); return ret; + } } return 0; } -static int vpd_probe(struct platform_device *pdev) -{ - int ret; - struct lb_cbmem_ref entry; - - ret = coreboot_table_find(CB_TAG_VPD, &entry, sizeof(entry)); - if (ret) - return ret; - - return vpd_sections_init(entry.cbmem_addr); -} - -static struct platform_driver vpd_driver = { - .probe = vpd_probe, - .driver = { - .name = "vpd", - }, -}; - static int __init vpd_platform_init(void) { - struct platform_device *pdev; - - pdev = platform_device_register_simple("vpd", -1, NULL, 0); - if (IS_ERR(pdev)) - return PTR_ERR(pdev); + struct lb_cbmem_ref entry; + int err; vpd_kobj = kobject_create_and_add("vpd", firmware_kobj); if (!vpd_kobj) return -ENOMEM; - platform_driver_register(&vpd_driver); + err = coreboot_table_find(CB_TAG_VPD, &entry, sizeof(entry)); + if (err) + goto err_kobject_put; + + err = vpd_sections_init(entry.cbmem_addr); + if (err) + goto err_kobject_put; return 0; + +err_kobject_put: + kobject_put(vpd_kobj); + return err; } static void __exit vpd_platform_exit(void) -- cgit v1.2.3 From e546d778d6bb3e1a80697a6556d870c707e6df82 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 18 May 2017 10:46:02 -0700 Subject: Drivers: hv: vmbus: Get the current time from the current clocksource The current code uses the MSR based mechanism to get the current tick. Use the current clock source as that might be more optimal. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/mshyperv.h | 1 - drivers/hv/hv.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index fba100713924..18325dcdb7f1 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -137,7 +137,6 @@ static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type) } } -#define hv_get_current_tick(tick) rdmsrl(HV_X64_MSR_TIME_REF_COUNT, tick) #define hv_init_timer(timer, tick) wrmsrl(timer, tick) #define hv_init_timer_config(config, val) wrmsrl(config, val) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 12e7baecb84e..61fc8ce169a5 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -96,7 +96,7 @@ static int hv_ce_set_next_event(unsigned long delta, WARN_ON(!clockevent_state_oneshot(evt)); - hv_get_current_tick(current_tick); + current_tick = hyperv_cs->read(NULL); current_tick += delta; hv_init_timer(HV_X64_MSR_STIMER0_COUNT, current_tick); return 0; -- cgit v1.2.3 From 4f9bac039a64f6306b613a0d90e6b7e75d7ab0c4 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Thu, 18 May 2017 10:46:03 -0700 Subject: hv_utils: drop .getcrosststamp() support from PTP driver Turns out that our implementation of .getcrosststamp() never actually worked. Hyper-V is sending time samples every 5 seconds and this is too much for get_device_system_crosststamp() as it's interpolation algorithm (which nobody is currently using in kernel, btw) accounts for a 'slow' device but we're not slow in Hyper-V, our time reference is too far away. .getcrosststamp() is not currently used, get_device_system_crosststamp() almost always returns -EINVAL and client falls back to using PTP_SYS_OFFSET so this patch doesn't change much. I also tried doing interpolation manually (e.g. the same way hv_ptp_gettime() works and it turns out that we're getting even lower quality: PTP_SYS_OFFSET_PRECISE with manual interpolation: * PHC0 0 3 37 4 -3974ns[-5338ns] +/- 977ns * PHC0 0 3 77 7 +2227ns[+3184ns] +/- 576ns * PHC0 0 3 177 10 +3060ns[+5220ns] +/- 548ns * PHC0 0 3 377 12 +3937ns[+4371ns] +/- 1414ns * PHC0 0 3 377 6 +764ns[+1240ns] +/- 1047ns * PHC0 0 3 377 7 -1210ns[-3731ns] +/- 479ns * PHC0 0 3 377 9 +153ns[-1019ns] +/- 406ns * PHC0 0 3 377 12 -872ns[-1793ns] +/- 443ns * PHC0 0 3 377 5 +701ns[+3599ns] +/- 426ns * PHC0 0 3 377 5 -923ns[ -375ns] +/- 1062ns PTP_SYS_OFFSET: * PHC0 0 3 7 5 +72ns[+8020ns] +/- 251ns * PHC0 0 3 17 5 -885ns[-3661ns] +/- 254ns * PHC0 0 3 37 6 -454ns[-5732ns] +/- 258ns * PHC0 0 3 77 10 +1183ns[+3754ns] +/- 164ns * PHC0 0 3 377 5 +579ns[+1137ns] +/- 110ns * PHC0 0 3 377 7 +501ns[+1064ns] +/- 96ns * PHC0 0 3 377 9 +1641ns[+3342ns] +/- 106ns * PHC0 0 3 377 8 -47ns[ +77ns] +/- 160ns * PHC0 0 3 377 5 +54ns[ +107ns] +/- 102ns * PHC0 0 3 377 8 -354ns[ -617ns] +/- 89ns This fact wasn't noticed during the initial testing of the PTP device somehow but got revealed now. Let's just drop .getcrosststamp() implementation for now as it doesn't seem to be suitable for us. Signed-off-by: Vitaly Kuznetsov Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/hv_util.c | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index 186b10083c55..2849143bf6f0 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c @@ -248,7 +248,6 @@ static struct adj_time_work wrk; static struct { u64 host_time; u64 ref_time; - struct system_time_snapshot snap; spinlock_t lock; } host_ts; @@ -281,7 +280,6 @@ static inline void adj_guesttime(u64 hosttime, u64 reftime, u8 adj_flags) cur_reftime = hyperv_cs->read(hyperv_cs); host_ts.host_time = hosttime; host_ts.ref_time = cur_reftime; - ktime_get_snapshot(&host_ts.snap); /* * TimeSync v4 messages contain reference time (guest's Hyper-V @@ -538,46 +536,12 @@ static int hv_ptp_gettime(struct ptp_clock_info *info, struct timespec64 *ts) return 0; } -static int hv_ptp_get_syncdevicetime(ktime_t *device, - struct system_counterval_t *system, - void *ctx) -{ - system->cs = hyperv_cs; - system->cycles = host_ts.ref_time; - *device = ns_to_ktime((host_ts.host_time - WLTIMEDELTA) * 100); - - return 0; -} - -static int hv_ptp_getcrosststamp(struct ptp_clock_info *ptp, - struct system_device_crosststamp *xtstamp) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&host_ts.lock, flags); - - /* - * host_ts contains the last time sample from the host and the snapshot - * of system time. We don't need to calculate the time delta between - * the reception and now as get_device_system_crosststamp() does the - * required interpolation. - */ - ret = get_device_system_crosststamp(hv_ptp_get_syncdevicetime, - NULL, &host_ts.snap, xtstamp); - - spin_unlock_irqrestore(&host_ts.lock, flags); - - return ret; -} - static struct ptp_clock_info ptp_hyperv_info = { .name = "hyperv", .enable = hv_ptp_enable, .adjtime = hv_ptp_adjtime, .adjfreq = hv_ptp_adjfreq, .gettime64 = hv_ptp_gettime, - .getcrosststamp = hv_ptp_getcrosststamp, .settime64 = hv_ptp_settime, .owner = THIS_MODULE, }; -- cgit v1.2.3 From 1d10602d306cb7f70545b5e1166efc9409e7d384 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Thu, 18 May 2017 10:46:04 -0700 Subject: hv_utils: fix TimeSync work on pre-TimeSync-v4 hosts It was found that ICTIMESYNCFLAG_SYNC packets are handled incorrectly on WS2012R2, e.g. after the guest is paused and resumed its time is set to something different from host's time. The problem is that we call adj_guesttime() with reftime=0 for these old hosts and we don't account for that in 'if (adj_flags & ICTIMESYNCFLAG_SYNC)' branch and hv_set_host_time(). While we could've solved this by adding a check like 'if (ts_srv_version > TS_VERSION_3)' to hv_set_host_time() I prefer to do some refactoring. We don't need to have two separate containers for host samples, struct host_ts which we use for PTP is enough. Throw away 'struct adj_time_work' and create hv_get_adj_host_time() accessor to host_ts to avoid code duplication. Fixes: 3716a49a81ba ("hv_utils: implement Hyper-V PTP source") Signed-off-by: Vitaly Kuznetsov Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/hv_util.c | 128 ++++++++++++++++++++++----------------------------- 1 file changed, 54 insertions(+), 74 deletions(-) diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index 2849143bf6f0..14dce25c104f 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c @@ -202,27 +202,39 @@ static void shutdown_onchannelcallback(void *context) /* * Set the host time in a process context. */ +static struct work_struct adj_time_work; -struct adj_time_work { - struct work_struct work; - u64 host_time; - u64 ref_time; - u8 flags; -}; +/* + * The last time sample, received from the host. PTP device responds to + * requests by using this data and the current partition-wide time reference + * count. + */ +static struct { + u64 host_time; + u64 ref_time; + spinlock_t lock; +} host_ts; -static void hv_set_host_time(struct work_struct *work) +static struct timespec64 hv_get_adj_host_time(void) { - struct adj_time_work *wrk; - struct timespec64 host_ts; - u64 reftime, newtime; - - wrk = container_of(work, struct adj_time_work, work); + struct timespec64 ts; + u64 newtime, reftime; + unsigned long flags; + spin_lock_irqsave(&host_ts.lock, flags); reftime = hyperv_cs->read(hyperv_cs); - newtime = wrk->host_time + (reftime - wrk->ref_time); - host_ts = ns_to_timespec64((newtime - WLTIMEDELTA) * 100); + newtime = host_ts.host_time + (reftime - host_ts.ref_time); + ts = ns_to_timespec64((newtime - WLTIMEDELTA) * 100); + spin_unlock_irqrestore(&host_ts.lock, flags); - do_settimeofday64(&host_ts); + return ts; +} + +static void hv_set_host_time(struct work_struct *work) +{ + struct timespec64 ts = hv_get_adj_host_time(); + + do_settimeofday64(&ts); } /* @@ -238,60 +250,35 @@ static void hv_set_host_time(struct work_struct *work) * typically used as a hint to the guest. The guest is under no obligation * to discipline the clock. */ -static struct adj_time_work wrk; - -/* - * The last time sample, received from the host. PTP device responds to - * requests by using this data and the current partition-wide time reference - * count. - */ -static struct { - u64 host_time; - u64 ref_time; - spinlock_t lock; -} host_ts; - static inline void adj_guesttime(u64 hosttime, u64 reftime, u8 adj_flags) { unsigned long flags; u64 cur_reftime; /* - * This check is safe since we are executing in the - * interrupt context and time synch messages are always - * delivered on the same CPU. + * Save the adjusted time sample from the host and the snapshot + * of the current system time. */ - if (adj_flags & ICTIMESYNCFLAG_SYNC) { - /* Queue a job to do do_settimeofday64() */ - if (work_pending(&wrk.work)) - return; - - wrk.host_time = hosttime; - wrk.ref_time = reftime; - wrk.flags = adj_flags; - schedule_work(&wrk.work); - } else { - /* - * Save the adjusted time sample from the host and the snapshot - * of the current system time for PTP device. - */ - spin_lock_irqsave(&host_ts.lock, flags); - - cur_reftime = hyperv_cs->read(hyperv_cs); - host_ts.host_time = hosttime; - host_ts.ref_time = cur_reftime; - - /* - * TimeSync v4 messages contain reference time (guest's Hyper-V - * clocksource read when the time sample was generated), we can - * improve the precision by adding the delta between now and the - * time of generation. - */ - if (ts_srv_version > TS_VERSION_3) - host_ts.host_time += (cur_reftime - reftime); - - spin_unlock_irqrestore(&host_ts.lock, flags); - } + spin_lock_irqsave(&host_ts.lock, flags); + + cur_reftime = hyperv_cs->read(hyperv_cs); + host_ts.host_time = hosttime; + host_ts.ref_time = cur_reftime; + + /* + * TimeSync v4 messages contain reference time (guest's Hyper-V + * clocksource read when the time sample was generated), we can + * improve the precision by adding the delta between now and the + * time of generation. For older protocols we set + * reftime == cur_reftime on call. + */ + host_ts.host_time += (cur_reftime - reftime); + + spin_unlock_irqrestore(&host_ts.lock, flags); + + /* Schedule work to do do_settimeofday64() */ + if (adj_flags & ICTIMESYNCFLAG_SYNC) + schedule_work(&adj_time_work); } /* @@ -339,8 +326,8 @@ static void timesync_onchannelcallback(void *context) sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; adj_guesttime(timedatap->parenttime, - 0, - timedatap->flags); + hyperv_cs->read(hyperv_cs), + timedatap->flags); } } @@ -524,14 +511,7 @@ static int hv_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) static int hv_ptp_gettime(struct ptp_clock_info *info, struct timespec64 *ts) { - unsigned long flags; - u64 newtime, reftime; - - spin_lock_irqsave(&host_ts.lock, flags); - reftime = hyperv_cs->read(hyperv_cs); - newtime = host_ts.host_time + (reftime - host_ts.ref_time); - *ts = ns_to_timespec64((newtime - WLTIMEDELTA) * 100); - spin_unlock_irqrestore(&host_ts.lock, flags); + *ts = hv_get_adj_host_time(); return 0; } @@ -556,7 +536,7 @@ static int hv_timesync_init(struct hv_util_service *srv) spin_lock_init(&host_ts.lock); - INIT_WORK(&wrk.work, hv_set_host_time); + INIT_WORK(&adj_time_work, hv_set_host_time); /* * ptp_clock_register() returns NULL when CONFIG_PTP_1588_CLOCK is @@ -577,7 +557,7 @@ static void hv_timesync_deinit(void) { if (hv_ptp_clock) ptp_clock_unregister(hv_ptp_clock); - cancel_work_sync(&wrk.work); + cancel_work_sync(&adj_time_work); } static int __init init_hyperv_utils(void) -- cgit v1.2.3 From e917a5e23a87e24931625c344daea834cd2d6f2f Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 18 May 2017 10:46:05 -0700 Subject: drivers: hv: vmbus: Increase the time between retries in vmbus_post_msg() Commit c0bb03924f1a ("Drivers: hv: vmbus: Raise retry/wait limits in vmbus_post_msg()") increased the retry/wait limits of vmbus_post_msg() to address the new DoS protection policies in WS2016. Increase the time between retries to make the code more robust. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index c2d74ee95f60..59c11ff90d12 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -390,7 +390,7 @@ int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep) else mdelay(usec / 1000); - if (usec < 256000) + if (retries < 22) usec *= 2; } return ret; -- cgit v1.2.3 From 3110010896f17f381bd74d72b9d4a46a087c46b8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 18 May 2017 10:46:06 -0700 Subject: vmbus: Reuse uuid_le_to_bin() helper Instead of open coded variant use generic helper to convert UUID strings to binary format. Signed-off-by: Andy Shevchenko Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/vmbus_drv.c | 51 ++++++++++---------------------------------------- 1 file changed, 10 insertions(+), 41 deletions(-) diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 59bb3efa6e10..ed84e96715a0 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -608,40 +608,6 @@ static void vmbus_free_dynids(struct hv_driver *drv) spin_unlock(&drv->dynids.lock); } -/* Parse string of form: 1b4e28ba-2fa1-11d2-883f-b9a761bde3f */ -static int get_uuid_le(const char *str, uuid_le *uu) -{ - unsigned int b[16]; - int i; - - if (strlen(str) < 37) - return -1; - - for (i = 0; i < 36; i++) { - switch (i) { - case 8: case 13: case 18: case 23: - if (str[i] != '-') - return -1; - break; - default: - if (!isxdigit(str[i])) - return -1; - } - } - - /* unparse little endian output byte order */ - if (sscanf(str, - "%2x%2x%2x%2x-%2x%2x-%2x%2x-%2x%2x-%2x%2x%2x%2x%2x%2x", - &b[3], &b[2], &b[1], &b[0], - &b[5], &b[4], &b[7], &b[6], &b[8], &b[9], - &b[10], &b[11], &b[12], &b[13], &b[14], &b[15]) != 16) - return -1; - - for (i = 0; i < 16; i++) - uu->b[i] = b[i]; - return 0; -} - /* * store_new_id - sysfs frontend to vmbus_add_dynid() * @@ -651,11 +617,12 @@ static ssize_t new_id_store(struct device_driver *driver, const char *buf, size_t count) { struct hv_driver *drv = drv_to_hv_drv(driver); - uuid_le guid = NULL_UUID_LE; + uuid_le guid; ssize_t retval; - if (get_uuid_le(buf, &guid) != 0) - return -EINVAL; + retval = uuid_le_to_bin(buf, &guid); + if (retval) + return retval; if (hv_vmbus_get_id(drv, &guid)) return -EEXIST; @@ -677,12 +644,14 @@ static ssize_t remove_id_store(struct device_driver *driver, const char *buf, { struct hv_driver *drv = drv_to_hv_drv(driver); struct vmbus_dynid *dynid, *n; - uuid_le guid = NULL_UUID_LE; - size_t retval = -ENODEV; + uuid_le guid; + ssize_t retval; - if (get_uuid_le(buf, &guid)) - return -EINVAL; + retval = uuid_le_to_bin(buf, &guid); + if (retval) + return retval; + retval = -ENODEV; spin_lock(&drv->dynids.lock); list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) { struct hv_vmbus_device_id *id = &dynid->id; -- cgit v1.2.3 From 13b9abfc92be7c4454bff912021b9f835dea6e15 Mon Sep 17 00:00:00 2001 From: Michael Kelley Date: Thu, 18 May 2017 10:46:07 -0700 Subject: Drivers: hv: vmbus: Close timing hole that can corrupt per-cpu page Extend the disabling of preemption to include the hypercall so that another thread can't get the CPU and corrupt the per-cpu page used for hypercall arguments. Cc: #4.11 Signed-off-by: Michael Kelley Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/hv.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 61fc8ce169a5..2ea12207caa0 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -82,10 +82,15 @@ int hv_post_message(union hv_connection_id connection_id, aligned_msg->message_type = message_type; aligned_msg->payload_size = payload_size; memcpy((void *)aligned_msg->payload, payload, payload_size); - put_cpu_ptr(hv_cpu); status = hv_do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL); + /* Preemption must remain disabled until after the hypercall + * so some other thread can't get scheduled onto this cpu and + * corrupt the per-cpu post_msg_page + */ + put_cpu_ptr(hv_cpu); + return status & 0xFFFF; } -- cgit v1.2.3 From 50fa2951bd744d2a82aa33074001efac12d4e1cf Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Tue, 16 May 2017 15:02:12 -0500 Subject: w1: Organize driver source to natural/common order Structures and functions should be ordered such that forward declaration use is minimized. MODULE_* macros should immediately follow the structures and functions upon which they act. Remaining MODULE_* macros should be at the end of the file in alphabetical order. Signed-off-by: Andrew F. Davis Acked-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/masters/ds2482.c | 45 ++++++++++++++------------------- drivers/w1/masters/ds2490.c | 33 ++++++++++-------------- drivers/w1/masters/matrox_w1.c | 40 +++++++++++++---------------- drivers/w1/masters/omap_hdq.c | 57 ++++++++++++++++++------------------------ drivers/w1/slaves/w1_bq27000.c | 9 +++---- drivers/w1/slaves/w1_ds2406.c | 8 +++--- drivers/w1/slaves/w1_ds2408.c | 11 ++++---- drivers/w1/slaves/w1_ds2413.c | 10 ++++---- drivers/w1/slaves/w1_ds2423.c | 2 +- drivers/w1/slaves/w1_ds2431.c | 2 +- drivers/w1/slaves/w1_ds2433.c | 10 ++++---- drivers/w1/slaves/w1_ds2760.c | 11 ++++---- drivers/w1/slaves/w1_ds2780.c | 2 +- drivers/w1/slaves/w1_ds2781.c | 2 +- drivers/w1/slaves/w1_ds28e04.c | 10 ++++---- drivers/w1/slaves/w1_smem.c | 12 ++++----- drivers/w1/slaves/w1_therm.c | 18 ++++++------- drivers/w1/w1.c | 18 +++++++------ drivers/w1/w1_family.c | 5 ++-- drivers/w1/w1_int.c | 3 +-- 20 files changed, 138 insertions(+), 170 deletions(-) diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c index 2e30db1b1a43..e8730ea3e3aa 100644 --- a/drivers/w1/masters/ds2482.c +++ b/drivers/w1/masters/ds2482.c @@ -35,6 +35,8 @@ */ static int ds2482_active_pullup = 1; module_param_named(active_pullup, ds2482_active_pullup, int, 0644); +MODULE_PARM_DESC(active_pullup, "Active pullup (apply to all buses): " \ + "0-disable, 1-enable (default)"); /** * The DS2482 registers - there are 3 registers that are addressed by a read @@ -93,30 +95,6 @@ static const u8 ds2482_chan_rd[8] = #define DS2482_REG_STS_PPD 0x02 #define DS2482_REG_STS_1WB 0x01 - -static int ds2482_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int ds2482_remove(struct i2c_client *client); - - -/** - * Driver data (common to all clients) - */ -static const struct i2c_device_id ds2482_id[] = { - { "ds2482", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ds2482_id); - -static struct i2c_driver ds2482_driver = { - .driver = { - .name = "ds2482", - }, - .probe = ds2482_probe, - .remove = ds2482_remove, - .id_table = ds2482_id, -}; - /* * Client data (each client gets its own) */ @@ -560,10 +538,25 @@ static int ds2482_remove(struct i2c_client *client) return 0; } +/** + * Driver data (common to all clients) + */ +static const struct i2c_device_id ds2482_id[] = { + { "ds2482", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ds2482_id); + +static struct i2c_driver ds2482_driver = { + .driver = { + .name = "ds2482", + }, + .probe = ds2482_probe, + .remove = ds2482_remove, + .id_table = ds2482_id, +}; module_i2c_driver(ds2482_driver); -MODULE_PARM_DESC(active_pullup, "Active pullup (apply to all buses): " \ - "0-disable, 1-enable (default)"); MODULE_AUTHOR("Ben Gardner "); MODULE_DESCRIPTION("DS2482 driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c index be77b7914fad..d748e34d4ce5 100644 --- a/drivers/w1/masters/ds2490.c +++ b/drivers/w1/masters/ds2490.c @@ -179,28 +179,9 @@ struct ds_status u8 reserved2; }; -static struct usb_device_id ds_id_table [] = { - { USB_DEVICE(0x04fa, 0x2490) }, - { }, -}; -MODULE_DEVICE_TABLE(usb, ds_id_table); - -static int ds_probe(struct usb_interface *, const struct usb_device_id *); -static void ds_disconnect(struct usb_interface *); - -static int ds_send_control(struct ds_device *, u16, u16); -static int ds_send_control_cmd(struct ds_device *, u16, u16); - static LIST_HEAD(ds_devices); static DEFINE_MUTEX(ds_mutex); -static struct usb_driver ds_driver = { - .name = "DS9490R", - .probe = ds_probe, - .disconnect = ds_disconnect, - .id_table = ds_id_table, -}; - static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index) { int err; @@ -1108,8 +1089,20 @@ static void ds_disconnect(struct usb_interface *intf) kfree(dev); } +static struct usb_device_id ds_id_table [] = { + { USB_DEVICE(0x04fa, 0x2490) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, ds_id_table); + +static struct usb_driver ds_driver = { + .name = "DS9490R", + .probe = ds_probe, + .disconnect = ds_disconnect, + .id_table = ds_id_table, +}; module_usb_driver(ds_driver); -MODULE_LICENSE("GPL"); MODULE_AUTHOR("Evgeniy Polyakov "); MODULE_DESCRIPTION("DS2490 USB <-> W1 bus master driver (DS9490*)"); +MODULE_LICENSE("GPL"); diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c index 97a676bf5989..f20d03ecfd1d 100644 --- a/drivers/w1/masters/matrox_w1.c +++ b/drivers/w1/masters/matrox_w1.c @@ -37,26 +37,6 @@ #include "../w1.h" #include "../w1_int.h" -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Evgeniy Polyakov "); -MODULE_DESCRIPTION("Driver for transport(Dallas 1-wire protocol) over VGA DDC(matrox gpio)."); - -static struct pci_device_id matrox_w1_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400) }, - { }, -}; -MODULE_DEVICE_TABLE(pci, matrox_w1_tbl); - -static int matrox_w1_probe(struct pci_dev *, const struct pci_device_id *); -static void matrox_w1_remove(struct pci_dev *); - -static struct pci_driver matrox_w1_pci_driver = { - .name = "matrox_w1", - .id_table = matrox_w1_tbl, - .probe = matrox_w1_probe, - .remove = matrox_w1_remove, -}; - /* * Matrox G400 DDC registers. */ @@ -88,9 +68,6 @@ struct matrox_device struct w1_bus_master *bus_master; }; -static u8 matrox_w1_read_ddc_bit(void *); -static void matrox_w1_write_ddc_bit(void *, u8); - /* * These functions read and write DDC Data bit. * @@ -226,4 +203,21 @@ static void matrox_w1_remove(struct pci_dev *pdev) } kfree(dev); } + +static struct pci_device_id matrox_w1_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400) }, + { }, +}; +MODULE_DEVICE_TABLE(pci, matrox_w1_tbl); + +static struct pci_driver matrox_w1_pci_driver = { + .name = "matrox_w1", + .id_table = matrox_w1_tbl, + .probe = matrox_w1_probe, + .remove = matrox_w1_remove, +}; module_pci_driver(matrox_w1_pci_driver); + +MODULE_AUTHOR("Evgeniy Polyakov "); +MODULE_DESCRIPTION("Driver for transport(Dallas 1-wire protocol) over VGA DDC(matrox gpio)."); +MODULE_LICENSE("GPL"); diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c index fb190c259607..3302cbd2344a 100644 --- a/drivers/w1/masters/omap_hdq.c +++ b/drivers/w1/masters/omap_hdq.c @@ -53,7 +53,10 @@ #define OMAP_HDQ_MAX_USER 4 static DECLARE_WAIT_QUEUE_HEAD(hdq_wait_queue); + static int w1_id; +module_param(w1_id, int, S_IRUSR); +MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection in HDQ mode"); struct hdq_data { struct device *dev; @@ -76,36 +79,6 @@ struct hdq_data { }; -static int omap_hdq_probe(struct platform_device *pdev); -static int omap_hdq_remove(struct platform_device *pdev); - -static const struct of_device_id omap_hdq_dt_ids[] = { - { .compatible = "ti,omap3-1w" }, - { .compatible = "ti,am4372-hdq" }, - {} -}; -MODULE_DEVICE_TABLE(of, omap_hdq_dt_ids); - -static struct platform_driver omap_hdq_driver = { - .probe = omap_hdq_probe, - .remove = omap_hdq_remove, - .driver = { - .name = "omap_hdq", - .of_match_table = omap_hdq_dt_ids, - }, -}; - -static u8 omap_w1_read_byte(void *_hdq); -static void omap_w1_write_byte(void *_hdq, u8 byte); -static u8 omap_w1_reset_bus(void *_hdq); - - -static struct w1_bus_master omap_w1_master = { - .read_byte = omap_w1_read_byte, - .write_byte = omap_w1_write_byte, - .reset_bus = omap_w1_reset_bus, -}; - /* HDQ register I/O routines */ static inline u8 hdq_reg_in(struct hdq_data *hdq_data, u32 offset) { @@ -678,6 +651,12 @@ static void omap_w1_write_byte(void *_hdq, u8 byte) } } +static struct w1_bus_master omap_w1_master = { + .read_byte = omap_w1_read_byte, + .write_byte = omap_w1_write_byte, + .reset_bus = omap_w1_reset_bus, +}; + static int omap_hdq_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -787,10 +766,22 @@ static int omap_hdq_remove(struct platform_device *pdev) return 0; } -module_platform_driver(omap_hdq_driver); +static const struct of_device_id omap_hdq_dt_ids[] = { + { .compatible = "ti,omap3-1w" }, + { .compatible = "ti,am4372-hdq" }, + {} +}; +MODULE_DEVICE_TABLE(of, omap_hdq_dt_ids); -module_param(w1_id, int, S_IRUSR); -MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection in HDQ mode"); +static struct platform_driver omap_hdq_driver = { + .probe = omap_hdq_probe, + .remove = omap_hdq_remove, + .driver = { + .name = "omap_hdq", + .of_match_table = omap_hdq_dt_ids, + }, +}; +module_platform_driver(omap_hdq_driver); MODULE_AUTHOR("Texas Instruments"); MODULE_DESCRIPTION("HDQ-1W driver Library"); diff --git a/drivers/w1/slaves/w1_bq27000.c b/drivers/w1/slaves/w1_bq27000.c index 9f4a86b754ba..d480900a28ab 100644 --- a/drivers/w1/slaves/w1_bq27000.c +++ b/drivers/w1/slaves/w1_bq27000.c @@ -25,6 +25,8 @@ #define HDQ_CMD_WRITE (1<<7) static int F_ID; +module_param(F_ID, int, S_IRUSR); +MODULE_PARM_DESC(F_ID, "1-wire slave FID for BQ device"); static int w1_bq27000_read(struct device *dev, unsigned int reg) { @@ -106,13 +108,10 @@ static void __exit w1_bq27000_exit(void) w1_unregister_family(&w1_bq27000_family); } - module_init(w1_bq27000_init); module_exit(w1_bq27000_exit); -module_param(F_ID, int, S_IRUSR); -MODULE_PARM_DESC(F_ID, "1-wire slave FID for BQ device"); -MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_BQ27000)); -MODULE_LICENSE("GPL"); MODULE_AUTHOR("Texas Instruments Ltd"); MODULE_DESCRIPTION("HDQ/1-wire slave driver bq27000 battery monitor chip"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_BQ27000)); diff --git a/drivers/w1/slaves/w1_ds2406.c b/drivers/w1/slaves/w1_ds2406.c index 51f2f66d6555..709bd5e02eed 100644 --- a/drivers/w1/slaves/w1_ds2406.c +++ b/drivers/w1/slaves/w1_ds2406.c @@ -21,10 +21,6 @@ #include "../w1_int.h" #include "../w1_family.h" -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Scott Alfter "); -MODULE_DESCRIPTION("w1 family 12 driver for DS2406 2 Pin IO"); - #define W1_F12_FUNC_READ_STATUS 0xAA #define W1_F12_FUNC_WRITE_STATUS 0x55 @@ -154,3 +150,7 @@ static struct w1_family w1_family_12 = { .fops = &w1_f12_fops, }; module_w1_family(w1_family_12); + +MODULE_AUTHOR("Scott Alfter "); +MODULE_DESCRIPTION("w1 family 12 driver for DS2406 2 Pin IO"); +MODULE_LICENSE("GPL"); diff --git a/drivers/w1/slaves/w1_ds2408.c b/drivers/w1/slaves/w1_ds2408.c index aec5958e66e9..e01d2b3997bc 100644 --- a/drivers/w1/slaves/w1_ds2408.c +++ b/drivers/w1/slaves/w1_ds2408.c @@ -19,12 +19,6 @@ #include "../w1_int.h" #include "../w1_family.h" -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jean-Francois Dagenais "); -MODULE_DESCRIPTION("w1 family 29 driver for DS2408 8 Pin IO"); -MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2408)); - - #define W1_F29_RETRIES 3 #define W1_F29_REG_LOGIG_STATE 0x88 /* R */ @@ -352,3 +346,8 @@ static struct w1_family w1_family_29 = { .fops = &w1_f29_fops, }; module_w1_family(w1_family_29); + +MODULE_AUTHOR("Jean-Francois Dagenais "); +MODULE_DESCRIPTION("w1 family 29 driver for DS2408 8 Pin IO"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2408)); diff --git a/drivers/w1/slaves/w1_ds2413.c b/drivers/w1/slaves/w1_ds2413.c index f2e1c51533b9..9cc6f0bc2e95 100644 --- a/drivers/w1/slaves/w1_ds2413.c +++ b/drivers/w1/slaves/w1_ds2413.c @@ -20,11 +20,6 @@ #include "../w1_int.h" #include "../w1_family.h" -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mariusz Bialonczyk "); -MODULE_DESCRIPTION("w1 family 3a driver for DS2413 2 Pin IO"); -MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2413)); - #define W1_F3A_RETRIES 3 #define W1_F3A_FUNC_PIO_ACCESS_READ 0xF5 #define W1_F3A_FUNC_PIO_ACCESS_WRITE 0x5A @@ -136,3 +131,8 @@ static struct w1_family w1_family_3a = { .fops = &w1_f3a_fops, }; module_w1_family(w1_family_3a); + +MODULE_AUTHOR("Mariusz Bialonczyk "); +MODULE_DESCRIPTION("w1 family 3a driver for DS2413 2 Pin IO"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2413)); diff --git a/drivers/w1/slaves/w1_ds2423.c b/drivers/w1/slaves/w1_ds2423.c index 4ab54fd9dde2..306240fe496c 100644 --- a/drivers/w1/slaves/w1_ds2423.c +++ b/drivers/w1/slaves/w1_ds2423.c @@ -140,7 +140,7 @@ static struct w1_family w1_family_1d = { }; module_w1_family(w1_family_1d); -MODULE_LICENSE("GPL"); MODULE_AUTHOR("Mika Laitio "); MODULE_DESCRIPTION("w1 family 1d driver for DS2423, 4 counters and 4kb ram"); +MODULE_LICENSE("GPL"); MODULE_ALIAS("w1-family-" __stringify(W1_COUNTER_DS2423)); diff --git a/drivers/w1/slaves/w1_ds2431.c b/drivers/w1/slaves/w1_ds2431.c index 80572cb63ba8..20182d4a4b19 100644 --- a/drivers/w1/slaves/w1_ds2431.c +++ b/drivers/w1/slaves/w1_ds2431.c @@ -290,7 +290,7 @@ static struct w1_family w1_family_2d = { }; module_w1_family(w1_family_2d); -MODULE_LICENSE("GPL"); MODULE_AUTHOR("Bernhard Weirich "); MODULE_DESCRIPTION("w1 family 2d driver for DS2431, 1kb EEPROM"); +MODULE_LICENSE("GPL"); MODULE_ALIAS("w1-family-" __stringify(W1_EEPROM_DS2431)); diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c index 6cf378c89ecb..86c30aceea3e 100644 --- a/drivers/w1/slaves/w1_ds2433.c +++ b/drivers/w1/slaves/w1_ds2433.c @@ -26,11 +26,6 @@ #include "../w1_int.h" #include "../w1_family.h" -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Ben Gardner "); -MODULE_DESCRIPTION("w1 family 23 driver for DS2433, 4kb EEPROM"); -MODULE_ALIAS("w1-family-" __stringify(W1_EEPROM_DS2433)); - #define W1_EEPROM_SIZE 512 #define W1_PAGE_COUNT 16 #define W1_PAGE_SIZE 32 @@ -306,3 +301,8 @@ static struct w1_family w1_family_23 = { .fops = &w1_f23_fops, }; module_w1_family(w1_family_23); + +MODULE_AUTHOR("Ben Gardner "); +MODULE_DESCRIPTION("w1 family 23 driver for DS2433, 4kb EEPROM"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("w1-family-" __stringify(W1_EEPROM_DS2433)); diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c index ffa37f773b3b..f35d1e2ef9bb 100644 --- a/drivers/w1/slaves/w1_ds2760.c +++ b/drivers/w1/slaves/w1_ds2760.c @@ -63,11 +63,13 @@ int w1_ds2760_read(struct device *dev, char *buf, int addr, size_t count) { return w1_ds2760_io(dev, buf, addr, count, 0); } +EXPORT_SYMBOL(w1_ds2760_read); int w1_ds2760_write(struct device *dev, char *buf, int addr, size_t count) { return w1_ds2760_io(dev, buf, addr, count, 1); } +EXPORT_SYMBOL(w1_ds2760_write); static int w1_ds2760_eeprom_cmd(struct device *dev, int addr, int cmd) { @@ -91,11 +93,13 @@ int w1_ds2760_store_eeprom(struct device *dev, int addr) { return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_COPY_DATA); } +EXPORT_SYMBOL(w1_ds2760_store_eeprom); int w1_ds2760_recall_eeprom(struct device *dev, int addr) { return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_RECALL_DATA); } +EXPORT_SYMBOL(w1_ds2760_recall_eeprom); static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, @@ -164,12 +168,7 @@ static struct w1_family w1_ds2760_family = { }; module_w1_family(w1_ds2760_family); -EXPORT_SYMBOL(w1_ds2760_read); -EXPORT_SYMBOL(w1_ds2760_write); -EXPORT_SYMBOL(w1_ds2760_store_eeprom); -EXPORT_SYMBOL(w1_ds2760_recall_eeprom); - -MODULE_LICENSE("GPL"); MODULE_AUTHOR("Szabolcs Gyurko "); MODULE_DESCRIPTION("1-wire Driver Dallas 2760 battery monitor chip"); +MODULE_LICENSE("GPL"); MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2760)); diff --git a/drivers/w1/slaves/w1_ds2780.c b/drivers/w1/slaves/w1_ds2780.c index f5c2aa429a92..292972212107 100644 --- a/drivers/w1/slaves/w1_ds2780.c +++ b/drivers/w1/slaves/w1_ds2780.c @@ -156,7 +156,7 @@ static struct w1_family w1_ds2780_family = { }; module_w1_family(w1_ds2780_family); -MODULE_LICENSE("GPL"); MODULE_AUTHOR("Clifton Barnes "); MODULE_DESCRIPTION("1-wire Driver for Maxim/Dallas DS2780 Stand-Alone Fuel Gauge IC"); +MODULE_LICENSE("GPL"); MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2780)); diff --git a/drivers/w1/slaves/w1_ds2781.c b/drivers/w1/slaves/w1_ds2781.c index 9c03e014cf9e..a5d75067b230 100644 --- a/drivers/w1/slaves/w1_ds2781.c +++ b/drivers/w1/slaves/w1_ds2781.c @@ -153,7 +153,7 @@ static struct w1_family w1_ds2781_family = { }; module_w1_family(w1_ds2781_family); -MODULE_LICENSE("GPL"); MODULE_AUTHOR("Renata Sayakhova "); MODULE_DESCRIPTION("1-wire Driver for Maxim/Dallas DS2781 Stand-Alone Fuel Gauge IC"); +MODULE_LICENSE("GPL"); MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2781)); diff --git a/drivers/w1/slaves/w1_ds28e04.c b/drivers/w1/slaves/w1_ds28e04.c index 5e348d38ec5c..c62858c05e8f 100644 --- a/drivers/w1/slaves/w1_ds28e04.c +++ b/drivers/w1/slaves/w1_ds28e04.c @@ -24,11 +24,6 @@ #include "../w1_int.h" #include "../w1_family.h" -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Markus Franke , "); -MODULE_DESCRIPTION("w1 family 1C driver for DS28E04, 4kb EEPROM and PIO"); -MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS28E04)); - /* Allow the strong pullup to be disabled, but default to enabled. * If it was disabled a parasite powered device might not get the required * current to copy the data from the scratchpad to EEPROM. If it is enabled @@ -428,3 +423,8 @@ static struct w1_family w1_family_1C = { .fops = &w1_f1C_fops, }; module_w1_family(w1_family_1C); + +MODULE_AUTHOR("Markus Franke , "); +MODULE_DESCRIPTION("w1 family 1C driver for DS28E04, 4kb EEPROM and PIO"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS28E04)); diff --git a/drivers/w1/slaves/w1_smem.c b/drivers/w1/slaves/w1_smem.c index ed4c87506def..99b03bfb9941 100644 --- a/drivers/w1/slaves/w1_smem.c +++ b/drivers/w1/slaves/w1_smem.c @@ -31,12 +31,6 @@ #include "../w1_int.h" #include "../w1_family.h" -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Evgeniy Polyakov "); -MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family."); -MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_SMEM_01)); -MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_SMEM_81)); - static struct w1_family w1_smem_family_01 = { .fid = W1_FAMILY_SMEM_01, }; @@ -70,3 +64,9 @@ static void __exit w1_smem_fini(void) module_init(w1_smem_init); module_exit(w1_smem_fini); + +MODULE_AUTHOR("Evgeniy Polyakov "); +MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family."); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_SMEM_01)); +MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_SMEM_81)); diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index 82611f197b0a..ccaf29994a42 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c @@ -34,15 +34,6 @@ #include "../w1_int.h" #include "../w1_family.h" -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Evgeniy Polyakov "); -MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family."); -MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS18S20)); -MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS1822)); -MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS18B20)); -MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS1825)); -MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS28EA00)); - /* Allow the strong pullup to be disabled, but default to enabled. * If it was disabled a parasite powered device might not get the require * current to do a temperature conversion. If it is enabled parasite powered @@ -646,3 +637,12 @@ static void __exit w1_therm_fini(void) module_init(w1_therm_init); module_exit(w1_therm_fini); + +MODULE_AUTHOR("Evgeniy Polyakov "); +MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family."); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS18S20)); +MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS1822)); +MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS18B20)); +MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS1825)); +MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS28EA00)); diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 8511d1685db9..8172dee5e23c 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -33,20 +33,15 @@ #include "w1_family.h" #include "w1_netlink.h" -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Evgeniy Polyakov "); -MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol."); - static int w1_timeout = 10; -static int w1_timeout_us = 0; -int w1_max_slave_count = 64; -int w1_max_slave_ttl = 10; - module_param_named(timeout, w1_timeout, int, 0); MODULE_PARM_DESC(timeout, "time in seconds between automatic slave searches"); + +static int w1_timeout_us = 0; module_param_named(timeout_us, w1_timeout_us, int, 0); MODULE_PARM_DESC(timeout_us, "time in microseconds between automatic slave searches"); + /* A search stops when w1_max_slave_count devices have been found in that * search. The next search will start over and detect the same set of devices * on a static 1-wire bus. Memory is not allocated based on this number, just @@ -55,9 +50,12 @@ MODULE_PARM_DESC(timeout_us, * device on the network and w1_max_slave_count is set to 1, the device id can * be read directly skipping the normal slower search process. */ +int w1_max_slave_count = 64; module_param_named(max_slave_count, w1_max_slave_count, int, 0); MODULE_PARM_DESC(max_slave_count, "maximum number of slaves detected in a search"); + +int w1_max_slave_ttl = 10; module_param_named(slave_ttl, w1_max_slave_ttl, int, 0); MODULE_PARM_DESC(slave_ttl, "Number of searches not seeing a slave before it will be removed"); @@ -1228,3 +1226,7 @@ static void __exit w1_fini(void) module_init(w1_init); module_exit(w1_fini); + +MODULE_AUTHOR("Evgeniy Polyakov "); +MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol."); +MODULE_LICENSE("GPL"); diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c index 2096f460498f..9759cdaf22f4 100644 --- a/drivers/w1/w1_family.c +++ b/drivers/w1/w1_family.c @@ -55,6 +55,7 @@ int w1_register_family(struct w1_family *newf) return ret; } +EXPORT_SYMBOL(w1_register_family); /** * w1_unregister_family() - unregister a device family driver @@ -87,6 +88,7 @@ void w1_unregister_family(struct w1_family *fent) flush_signals(current); } } +EXPORT_SYMBOL(w1_unregister_family); /* * Should be called under w1_flock held. @@ -136,6 +138,3 @@ void __w1_family_get(struct w1_family *f) atomic_inc(&f->refcnt); smp_mb__after_atomic(); } - -EXPORT_SYMBOL(w1_unregister_family); -EXPORT_SYMBOL(w1_register_family); diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index 1072a2e620bb..4439d10709bb 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c @@ -179,6 +179,7 @@ err_out_free_dev: return retval; } +EXPORT_SYMBOL(w1_add_master_device); void __w1_remove_master_device(struct w1_master *dev) { @@ -251,6 +252,4 @@ void w1_remove_master_device(struct w1_bus_master *bm) __w1_remove_master_device(found); } - -EXPORT_SYMBOL(w1_add_master_device); EXPORT_SYMBOL(w1_remove_master_device); -- cgit v1.2.3 From 8bb2d27f837d72f247bfa341a5ccf2d54d2b7d2d Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 30 Apr 2017 13:12:10 +0300 Subject: mei: make mei_cl_bus_rescan static mei_cl_bus_rescan is used only in bus.c, so make it local to the file and mark static. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 2 +- drivers/misc/mei/mei_dev.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index d1928fdd0f43..42078e6be47f 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -1038,7 +1038,7 @@ static void mei_cl_bus_dev_init(struct mei_device *bus, * * @bus: mei device */ -void mei_cl_bus_rescan(struct mei_device *bus) +static void mei_cl_bus_rescan(struct mei_device *bus) { struct mei_cl_device *cldev, *n; struct mei_me_client *me_cl; diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 63a67c99fc78..ebcd5132e447 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -306,7 +306,6 @@ struct mei_hw_ops { }; /* MEI bus API*/ -void mei_cl_bus_rescan(struct mei_device *bus); void mei_cl_bus_rescan_work(struct work_struct *work); void mei_cl_bus_dev_fixup(struct mei_cl_device *dev); ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, -- cgit v1.2.3 From b6a38565e6d783a16854654b3cfb3a178768b37a Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 30 Apr 2017 13:12:11 +0300 Subject: mei: hw: fix a spelling mistake notifcation -> notification Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h index e1e4d47d4d7d..5c8286b40b62 100644 --- a/drivers/misc/mei/hw.h +++ b/drivers/misc/mei/hw.h @@ -65,7 +65,7 @@ #define HBM_MAJOR_VERSION_DOT 2 /* - * MEI version with notifcation support + * MEI version with notification support */ #define HBM_MINOR_VERSION_EV 0 #define HBM_MAJOR_VERSION_EV 2 -- cgit v1.2.3 From 70caf709164b7347326205ea19cfafea7d002f81 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 27 Apr 2017 18:41:34 +0100 Subject: goldfish_pipe: make pipe_dev static Make this static as it's only referenced in this source and it does not need global scope. Cleans up a sparse warning: drivers/platform/goldfish/goldfish_pipe.c: warning: symbol 'pipe_dev' was not declared. Should it be static? Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 2de1e603bd2b..8a4b088c52a7 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -266,7 +266,7 @@ struct goldfish_pipe_dev { unsigned char __iomem *base; }; -struct goldfish_pipe_dev pipe_dev[1] = {}; +static struct goldfish_pipe_dev pipe_dev[1] = {}; static int goldfish_cmd_locked(struct goldfish_pipe *pipe, enum PipeCmdCode cmd) { -- cgit v1.2.3 From 4654bdb63910eaafd586c7c12b473ecc0b3ab94a Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 25 Apr 2017 16:13:34 +0000 Subject: auxdisplay: Convert list_for_each to entry variant convert list_for_each() to list_for_each_entry() where applicable. Signed-off-by: Wei Yongjun Reviewed-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/auxdisplay/panel.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c index e0c014c2356f..7a8b8fb2f572 100644 --- a/drivers/auxdisplay/panel.c +++ b/drivers/auxdisplay/panel.c @@ -1345,14 +1345,11 @@ static inline void input_state_falling(struct logical_input *input) static void panel_process_inputs(void) { - struct list_head *item; struct logical_input *input; keypressed = 0; inputs_stable = 1; - list_for_each(item, &logical_inputs) { - input = list_entry(item, struct logical_input, list); - + list_for_each_entry(input, &logical_inputs, list) { switch (input->state) { case INPUT_ST_LOW: if ((phys_curr & input->mask) != input->value) -- cgit v1.2.3 From 610387d162eb1beb6eb2009af5175dc6b44b8da6 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 21 May 2017 22:42:32 +0200 Subject: misc: apds990x: move header file out of I2C realm include/linux/i2c is not for client devices. Move the header file to a more appropriate location. Signed-off-by: Wolfram Sang Signed-off-by: Greg Kroah-Hartman --- drivers/misc/apds990x.c | 2 +- include/linux/i2c/apds990x.h | 79 ---------------------------------- include/linux/platform_data/apds990x.h | 79 ++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 80 deletions(-) delete mode 100644 include/linux/i2c/apds990x.h create mode 100644 include/linux/platform_data/apds990x.h diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c index dfb72ecfa604..c341164edaad 100644 --- a/drivers/misc/apds990x.c +++ b/drivers/misc/apds990x.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include /* Register map */ #define APDS990X_ENABLE 0x00 /* Enable of states and interrupts */ diff --git a/include/linux/i2c/apds990x.h b/include/linux/i2c/apds990x.h deleted file mode 100644 index d186fcc5d257..000000000000 --- a/include/linux/i2c/apds990x.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * This file is part of the APDS990x sensor driver. - * Chip is combined proximity and ambient light sensor. - * - * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: Samu Onkalo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __APDS990X_H__ -#define __APDS990X_H__ - - -#define APDS_IRLED_CURR_12mA 0x3 -#define APDS_IRLED_CURR_25mA 0x2 -#define APDS_IRLED_CURR_50mA 0x1 -#define APDS_IRLED_CURR_100mA 0x0 - -/** - * struct apds990x_chip_factors - defines effect of the cover window - * @ga: Total glass attenuation - * @cf1: clear channel factor 1 for raw to lux conversion - * @irf1: IR channel factor 1 for raw to lux conversion - * @cf2: clear channel factor 2 for raw to lux conversion - * @irf2: IR channel factor 2 for raw to lux conversion - * @df: device factor for conversion formulas - * - * Structure for tuning ALS calculation to match with environment. - * Values depend on the material above the sensor and the sensor - * itself. If the GA is zero, driver will use uncovered sensor default values - * format: decimal value * APDS_PARAM_SCALE except df which is plain integer. - */ -#define APDS_PARAM_SCALE 4096 -struct apds990x_chip_factors { - int ga; - int cf1; - int irf1; - int cf2; - int irf2; - int df; -}; - -/** - * struct apds990x_platform_data - platform data for apsd990x.c driver - * @cf: chip factor data - * @pddrive: IR-led driving current - * @ppcount: number of IR pulses used for proximity estimation - * @setup_resources: interrupt line setup call back function - * @release_resources: interrupt line release call back function - * - * Proximity detection result depends heavily on correct ppcount, pdrive - * and cover window. - * - */ - -struct apds990x_platform_data { - struct apds990x_chip_factors cf; - u8 pdrive; - u8 ppcount; - int (*setup_resources)(void); - int (*release_resources)(void); -}; - -#endif diff --git a/include/linux/platform_data/apds990x.h b/include/linux/platform_data/apds990x.h new file mode 100644 index 000000000000..d186fcc5d257 --- /dev/null +++ b/include/linux/platform_data/apds990x.h @@ -0,0 +1,79 @@ +/* + * This file is part of the APDS990x sensor driver. + * Chip is combined proximity and ambient light sensor. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: Samu Onkalo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __APDS990X_H__ +#define __APDS990X_H__ + + +#define APDS_IRLED_CURR_12mA 0x3 +#define APDS_IRLED_CURR_25mA 0x2 +#define APDS_IRLED_CURR_50mA 0x1 +#define APDS_IRLED_CURR_100mA 0x0 + +/** + * struct apds990x_chip_factors - defines effect of the cover window + * @ga: Total glass attenuation + * @cf1: clear channel factor 1 for raw to lux conversion + * @irf1: IR channel factor 1 for raw to lux conversion + * @cf2: clear channel factor 2 for raw to lux conversion + * @irf2: IR channel factor 2 for raw to lux conversion + * @df: device factor for conversion formulas + * + * Structure for tuning ALS calculation to match with environment. + * Values depend on the material above the sensor and the sensor + * itself. If the GA is zero, driver will use uncovered sensor default values + * format: decimal value * APDS_PARAM_SCALE except df which is plain integer. + */ +#define APDS_PARAM_SCALE 4096 +struct apds990x_chip_factors { + int ga; + int cf1; + int irf1; + int cf2; + int irf2; + int df; +}; + +/** + * struct apds990x_platform_data - platform data for apsd990x.c driver + * @cf: chip factor data + * @pddrive: IR-led driving current + * @ppcount: number of IR pulses used for proximity estimation + * @setup_resources: interrupt line setup call back function + * @release_resources: interrupt line release call back function + * + * Proximity detection result depends heavily on correct ppcount, pdrive + * and cover window. + * + */ + +struct apds990x_platform_data { + struct apds990x_chip_factors cf; + u8 pdrive; + u8 ppcount; + int (*setup_resources)(void); + int (*release_resources)(void); +}; + +#endif -- cgit v1.2.3 From 7ae5f10a9fc1ae2f001ab3be5be84a5d0a89f918 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 21 May 2017 22:42:33 +0200 Subject: misc: bh1770glc: move header file out of I2C realm include/linux/i2c is not for client devices. Move the header file to a more appropriate location. Signed-off-by: Wolfram Sang Signed-off-by: Greg Kroah-Hartman --- drivers/misc/bh1770glc.c | 2 +- include/linux/i2c/bh1770glc.h | 53 --------------------------------- include/linux/platform_data/bh1770glc.h | 53 +++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 54 deletions(-) delete mode 100644 include/linux/i2c/bh1770glc.h create mode 100644 include/linux/platform_data/bh1770glc.h diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c index 845466e45b95..38fcfe219d1c 100644 --- a/drivers/misc/bh1770glc.c +++ b/drivers/misc/bh1770glc.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/linux/i2c/bh1770glc.h b/include/linux/i2c/bh1770glc.h deleted file mode 100644 index 8b5e2df36c72..000000000000 --- a/include/linux/i2c/bh1770glc.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of the ROHM BH1770GLC / OSRAM SFH7770 sensor driver. - * Chip is combined proximity and ambient light sensor. - * - * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: Samu Onkalo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __BH1770_H__ -#define __BH1770_H__ - -/** - * struct bh1770_platform_data - platform data for bh1770glc driver - * @led_def_curr: IR led driving current. - * @glass_attenuation: Attenuation factor for covering window. - * @setup_resources: Call back for interrupt line setup function - * @release_resources: Call back for interrupte line release function - * - * Example of glass attenuation: 16384 * 385 / 100 means attenuation factor - * of 3.85. i.e. light_above_sensor = light_above_cover_window / 3.85 - */ - -struct bh1770_platform_data { -#define BH1770_LED_5mA 0 -#define BH1770_LED_10mA 1 -#define BH1770_LED_20mA 2 -#define BH1770_LED_50mA 3 -#define BH1770_LED_100mA 4 -#define BH1770_LED_150mA 5 -#define BH1770_LED_200mA 6 - __u8 led_def_curr; -#define BH1770_NEUTRAL_GA 16384 /* 16384 / 16384 = 1 */ - __u32 glass_attenuation; - int (*setup_resources)(void); - int (*release_resources)(void); -}; -#endif diff --git a/include/linux/platform_data/bh1770glc.h b/include/linux/platform_data/bh1770glc.h new file mode 100644 index 000000000000..8b5e2df36c72 --- /dev/null +++ b/include/linux/platform_data/bh1770glc.h @@ -0,0 +1,53 @@ +/* + * This file is part of the ROHM BH1770GLC / OSRAM SFH7770 sensor driver. + * Chip is combined proximity and ambient light sensor. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: Samu Onkalo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __BH1770_H__ +#define __BH1770_H__ + +/** + * struct bh1770_platform_data - platform data for bh1770glc driver + * @led_def_curr: IR led driving current. + * @glass_attenuation: Attenuation factor for covering window. + * @setup_resources: Call back for interrupt line setup function + * @release_resources: Call back for interrupte line release function + * + * Example of glass attenuation: 16384 * 385 / 100 means attenuation factor + * of 3.85. i.e. light_above_sensor = light_above_cover_window / 3.85 + */ + +struct bh1770_platform_data { +#define BH1770_LED_5mA 0 +#define BH1770_LED_10mA 1 +#define BH1770_LED_20mA 2 +#define BH1770_LED_50mA 3 +#define BH1770_LED_100mA 4 +#define BH1770_LED_150mA 5 +#define BH1770_LED_200mA 6 + __u8 led_def_curr; +#define BH1770_NEUTRAL_GA 16384 /* 16384 / 16384 = 1 */ + __u32 glass_attenuation; + int (*setup_resources)(void); + int (*release_resources)(void); +}; +#endif -- cgit v1.2.3 From 46505c802a55189955d97195c8567ee263168747 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 26 May 2017 13:57:49 -0700 Subject: Revert "firmware: vpd: remove platform driver" This reverts commit 7975bd4cca05a99aa14964cfa22366ee64da50ad, because VPD relies on driver core to handle deferrals returned by coreboot_table_find(). Signed-off-by: Dmitry Torokhov Reviewed-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/google/vpd.c | 44 +++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c index d28f62fed50f..4f8f99edbbfa 100644 --- a/drivers/firmware/google/vpd.c +++ b/drivers/firmware/google/vpd.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -277,37 +279,47 @@ static int vpd_sections_init(phys_addr_t physaddr) ret = vpd_section_init("rw", &rw_vpd, physaddr + sizeof(struct vpd_cbmem) + header.ro_size, header.rw_size); - if (ret) { - vpd_section_destroy(&ro_vpd); + if (ret) return ret; - } } return 0; } -static int __init vpd_platform_init(void) +static int vpd_probe(struct platform_device *pdev) { + int ret; struct lb_cbmem_ref entry; - int err; + + ret = coreboot_table_find(CB_TAG_VPD, &entry, sizeof(entry)); + if (ret) + return ret; + + return vpd_sections_init(entry.cbmem_addr); +} + +static struct platform_driver vpd_driver = { + .probe = vpd_probe, + .driver = { + .name = "vpd", + }, +}; + +static int __init vpd_platform_init(void) +{ + struct platform_device *pdev; + + pdev = platform_device_register_simple("vpd", -1, NULL, 0); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); vpd_kobj = kobject_create_and_add("vpd", firmware_kobj); if (!vpd_kobj) return -ENOMEM; - err = coreboot_table_find(CB_TAG_VPD, &entry, sizeof(entry)); - if (err) - goto err_kobject_put; - - err = vpd_sections_init(entry.cbmem_addr); - if (err) - goto err_kobject_put; + platform_driver_register(&vpd_driver); return 0; - -err_kobject_put: - kobject_put(vpd_kobj); - return err; } static void __exit vpd_platform_exit(void) -- cgit v1.2.3