summaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-03-17 13:47:50 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2016-03-17 13:47:50 -0700
commit8eee93e2576c303b6071368456dcd6c9a5a021c9 (patch)
tree0c65d2dc160af900e0c87ebc4b41979c0b9075cf /include/linux
parent1a4ab084afaa8e5405a3e22aca21478ee3ca5d59 (diff)
parent16617535684faf9de30620de83667214297a36b8 (diff)
downloadlinux-stable-8eee93e2576c303b6071368456dcd6c9a5a021c9.tar.gz
linux-stable-8eee93e2576c303b6071368456dcd6c9a5a021c9.tar.bz2
linux-stable-8eee93e2576c303b6071368456dcd6c9a5a021c9.zip
Merge tag 'char-misc-4.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc updates from Greg KH: "Here is the big char/misc driver update for 4.6-rc1. The majority of the patches here is hwtracing and some new mic drivers, but there's a lot of other driver updates as well. Full details in the shortlog. All have been in linux-next for a while with no reported issues" * tag 'char-misc-4.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (238 commits) goldfish: Fix build error of missing ioremap on UM nvmem: mediatek: Fix later provider initialization nvmem: imx-ocotp: Fix return value of imx_ocotp_read nvmem: Fix dependencies for !HAS_IOMEM archs char: genrtc: replace blacklist with whitelist drivers/hwtracing: make coresight-etm-perf.c explicitly non-modular drivers: char: mem: fix IS_ERROR_VALUE usage char: xillybus: Fix internal data structure initialization pch_phub: return -ENODATA if ROM can't be mapped Drivers: hv: vmbus: Support kexec on ws2012 r2 and above Drivers: hv: vmbus: Support handling messages on multiple CPUs Drivers: hv: utils: Remove util transport handler from list if registration fails Drivers: hv: util: Pass the channel information during the init call Drivers: hv: vmbus: avoid unneeded compiler optimizations in vmbus_wait_for_unload() Drivers: hv: vmbus: remove code duplication in message handling Drivers: hv: vmbus: avoid wait_for_completion() on crash Drivers: hv: vmbus: don't loose HVMSG_TIMER_EXPIRED messages misc: at24: replace memory_accessor with nvmem_device_read eeprom: 93xx46: extend driver to plug into the NVMEM framework eeprom: at25: extend driver to plug into the NVMEM framework ...
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/amba/bus.h9
-rw-r--r--include/linux/coresight-pmu.h39
-rw-r--r--include/linux/coresight.h34
-rw-r--r--include/linux/davinci_emac.h4
-rw-r--r--include/linux/eeprom_93xx46.h9
-rw-r--r--include/linux/hyperv.h96
-rw-r--r--include/linux/memory.h11
-rw-r--r--include/linux/mfd/palmas.h3
-rw-r--r--include/linux/nvmem-provider.h5
-rw-r--r--include/linux/platform_data/at24.h10
-rw-r--r--include/linux/spi/eeprom.h2
-rw-r--r--include/linux/stm.h10
-rw-r--r--include/linux/vmw_vmci_defs.h43
13 files changed, 243 insertions, 32 deletions
diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h
index 9006c4e75cf7..3d8dcdd1aeae 100644
--- a/include/linux/amba/bus.h
+++ b/include/linux/amba/bus.h
@@ -163,4 +163,13 @@ struct amba_device name##_device = { \
#define module_amba_driver(__amba_drv) \
module_driver(__amba_drv, amba_driver_register, amba_driver_unregister)
+/*
+ * builtin_amba_driver() - Helper macro for drivers that don't do anything
+ * special in driver initcall. This eliminates a lot of boilerplate. Each
+ * driver may only use this macro once, and calling it replaces the instance
+ * device_initcall().
+ */
+#define builtin_amba_driver(__amba_drv) \
+ builtin_driver(__amba_drv, amba_driver_register)
+
#endif
diff --git a/include/linux/coresight-pmu.h b/include/linux/coresight-pmu.h
new file mode 100644
index 000000000000..7d410260661b
--- /dev/null
+++ b/include/linux/coresight-pmu.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _LINUX_CORESIGHT_PMU_H
+#define _LINUX_CORESIGHT_PMU_H
+
+#define CORESIGHT_ETM_PMU_NAME "cs_etm"
+#define CORESIGHT_ETM_PMU_SEED 0x10
+
+/* ETMv3.5/PTM's ETMCR config bit */
+#define ETM_OPT_CYCACC 12
+#define ETM_OPT_TS 28
+
+static inline int coresight_get_trace_id(int cpu)
+{
+ /*
+ * A trace ID of value 0 is invalid, so let's start at some
+ * random value that fits in 7 bits and go from there. Since
+ * the common convention is to have data trace IDs be I(N) + 1,
+ * set instruction trace IDs as a function of the CPU number.
+ */
+ return (CORESIGHT_ETM_PMU_SEED + (cpu * 2));
+}
+
+#endif
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index a7cabfa23b55..385d62e64abb 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -14,6 +14,7 @@
#define _LINUX_CORESIGHT_H
#include <linux/device.h>
+#include <linux/perf_event.h>
#include <linux/sched.h>
/* Peripheral id registers (0xFD0-0xFEC) */
@@ -152,7 +153,6 @@ struct coresight_connection {
by @coresight_ops.
* @dev: The device entity associated to this component.
* @refcnt: keep track of what is in use.
- * @path_link: link of current component into the path being enabled.
* @orphan: true if the component has connections that haven't been linked.
* @enable: 'true' if component is currently part of an active path.
* @activated: 'true' only if a _sink_ has been activated. A sink can be
@@ -168,7 +168,6 @@ struct coresight_device {
const struct coresight_ops *ops;
struct device dev;
atomic_t *refcnt;
- struct list_head path_link;
bool orphan;
bool enable; /* true only if configured as part of a path */
bool activated; /* true only if a sink is part of a path */
@@ -183,12 +182,29 @@ struct coresight_device {
/**
* struct coresight_ops_sink - basic operations for a sink
* Operations available for sinks
- * @enable: enables the sink.
- * @disable: disables the sink.
+ * @enable: enables the sink.
+ * @disable: disables the sink.
+ * @alloc_buffer: initialises perf's ring buffer for trace collection.
+ * @free_buffer: release memory allocated in @get_config.
+ * @set_buffer: initialises buffer mechanic before a trace session.
+ * @reset_buffer: finalises buffer mechanic after a trace session.
+ * @update_buffer: update buffer pointers after a trace session.
*/
struct coresight_ops_sink {
- int (*enable)(struct coresight_device *csdev);
+ int (*enable)(struct coresight_device *csdev, u32 mode);
void (*disable)(struct coresight_device *csdev);
+ void *(*alloc_buffer)(struct coresight_device *csdev, int cpu,
+ void **pages, int nr_pages, bool overwrite);
+ void (*free_buffer)(void *config);
+ int (*set_buffer)(struct coresight_device *csdev,
+ struct perf_output_handle *handle,
+ void *sink_config);
+ unsigned long (*reset_buffer)(struct coresight_device *csdev,
+ struct perf_output_handle *handle,
+ void *sink_config, bool *lost);
+ void (*update_buffer)(struct coresight_device *csdev,
+ struct perf_output_handle *handle,
+ void *sink_config);
};
/**
@@ -205,14 +221,18 @@ struct coresight_ops_link {
/**
* struct coresight_ops_source - basic operations for a source
* Operations available for sources.
+ * @cpu_id: returns the value of the CPU number this component
+ * is associated to.
* @trace_id: returns the value of the component's trace ID as known
- to the HW.
+ * to the HW.
* @enable: enables tracing for a source.
* @disable: disables tracing for a source.
*/
struct coresight_ops_source {
+ int (*cpu_id)(struct coresight_device *csdev);
int (*trace_id)(struct coresight_device *csdev);
- int (*enable)(struct coresight_device *csdev);
+ int (*enable)(struct coresight_device *csdev,
+ struct perf_event_attr *attr, u32 mode);
void (*disable)(struct coresight_device *csdev);
};
diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h
index 542888504994..05b97144d342 100644
--- a/include/linux/davinci_emac.h
+++ b/include/linux/davinci_emac.h
@@ -12,7 +12,7 @@
#define _LINUX_DAVINCI_EMAC_H
#include <linux/if_ether.h>
-#include <linux/memory.h>
+#include <linux/nvmem-consumer.h>
struct mdio_platform_data {
unsigned long bus_freq;
@@ -46,5 +46,5 @@ enum {
EMAC_VERSION_2, /* DM646x */
};
-void davinci_get_mac_addr(struct memory_accessor *mem_acc, void *context);
+void davinci_get_mac_addr(struct nvmem_device *nvmem, void *context);
#endif
diff --git a/include/linux/eeprom_93xx46.h b/include/linux/eeprom_93xx46.h
index 06791811e49d..885f587a3555 100644
--- a/include/linux/eeprom_93xx46.h
+++ b/include/linux/eeprom_93xx46.h
@@ -3,16 +3,25 @@
* platform description for 93xx46 EEPROMs.
*/
+struct gpio_desc;
+
struct eeprom_93xx46_platform_data {
unsigned char flags;
#define EE_ADDR8 0x01 /* 8 bit addr. cfg */
#define EE_ADDR16 0x02 /* 16 bit addr. cfg */
#define EE_READONLY 0x08 /* forbid writing */
+ unsigned int quirks;
+/* Single word read transfers only; no sequential read. */
+#define EEPROM_93XX46_QUIRK_SINGLE_WORD_READ (1 << 0)
+/* Instructions such as EWEN are (addrlen + 2) in length. */
+#define EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH (1 << 1)
+
/*
* optional hooks to control additional logic
* before and after spi transfer.
*/
void (*prepare)(void *);
void (*finish)(void *);
+ struct gpio_desc *select;
};
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 753dbad0bf94..aa0fadce9308 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -235,6 +235,7 @@ struct vmbus_channel_offer {
#define VMBUS_CHANNEL_LOOPBACK_OFFER 0x100
#define VMBUS_CHANNEL_PARENT_OFFER 0x200
#define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION 0x400
+#define VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER 0x2000
struct vmpacket_descriptor {
u16 type;
@@ -391,6 +392,10 @@ enum vmbus_channel_message_type {
CHANNELMSG_VERSION_RESPONSE = 15,
CHANNELMSG_UNLOAD = 16,
CHANNELMSG_UNLOAD_RESPONSE = 17,
+ CHANNELMSG_18 = 18,
+ CHANNELMSG_19 = 19,
+ CHANNELMSG_20 = 20,
+ CHANNELMSG_TL_CONNECT_REQUEST = 21,
CHANNELMSG_COUNT
};
@@ -561,6 +566,13 @@ struct vmbus_channel_initiate_contact {
u64 monitor_page2;
} __packed;
+/* Hyper-V socket: guest's connect()-ing to host */
+struct vmbus_channel_tl_connect_request {
+ struct vmbus_channel_message_header header;
+ uuid_le guest_endpoint_id;
+ uuid_le host_service_id;
+} __packed;
+
struct vmbus_channel_version_response {
struct vmbus_channel_message_header header;
u8 version_supported;
@@ -633,6 +645,32 @@ enum hv_signal_policy {
HV_SIGNAL_POLICY_EXPLICIT,
};
+enum vmbus_device_type {
+ HV_IDE = 0,
+ HV_SCSI,
+ HV_FC,
+ HV_NIC,
+ HV_ND,
+ HV_PCIE,
+ HV_FB,
+ HV_KBD,
+ HV_MOUSE,
+ HV_KVP,
+ HV_TS,
+ HV_HB,
+ HV_SHUTDOWN,
+ HV_FCOPY,
+ HV_BACKUP,
+ HV_DM,
+ HV_UNKOWN,
+};
+
+struct vmbus_device {
+ u16 dev_type;
+ uuid_le guid;
+ bool perf_device;
+};
+
struct vmbus_channel {
/* Unique channel id */
int id;
@@ -728,6 +766,12 @@ struct vmbus_channel {
void (*sc_creation_callback)(struct vmbus_channel *new_sc);
/*
+ * Channel rescind callback. Some channels (the hvsock ones), need to
+ * register a callback which is invoked in vmbus_onoffer_rescind().
+ */
+ void (*chn_rescind_callback)(struct vmbus_channel *channel);
+
+ /*
* The spinlock to protect the structure. It is being used to protect
* test-and-set access to various attributes of the structure as well
* as all sc_list operations.
@@ -767,8 +811,30 @@ struct vmbus_channel {
* signaling control.
*/
enum hv_signal_policy signal_policy;
+ /*
+ * On the channel send side, many of the VMBUS
+ * device drivers explicity serialize access to the
+ * outgoing ring buffer. Give more control to the
+ * VMBUS device drivers in terms how to serialize
+ * accesss to the outgoing ring buffer.
+ * The default behavior will be to aquire the
+ * ring lock to preserve the current behavior.
+ */
+ bool acquire_ring_lock;
+
};
+static inline void set_channel_lock_state(struct vmbus_channel *c, bool state)
+{
+ c->acquire_ring_lock = state;
+}
+
+static inline bool is_hvsock_channel(const struct vmbus_channel *c)
+{
+ return !!(c->offermsg.offer.chn_flags &
+ VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER);
+}
+
static inline void set_channel_signal_state(struct vmbus_channel *c,
enum hv_signal_policy policy)
{
@@ -790,6 +856,12 @@ static inline void *get_per_channel_state(struct vmbus_channel *c)
return c->per_channel_state;
}
+static inline void set_channel_pending_send_size(struct vmbus_channel *c,
+ u32 size)
+{
+ c->outbound.ring_buffer->pending_send_sz = size;
+}
+
void vmbus_onmessage(void *context);
int vmbus_request_offers(void);
@@ -801,6 +873,9 @@ int vmbus_request_offers(void);
void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel,
void (*sc_cr_cb)(struct vmbus_channel *new_sc));
+void vmbus_set_chn_rescind_callback(struct vmbus_channel *channel,
+ void (*chn_rescind_cb)(struct vmbus_channel *));
+
/*
* Retrieve the (sub) channel on which to send an outgoing request.
* When a primary channel has multiple sub-channels, we choose a
@@ -940,6 +1015,20 @@ extern void vmbus_ontimer(unsigned long data);
struct hv_driver {
const char *name;
+ /*
+ * A hvsock offer, which has a VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER
+ * channel flag, actually doesn't mean a synthetic device because the
+ * offer's if_type/if_instance can change for every new hvsock
+ * connection.
+ *
+ * However, to facilitate the notification of new-offer/rescind-offer
+ * from vmbus driver to hvsock driver, we can handle hvsock offer as
+ * a special vmbus device, and hence we need the below flag to
+ * indicate if the driver is the hvsock driver or not: we need to
+ * specially treat the hvosck offer & driver in vmbus_match().
+ */
+ bool hvsock;
+
/* the device type supported by this driver */
uuid_le dev_type;
const struct hv_vmbus_device_id *id_table;
@@ -959,6 +1048,8 @@ struct hv_device {
/* the device instance id of this device */
uuid_le dev_instance;
+ u16 vendor_id;
+ u16 device_id;
struct device device;
@@ -994,6 +1085,8 @@ int __must_check __vmbus_driver_register(struct hv_driver *hv_driver,
const char *mod_name);
void vmbus_driver_unregister(struct hv_driver *hv_driver);
+void vmbus_hvsock_device_unregister(struct vmbus_channel *channel);
+
int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
resource_size_t min, resource_size_t max,
resource_size_t size, resource_size_t align,
@@ -1158,6 +1251,7 @@ u64 hv_do_hypercall(u64 control, void *input, void *output);
struct hv_util_service {
u8 *recv_buffer;
+ void *channel;
void (*util_cb)(void *);
int (*util_init)(struct hv_util_service *);
void (*util_deinit)(void);
@@ -1242,4 +1336,6 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid);
extern __u32 vmbus_proto_version;
+int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id,
+ const uuid_le *shv_host_servie_id);
#endif /* _HYPERV_H */
diff --git a/include/linux/memory.h b/include/linux/memory.h
index 82730adba950..093607f90b91 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -140,17 +140,6 @@ extern struct memory_block *find_memory_block(struct mem_section *);
#endif
/*
- * 'struct memory_accessor' is a generic interface to provide
- * in-kernel access to persistent memory such as i2c or SPI EEPROMs
- */
-struct memory_accessor {
- ssize_t (*read)(struct memory_accessor *, char *buf, off_t offset,
- size_t count);
- ssize_t (*write)(struct memory_accessor *, const char *buf,
- off_t offset, size_t count);
-};
-
-/*
* Kernel text modification mutex, used for code patching. Users of this lock
* can sleep.
*/
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
index c800dbc42079..5c9a1d44c125 100644
--- a/include/linux/mfd/palmas.h
+++ b/include/linux/mfd/palmas.h
@@ -580,7 +580,9 @@ struct palmas_usb {
int vbus_irq;
int gpio_id_irq;
+ int gpio_vbus_irq;
struct gpio_desc *id_gpiod;
+ struct gpio_desc *vbus_gpiod;
unsigned long sw_debounce_jiffies;
struct delayed_work wq_detectid;
@@ -589,6 +591,7 @@ struct palmas_usb {
bool enable_vbus_detection;
bool enable_id_detection;
bool enable_gpio_id_detection;
+ bool enable_gpio_vbus_detection;
};
#define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator)
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index 0b68caff1b3c..a4fcc90b0f20 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -23,6 +23,10 @@ struct nvmem_config {
const struct nvmem_cell_info *cells;
int ncells;
bool read_only;
+ bool root_only;
+ /* To be only used by old driver/misc/eeprom drivers */
+ bool compat;
+ struct device *base_dev;
};
#if IS_ENABLED(CONFIG_NVMEM)
@@ -43,5 +47,4 @@ static inline int nvmem_unregister(struct nvmem_device *nvmem)
}
#endif /* CONFIG_NVMEM */
-
#endif /* ifndef _LINUX_NVMEM_PROVIDER_H */
diff --git a/include/linux/platform_data/at24.h b/include/linux/platform_data/at24.h
index c42aa89d34ee..dc9a13e5acda 100644
--- a/include/linux/platform_data/at24.h
+++ b/include/linux/platform_data/at24.h
@@ -9,7 +9,7 @@
#define _LINUX_AT24_H
#include <linux/types.h>
-#include <linux/memory.h>
+#include <linux/nvmem-consumer.h>
/**
* struct at24_platform_data - data to set up at24 (generic eeprom) driver
@@ -17,7 +17,7 @@
* @page_size: number of byte which can be written in one go
* @flags: tunable options, check AT24_FLAG_* defines
* @setup: an optional callback invoked after eeprom is probed; enables kernel
- code to access eeprom via memory_accessor, see example
+ code to access eeprom via nvmem, see example
* @context: optional parameter passed to setup()
*
* If you set up a custom eeprom type, please double-check the parameters.
@@ -26,13 +26,13 @@
*
* An example in pseudo code for a setup() callback:
*
- * void get_mac_addr(struct memory_accessor *mem_acc, void *context)
+ * void get_mac_addr(struct mvmem_device *nvmem, void *context)
* {
* u8 *mac_addr = ethernet_pdata->mac_addr;
* off_t offset = context;
*
* // Read MAC addr from EEPROM
- * if (mem_acc->read(mem_acc, mac_addr, offset, ETH_ALEN) == ETH_ALEN)
+ * if (nvmem_device_read(nvmem, offset, ETH_ALEN, mac_addr) == ETH_ALEN)
* pr_info("Read MAC addr from EEPROM: %pM\n", mac_addr);
* }
*
@@ -48,7 +48,7 @@ struct at24_platform_data {
#define AT24_FLAG_IRUGO 0x20 /* sysfs-entry will be world-readable */
#define AT24_FLAG_TAKE8ADDR 0x10 /* take always 8 addresses (24c00) */
- void (*setup)(struct memory_accessor *, void *context);
+ void (*setup)(struct nvmem_device *nvmem, void *context);
void *context;
};
diff --git a/include/linux/spi/eeprom.h b/include/linux/spi/eeprom.h
index 403e007aef68..e34e169f9dcb 100644
--- a/include/linux/spi/eeprom.h
+++ b/include/linux/spi/eeprom.h
@@ -30,8 +30,6 @@ struct spi_eeprom {
*/
#define EE_INSTR_BIT3_IS_ADDR 0x0010
- /* for exporting this chip's data to other kernel code */
- void (*setup)(struct memory_accessor *mem, void *context);
void *context;
};
diff --git a/include/linux/stm.h b/include/linux/stm.h
index 9d0083d364e6..1a79ed8e43da 100644
--- a/include/linux/stm.h
+++ b/include/linux/stm.h
@@ -67,6 +67,16 @@ struct stm_device;
* description. That is, the lowest master that can be allocated to software
* writers is @sw_start and data from this writer will appear is @sw_start
* master in the STP stream.
+ *
+ * The @packet callback should adhere to the following rules:
+ * 1) it must return the number of bytes it consumed from the payload;
+ * 2) therefore, if it sent a packet that does not have payload (like FLAG),
+ * it must return zero;
+ * 3) if it does not support the requested packet type/flag combination,
+ * it must return -ENOTSUPP.
+ *
+ * The @unlink callback is called when there are no more active writers so
+ * that the master/channel can be quiesced.
*/
struct stm_data {
const char *name;
diff --git a/include/linux/vmw_vmci_defs.h b/include/linux/vmw_vmci_defs.h
index 65ac54c61c18..1bd31a38c51e 100644
--- a/include/linux/vmw_vmci_defs.h
+++ b/include/linux/vmw_vmci_defs.h
@@ -734,6 +734,41 @@ static inline void *vmci_event_data_payload(struct vmci_event_data *ev_data)
}
/*
+ * Helper to read a value from a head or tail pointer. For X86_32, the
+ * pointer is treated as a 32bit value, since the pointer value
+ * never exceeds a 32bit value in this case. Also, doing an
+ * atomic64_read on X86_32 uniprocessor systems may be implemented
+ * as a non locked cmpxchg8b, that may end up overwriting updates done
+ * by the VMCI device to the memory location. On 32bit SMP, the lock
+ * prefix will be used, so correctness isn't an issue, but using a
+ * 64bit operation still adds unnecessary overhead.
+ */
+static inline u64 vmci_q_read_pointer(atomic64_t *var)
+{
+#if defined(CONFIG_X86_32)
+ return atomic_read((atomic_t *)var);
+#else
+ return atomic64_read(var);
+#endif
+}
+
+/*
+ * Helper to set the value of a head or tail pointer. For X86_32, the
+ * pointer is treated as a 32bit value, since the pointer value
+ * never exceeds a 32bit value in this case. On 32bit SMP, using a
+ * locked cmpxchg8b adds unnecessary overhead.
+ */
+static inline void vmci_q_set_pointer(atomic64_t *var,
+ u64 new_val)
+{
+#if defined(CONFIG_X86_32)
+ return atomic_set((atomic_t *)var, (u32)new_val);
+#else
+ return atomic64_set(var, new_val);
+#endif
+}
+
+/*
* Helper to add a given offset to a head or tail pointer. Wraps the
* value of the pointer around the max size of the queue.
*/
@@ -741,14 +776,14 @@ static inline void vmci_qp_add_pointer(atomic64_t *var,
size_t add,
u64 size)
{
- u64 new_val = atomic64_read(var);
+ u64 new_val = vmci_q_read_pointer(var);
if (new_val >= size - add)
new_val -= size;
new_val += add;
- atomic64_set(var, new_val);
+ vmci_q_set_pointer(var, new_val);
}
/*
@@ -758,7 +793,7 @@ static inline u64
vmci_q_header_producer_tail(const struct vmci_queue_header *q_header)
{
struct vmci_queue_header *qh = (struct vmci_queue_header *)q_header;
- return atomic64_read(&qh->producer_tail);
+ return vmci_q_read_pointer(&qh->producer_tail);
}
/*
@@ -768,7 +803,7 @@ static inline u64
vmci_q_header_consumer_head(const struct vmci_queue_header *q_header)
{
struct vmci_queue_header *qh = (struct vmci_queue_header *)q_header;
- return atomic64_read(&qh->consumer_head);
+ return vmci_q_read_pointer(&qh->consumer_head);
}
/*