aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-driver-w1_therm2
-rw-r--r--Documentation/admin-guide/spkguide.txt1
-rw-r--r--Documentation/devicetree/bindings/nvmem/mtk-efuse.txt1
-rw-r--r--Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml17
-rw-r--r--Documentation/w1/slaves/w1_therm.rst2
-rw-r--r--drivers/accessibility/speakup/i18n.h6
-rw-r--r--drivers/accessibility/speakup/main.c64
-rw-r--r--drivers/accessibility/speakup/speakup_dummy.c7
-rw-r--r--drivers/android/binder.c427
-rw-r--r--drivers/android/binder_internal.h406
-rw-r--r--drivers/android/binder_trace.h29
-rw-r--r--drivers/char/lp.c1
-rw-r--r--drivers/char/misc.c2
-rw-r--r--drivers/char/mwave/mwavedd.c1
-rw-r--r--drivers/firmware/google/gsmi.c31
-rw-r--r--drivers/firmware/raspberrypi.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-core.c10
-rw-r--r--drivers/hwtracing/coresight/coresight-etb10.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x-core.c50
-rw-r--r--drivers/hwtracing/coresight/coresight-funnel.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-priv.h2
-rw-r--r--drivers/hwtracing/coresight/coresight-replicator.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-stm.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc-etf.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc-etr.c6
-rw-r--r--drivers/hwtracing/coresight/coresight-tpiu.c2
-rw-r--r--drivers/ipack/devices/ipoctal.c1
-rw-r--r--drivers/misc/c2port/core.c2
-rw-r--r--drivers/misc/eeprom/at25.c3
-rw-r--r--drivers/misc/hisi_hikey_usb.c5
-rw-r--r--drivers/misc/mei/bus.c20
-rw-r--r--drivers/misc/mei/hbm.c1
-rw-r--r--drivers/misc/ocxl/config.c2
-rw-r--r--drivers/misc/pci_endpoint_test.c2
-rw-r--r--drivers/misc/ti-st/st_core.c2
-rw-r--r--drivers/misc/uacce/uacce.c13
-rw-r--r--drivers/misc/xilinx_sdfec.c28
-rw-r--r--drivers/nvmem/core.c153
-rw-r--r--drivers/nvmem/imx-ocotp.c30
-rw-r--r--drivers/nvmem/qfprom.c30
-rw-r--r--drivers/slimbus/Kconfig4
-rw-r--r--drivers/slimbus/messaging.c1
-rw-r--r--drivers/slimbus/qcom-ngd-ctrl.c133
-rw-r--r--drivers/slimbus/slimbus.h2
-rw-r--r--drivers/uio/uio.c4
-rw-r--r--drivers/uio/uio_pci_generic.c37
-rw-r--r--drivers/uio/uio_pruss.c27
-rw-r--r--drivers/vme/bridges/vme_tsi148.c7
-rw-r--r--drivers/vme/vme.c13
-rw-r--r--drivers/w1/slaves/w1_therm.c12
-rw-r--r--include/linux/nvmem-provider.h17
-rw-r--r--include/linux/uio_driver.h16
52 files changed, 1016 insertions, 632 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-w1_therm b/Documentation/ABI/testing/sysfs-driver-w1_therm
index 6a37dc33ffdb..74642c73d29c 100644
--- a/Documentation/ABI/testing/sysfs-driver-w1_therm
+++ b/Documentation/ABI/testing/sysfs-driver-w1_therm
@@ -14,7 +14,7 @@ Users: any user space application which wants to communicate with
w1_term device
-What: /sys/bus/w1/devices/.../eeprom
+What: /sys/bus/w1/devices/.../eeprom_cmd
Date: May 2020
Contact: Akira Shimahara <akira215corp@gmail.com>
Description:
diff --git a/Documentation/admin-guide/spkguide.txt b/Documentation/admin-guide/spkguide.txt
index 3782f6a09e97..5ff6a0fe87d1 100644
--- a/Documentation/admin-guide/spkguide.txt
+++ b/Documentation/admin-guide/spkguide.txt
@@ -344,6 +344,7 @@ spk key_slash = say_attributes
spk key_8 = speakup_paste
shift spk key_m = say_first_char
ctrl spk key_semicolon = say_last_char
+spk key_r = read_all_doc
5. The Speakup Sys System
diff --git a/Documentation/devicetree/bindings/nvmem/mtk-efuse.txt b/Documentation/devicetree/bindings/nvmem/mtk-efuse.txt
index 0668c45a156d..ef93c3b95424 100644
--- a/Documentation/devicetree/bindings/nvmem/mtk-efuse.txt
+++ b/Documentation/devicetree/bindings/nvmem/mtk-efuse.txt
@@ -7,6 +7,7 @@ Required properties:
"mediatek,mt7622-efuse", "mediatek,efuse": for MT7622
"mediatek,mt7623-efuse", "mediatek,efuse": for MT7623
"mediatek,mt8173-efuse" or "mediatek,efuse": for MT8173
+ "mediatek,mt8516-efuse", "mediatek,efuse": for MT8516
- reg: Should contain registers location and length
= Data cells =
diff --git a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
index 1a18b6bab35e..992777c90a0b 100644
--- a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
+++ b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
@@ -14,7 +14,18 @@ allOf:
properties:
compatible:
- const: qcom,qfprom
+ items:
+ - enum:
+ - qcom,apq8064-qfprom
+ - qcom,apq8084-qfprom
+ - qcom,msm8974-qfprom
+ - qcom,msm8916-qfprom
+ - qcom,msm8996-qfprom
+ - qcom,msm8998-qfprom
+ - qcom,qcs404-qfprom
+ - qcom,sc7180-qfprom
+ - qcom,sdm845-qfprom
+ - const: qcom,qfprom
reg:
# If the QFPROM is read-only OS image then only the corrected region
@@ -60,7 +71,7 @@ examples:
#size-cells = <2>;
efuse@784000 {
- compatible = "qcom,qfprom";
+ compatible = "qcom,sc7180-qfprom", "qcom,qfprom";
reg = <0 0x00784000 0 0x8ff>,
<0 0x00780000 0 0x7a0>,
<0 0x00782000 0 0x100>,
@@ -85,7 +96,7 @@ examples:
#size-cells = <2>;
efuse@784000 {
- compatible = "qcom,qfprom";
+ compatible = "qcom,sdm845-qfprom", "qcom,qfprom";
reg = <0 0x00784000 0 0x8ff>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/Documentation/w1/slaves/w1_therm.rst b/Documentation/w1/slaves/w1_therm.rst
index e39202e2b000..c3c9ed7a356c 100644
--- a/Documentation/w1/slaves/w1_therm.rst
+++ b/Documentation/w1/slaves/w1_therm.rst
@@ -82,7 +82,7 @@ resolution is read back from the chip and verified.
Note: Changing the resolution reverts the conversion time to default.
-The write-only sysfs entry ``eeprom`` is an alternative for EEPROM operations.
+The write-only sysfs entry ``eeprom_cmd`` is an alternative for EEPROM operations.
Write ``save`` to save device RAM to EEPROM. Write ``restore`` to restore EEPROM
data in device RAM.
diff --git a/drivers/accessibility/speakup/i18n.h b/drivers/accessibility/speakup/i18n.h
index 2ec6e659d02b..2a607d263234 100644
--- a/drivers/accessibility/speakup/i18n.h
+++ b/drivers/accessibility/speakup/i18n.h
@@ -23,12 +23,15 @@ enum msg_index_t {
MSG_OFF = MSG_STATUS_START,
MSG_ON,
MSG_NO_WINDOW,
+
+ /* These must be ordered the same as enum cursor_track */
MSG_CURSOR_MSGS_START,
MSG_CURSORING_OFF = MSG_CURSOR_MSGS_START,
MSG_CURSORING_ON,
MSG_HIGHLIGHT_TRACKING,
MSG_READ_WINDOW,
MSG_READ_ALL,
+
MSG_EDIT_DONE,
MSG_WINDOW_ALREADY_SET,
MSG_END_BEFORE_START,
@@ -41,11 +44,14 @@ enum msg_index_t {
MSG_LEAVING_HELP,
MSG_IS_UNASSIGNED,
MSG_HELP_INFO,
+
+ /* These must be ordered the same as enum edge */
MSG_EDGE_MSGS_START,
MSG_EDGE_TOP = MSG_EDGE_MSGS_START,
MSG_EDGE_BOTTOM,
MSG_EDGE_LEFT,
MSG_EDGE_RIGHT,
+
MSG_NUMBER,
MSG_SPACE,
MSG_START, /* A little confusing, given our convention. */
diff --git a/drivers/accessibility/speakup/main.c b/drivers/accessibility/speakup/main.c
index 48019660a096..428fceaf9d50 100644
--- a/drivers/accessibility/speakup/main.c
+++ b/drivers/accessibility/speakup/main.c
@@ -90,19 +90,18 @@ const u_char spk_key_defaults[] = {
#include "speakupmap.h"
};
-/* Speakup Cursor Track Variables */
-static int cursor_track = 1, prev_cursor_track = 1;
-
-/* cursor track modes, must be ordered same as cursor_msgs */
-enum {
+/* cursor track modes, must be ordered same as cursor_msgs in enum msg_index_t */
+enum cursor_track {
CT_Off = 0,
CT_On,
CT_Highlight,
CT_Window,
- CT_Max
+ CT_Max,
+ read_all_mode = CT_Max,
};
-#define read_all_mode CT_Max
+/* Speakup Cursor Track Variables */
+static enum cursor_track cursor_track = 1, prev_cursor_track = 1;
static struct tty_struct *tty;
@@ -404,15 +403,17 @@ static void say_attributes(struct vc_data *vc)
synth_printf("%s\n", spk_msg_get(MSG_COLORS_START + bg));
}
-enum {
- edge_top = 1,
+/* must be ordered same as edge_msgs in enum msg_index_t */
+enum edge {
+ edge_none = 0,
+ edge_top,
edge_bottom,
edge_left,
edge_right,
edge_quiet
};
-static void announce_edge(struct vc_data *vc, int msg_id)
+static void announce_edge(struct vc_data *vc, enum edge msg_id)
{
if (spk_bleeps & 1)
bleep(spk_y);
@@ -607,7 +608,8 @@ static void say_prev_word(struct vc_data *vc)
{
u_char temp;
u16 ch;
- u_short edge_said = 0, last_state = 0, state = 0;
+ enum edge edge_said = edge_none;
+ u_short last_state = 0, state = 0;
spk_parked |= 0x01;
@@ -652,7 +654,7 @@ static void say_prev_word(struct vc_data *vc)
}
if (spk_x == 0 && edge_said == edge_quiet)
edge_said = edge_left;
- if (edge_said > 0 && edge_said < edge_quiet)
+ if (edge_said > edge_none && edge_said < edge_quiet)
announce_edge(vc, edge_said);
say_word(vc);
}
@@ -661,7 +663,8 @@ static void say_next_word(struct vc_data *vc)
{
u_char temp;
u16 ch;
- u_short edge_said = 0, last_state = 2, state = 0;
+ enum edge edge_said = edge_none;
+ u_short last_state = 2, state = 0;
spk_parked |= 0x01;
if (spk_x == vc->vc_cols - 1 && spk_y == vc->vc_rows - 1) {
@@ -693,7 +696,7 @@ static void say_next_word(struct vc_data *vc)
spk_pos += 2;
last_state = state;
}
- if (edge_said > 0)
+ if (edge_said > edge_none)
announce_edge(vc, edge_said);
say_word(vc);
}
@@ -1365,31 +1368,30 @@ static void speakup_deallocate(struct vc_data *vc)
speakup_console[vc_num] = NULL;
}
+enum read_all_command {
+ RA_NEXT_SENT = KVAL(K_DOWN)+1,
+ RA_PREV_LINE = KVAL(K_LEFT)+1,
+ RA_NEXT_LINE = KVAL(K_RIGHT)+1,
+ RA_PREV_SENT = KVAL(K_UP)+1,
+ RA_DOWN_ARROW,
+ RA_TIMER,
+ RA_FIND_NEXT_SENT,
+ RA_FIND_PREV_SENT,
+};
+
static u_char is_cursor;
static u_long old_cursor_pos, old_cursor_x, old_cursor_y;
static int cursor_con;
static void reset_highlight_buffers(struct vc_data *);
-static int read_all_key;
+static enum read_all_command read_all_key;
static int in_keyboard_notifier;
-static void start_read_all_timer(struct vc_data *vc, int command);
-
-enum {
- RA_NOTHING,
- RA_NEXT_SENT,
- RA_PREV_LINE,
- RA_NEXT_LINE,
- RA_PREV_SENT,
- RA_DOWN_ARROW,
- RA_TIMER,
- RA_FIND_NEXT_SENT,
- RA_FIND_PREV_SENT,
-};
+static void start_read_all_timer(struct vc_data *vc, enum read_all_command command);
-static void kbd_fakekey2(struct vc_data *vc, int command)
+static void kbd_fakekey2(struct vc_data *vc, enum read_all_command command)
{
del_timer(&cursor_timer);
speakup_fake_down_arrow();
@@ -1426,7 +1428,7 @@ static void stop_read_all(struct vc_data *vc)
spk_do_flush();
}
-static void start_read_all_timer(struct vc_data *vc, int command)
+static void start_read_all_timer(struct vc_data *vc, enum read_all_command command)
{
struct var_t *cursor_timeout;
@@ -1437,7 +1439,7 @@ static void start_read_all_timer(struct vc_data *vc, int command)
jiffies + msecs_to_jiffies(cursor_timeout->u.n.value));
}
-static void handle_cursor_read_all(struct vc_data *vc, int command)
+static void handle_cursor_read_all(struct vc_data *vc, enum read_all_command command)
{
int indcount, sentcount, rv, sn;
diff --git a/drivers/accessibility/speakup/speakup_dummy.c b/drivers/accessibility/speakup/speakup_dummy.c
index e393438af81b..63c2f2943282 100644
--- a/drivers/accessibility/speakup/speakup_dummy.c
+++ b/drivers/accessibility/speakup/speakup_dummy.c
@@ -80,6 +80,11 @@ static struct attribute *synth_attrs[] = {
NULL, /* need to NULL terminate the list of attributes */
};
+static void read_buff_add(u_char c)
+{
+ pr_info("speakup_dummy: got character %02x\n", c);
+}
+
static struct spk_synth synth_dummy = {
.name = "dummy",
.version = DRV_VERSION,
@@ -103,7 +108,7 @@ static struct spk_synth synth_dummy = {
.flush = spk_synth_flush,
.is_alive = spk_synth_is_alive_restart,
.synth_adjust = NULL,
- .read_buff_add = NULL,
+ .read_buff_add = read_buff_add,
.get_index = NULL,
.indexing = {
.command = NULL,
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index b5117576792b..20b08f52e788 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -68,11 +68,9 @@
#include <linux/sizes.h>
#include <uapi/linux/android/binder.h>
-#include <uapi/linux/android/binderfs.h>
#include <asm/cacheflush.h>
-#include "binder_alloc.h"
#include "binder_internal.h"
#include "binder_trace.h"
@@ -160,24 +158,6 @@ module_param_call(stop_on_user_error, binder_set_stop_on_user_error,
#define to_binder_fd_array_object(hdr) \
container_of(hdr, struct binder_fd_array_object, hdr)
-enum binder_stat_types {
- BINDER_STAT_PROC,
- BINDER_STAT_THREAD,
- BINDER_STAT_NODE,
- BINDER_STAT_REF,
- BINDER_STAT_DEATH,
- BINDER_STAT_TRANSACTION,
- BINDER_STAT_TRANSACTION_COMPLETE,
- BINDER_STAT_COUNT
-};
-
-struct binder_stats {
- atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
- atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
- atomic_t obj_created[BINDER_STAT_COUNT];
- atomic_t obj_deleted[BINDER_STAT_COUNT];
-};
-
static struct binder_stats binder_stats;
static inline void binder_stats_deleted(enum binder_stat_types type)
@@ -213,278 +193,11 @@ static struct binder_transaction_log_entry *binder_transaction_log_add(
return e;
}
-/**
- * struct binder_work - work enqueued on a worklist
- * @entry: node enqueued on list
- * @type: type of work to be performed
- *
- * There are separate work lists for proc, thread, and node (async).
- */
-struct binder_work {
- struct list_head entry;
-
- enum binder_work_type {
- BINDER_WORK_TRANSACTION = 1,
- BINDER_WORK_TRANSACTION_COMPLETE,
- BINDER_WORK_RETURN_ERROR,
- BINDER_WORK_NODE,
- BINDER_WORK_DEAD_BINDER,
- BINDER_WORK_DEAD_BINDER_AND_CLEAR,
- BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
- } type;
-};
-
-struct binder_error {
- struct binder_work work;
- uint32_t cmd;
-};
-
-/**
- * struct binder_node - binder node bookkeeping
- * @debug_id: unique ID for debugging
- * (invariant after initialized)
- * @lock: lock for node fields
- * @work: worklist element for node work
- * (protected by @proc->inner_lock)
- * @rb_node: element for proc->nodes tree
- * (protected by @proc->inner_lock)
- * @dead_node: element for binder_dead_nodes list
- * (protected by binder_dead_nodes_lock)
- * @proc: binder_proc that owns this node
- * (invariant after initialized)
- * @refs: list of references on this node
- * (protected by @lock)
- * @internal_strong_refs: used to take strong references when
- * initiating a transaction
- * (protected by @proc->inner_lock if @proc
- * and by @lock)
- * @local_weak_refs: weak user refs from local process
- * (protected by @proc->inner_lock if @proc
- * and by @lock)
- * @local_strong_refs: strong user refs from local process
- * (protected by @proc->inner_lock if @proc
- * and by @lock)
- * @tmp_refs: temporary kernel refs
- * (protected by @proc->inner_lock while @proc
- * is valid, and by binder_dead_nodes_lock
- * if @proc is NULL. During inc/dec and node release
- * it is also protected by @lock to provide safety
- * as the node dies and @proc becomes NULL)
- * @ptr: userspace pointer for node
- * (invariant, no lock needed)
- * @cookie: userspace cookie for node
- * (invariant, no lock needed)
- * @has_strong_ref: userspace notified of strong ref
- * (protected by @proc->inner_lock if @proc
- * and by @lock)
- * @pending_strong_ref: userspace has acked notification of strong ref
- * (protected by @proc->inner_lock if @proc
- * and by @lock)
- * @has_weak_ref: userspace notified of weak ref
- * (protected by @proc->inner_lock if @proc
- * and by @lock)
- * @pending_weak_ref: userspace has acked notification of weak ref
- * (protected by @proc->inner_lock if @proc
- * and by @lock)
- * @has_async_transaction: async transaction to node in progress
- * (protected by @lock)
- * @accept_fds: file descriptor operations supported for node
- * (invariant after initialized)
- * @min_priority: minimum scheduling priority
- * (invariant after initialized)
- * @txn_security_ctx: require sender's security context
- * (invariant after initialized)
- * @async_todo: list of async work items
- * (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder nodes.
- */
-struct binder_node {
- int debug_id;
- spinlock_t lock;
- struct binder_work work;
- union {
- struct rb_node rb_node;
- struct hlist_node dead_node;
- };
- struct binder_proc *proc;
- struct hlist_head refs;
- int internal_strong_refs;
- int local_weak_refs;
- int local_strong_refs;
- int tmp_refs;
- binder_uintptr_t ptr;
- binder_uintptr_t cookie;
- struct {
- /*
- * bitfield elements protected by
- * proc inner_lock
- */
- u8 has_strong_ref:1;
- u8 pending_strong_ref:1;
- u8 has_weak_ref:1;
- u8 pending_weak_ref:1;
- };
- struct {
- /*
- * invariant after initialization
- */
- u8 accept_fds:1;
- u8 txn_security_ctx:1;
- u8 min_priority;
- };
- bool has_async_transaction;
- struct list_head async_todo;
-};
-
-struct binder_ref_death {
- /**
- * @work: worklist element for death notifications
- * (protected by inner_lock of the proc that
- * this ref belongs to)
- */
- struct binder_work work;
- binder_uintptr_t cookie;
-};
-
-/**
- * struct binder_ref_data - binder_ref counts and id
- * @debug_id: unique ID for the ref
- * @desc: unique userspace handle for ref
- * @strong: strong ref count (debugging only if not locked)
- * @weak: weak ref count (debugging only if not locked)
- *
- * Structure to hold ref count and ref id information. Since
- * the actual ref can only be accessed with a lock, this structure
- * is used to return information about the ref to callers of
- * ref inc/dec functions.
- */
-struct binder_ref_data {
- int debug_id;
- uint32_t desc;
- int strong;
- int weak;
-};
-
-/**
- * struct binder_ref - struct to track references on nodes
- * @data: binder_ref_data containing id, handle, and current refcounts
- * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
- * @rb_node_node: node for lookup by @node in proc's rb_tree
- * @node_entry: list entry for node->refs list in target node
- * (protected by @node->lock)
- * @proc: binder_proc containing ref
- * @node: binder_node of target node. When cleaning up a
- * ref for deletion in binder_cleanup_ref, a non-NULL
- * @node indicates the node must be freed
- * @death: pointer to death notification (ref_death) if requested
- * (protected by @node->lock)
- *
- * Structure to track references from procA to target node (on procB). This
- * structure is unsafe to access without holding @proc->outer_lock.
- */
-struct binder_ref {
- /* Lookups needed: */
- /* node + proc => ref (transaction) */
- /* desc + proc => ref (transaction, inc/dec ref) */
- /* node => refs + procs (proc exit) */
- struct binder_ref_data data;
- struct rb_node rb_node_desc;
- struct rb_node rb_node_node;
- struct hlist_node node_entry;
- struct binder_proc *proc;
- struct binder_node *node;
- struct binder_ref_death *death;
-};
-
enum binder_deferred_state {
BINDER_DEFERRED_FLUSH = 0x01,
BINDER_DEFERRED_RELEASE = 0x02,
};
-/**
- * struct binder_proc - binder process bookkeeping
- * @proc_node: element for binder_procs list
- * @threads: rbtree of binder_threads in this proc
- * (protected by @inner_lock)
- * @nodes: rbtree of binder nodes associated with
- * this proc ordered by node->ptr
- * (protected by @inner_lock)
- * @refs_by_desc: rbtree of refs ordered by ref->desc
- * (protected by @outer_lock)
- * @refs_by_node: rbtree of refs ordered by ref->node
- * (protected by @outer_lock)
- * @waiting_threads: threads currently waiting for proc work
- * (protected by @inner_lock)
- * @pid PID of group_leader of process
- * (invariant after initialized)
- * @tsk task_struct for group_leader of process
- * (invariant after initialized)
- * @deferred_work_node: element for binder_deferred_list
- * (protected by binder_deferred_lock)
- * @deferred_work: bitmap of deferred work to perform
- * (protected by binder_deferred_lock)
- * @is_dead: process is dead and awaiting free
- * when outstanding transactions are cleaned up
- * (protected by @inner_lock)
- * @todo: list of work for this process
- * (protected by @inner_lock)
- * @stats: per-process binder statistics
- * (atomics, no lock needed)
- * @delivered_death: list of delivered death notification
- * (protected by @inner_lock)
- * @max_threads: cap on number of binder threads
- * (protected by @inner_lock)
- * @requested_threads: number of binder threads requested but not
- * yet started. In current implementation, can
- * only be 0 or 1.
- * (protected by @inner_lock)
- * @requested_threads_started: number binder threads started
- * (protected by @inner_lock)
- * @tmp_ref: temporary reference to indicate proc is in use
- * (protected by @inner_lock)
- * @default_priority: default scheduler priority
- * (invariant after initialized)
- * @debugfs_entry: debugfs node
- * @alloc: binder allocator bookkeeping
- * @context: binder_context for this proc
- * (invariant after initialized)
- * @inner_lock: can nest under outer_lock and/or node lock
- * @outer_lock: no nesting under innor or node lock
- * Lock order: 1) outer, 2) node, 3) inner
- * @binderfs_entry: process-specific binderfs log file
- *
- * Bookkeeping structure for binder processes
- */
-struct binder_proc {
- struct hlist_node proc_node;
- struct rb_root threads;
- struct rb_root nodes;
- struct rb_root refs_by_desc;
- struct rb_root refs_by_node;
- struct list_head waiting_threads;
- int pid;
- struct task_struct *tsk;
- struct hlist_node deferred_work_node;
- int deferred_work;
- bool is_dead;
-
- struct list_head todo;
- struct binder_stats stats;
- struct list_head delivered_death;
- int max_threads;
- int requested_threads;
- int requested_threads_started;
- int tmp_ref;
- long default_priority;
- struct dentry *debugfs_entry;
- struct binder_alloc alloc;
- struct binder_context *context;
- spinlock_t inner_lock;
- spinlock_t outer_lock;
- struct dentry *binderfs_entry;
-};
-
enum {
BINDER_LOOPER_STATE_REGISTERED = 0x01,
BINDER_LOOPER_STATE_ENTERED = 0x02,
@@ -495,125 +208,6 @@ enum {
};
/**
- * struct binder_thread - binder thread bookkeeping
- * @proc: binder process for this thread
- * (invariant after initialization)
- * @rb_node: element for proc->threads rbtree
- * (protected by @proc->inner_lock)
- * @waiting_thread_node: element for @proc->waiting_threads list
- * (protected by @proc->inner_lock)
- * @pid: PID for this thread
- * (invariant after initialization)
- * @looper: bitmap of looping state
- * (only accessed by this thread)
- * @looper_needs_return: looping thread needs to exit driver
- * (no lock needed)
- * @transaction_stack: stack of in-progress transactions for this thread
- * (protected by @proc->inner_lock)
- * @todo: list of work to do for this thread
- * (protected by @proc->inner_lock)
- * @process_todo: whether work in @todo should be processed
- * (protected by @proc->inner_lock)
- * @return_error: transaction errors reported by this thread
- * (only accessed by this thread)
- * @reply_error: transaction errors reported by target thread
- * (protected by @proc->inner_lock)
- * @wait: wait queue for thread work
- * @stats: per-thread statistics
- * (atomics, no lock needed)
- * @tmp_ref: temporary reference to indicate thread is in use
- * (atomic since @proc->inner_lock cannot
- * always be acquired)
- * @is_dead: thread is dead and awaiting free
- * when outstanding transactions are cleaned up
- * (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder threads.
- */
-struct binder_thread {
- struct binder_proc *proc;
- struct rb_node rb_node;
- struct list_head waiting_thread_node;
- int pid;
- int looper; /* only modified by this thread */
- bool looper_need_return; /* can be written by other thread */
- struct binder_transaction *transaction_stack;
- struct list_head todo;
- bool process_todo;
- struct binder_error return_error;
- struct binder_error reply_error;
- wait_queue_head_t wait;
- struct binder_stats stats;
- atomic_t tmp_ref;
- bool is_dead;
-};
-
-/**
- * struct binder_txn_fd_fixup - transaction fd fixup list element
- * @fixup_entry: list entry
- * @file: struct file to be associated with new fd
- * @offset: offset in buffer data to this fixup
- *
- * List element for fd fixups in a transaction. Since file
- * descriptors need to be allocated in the context of the
- * target process, we pass each fd to be processed in this
- * struct.
- */
-struct binder_txn_fd_fixup {
- struct list_head fixup_entry;
- struct file *file;
- size_t offset;
-};
-
-struct binder_transaction {
- int debug_id;
- struct binder_work work;
- struct binder_thread *from;
- struct binder_transaction *from_parent;
- struct binder_proc *to_proc;
- struct binder_thread *to_thread;
- struct binder_transaction *to_parent;
- unsigned need_reply:1;
- /* unsigned is_dead:1; */ /* not used at the moment */
-
- struct binder_buffer *buffer;
- unsigned int code;
- unsigned int flags;
- long priority;
- long saved_priority;
- kuid_t sender_euid;
- struct list_head fd_fixups;
- binder_uintptr_t security_ctx;
- /**
- * @lock: protects @from, @to_proc, and @to_thread
- *
- * @from, @to_proc, and @to_thread can be set to NULL
- * during thread teardown
- */
- spinlock_t lock;
-};
-
-/**
- * struct binder_object - union of flat binder object types
- * @hdr: generic object header
- * @fbo: binder object (nodes and refs)
- * @fdo: file descriptor object
- * @bbo: binder buffer pointer
- * @fdao: file descriptor array
- *
- * Used for type-independent object copies
- */
-struct binder_object {
- union {
- struct binder_object_header hdr;
- struct flat_binder_object fbo;
- struct binder_fd_object fdo;
- struct binder_buffer_object bbo;
- struct binder_fd_array_object fdao;
- };
-};
-
-/**
* binder_proc_lock() - Acquire outer lock for given binder_proc
* @proc: struct binder_proc to acquire
*
@@ -1892,6 +1486,20 @@ static void binder_free_txn_fixups(struct binder_transaction *t)
}
}
+static void binder_txn_latency_free(struct binder_transaction *t)
+{
+ int from_proc, from_thread, to_proc, to_thread;
+
+ spin_lock(&t->lock);
+ from_proc = t->from ? t->from->proc->pid : 0;
+ from_thread = t->from ? t->from->pid : 0;
+ to_proc = t->to_proc ? t->to_proc->pid : 0;
+ to_thread = t->to_thread ? t->to_thread->pid : 0;
+ spin_unlock(&t->lock);
+
+ trace_binder_txn_latency_free(t, from_proc, from_thread, to_proc, to_thread);
+}
+
static void binder_free_transaction(struct binder_transaction *t)
{
struct binder_proc *target_proc = t->to_proc;
@@ -1902,6 +1510,8 @@ static void binder_free_transaction(struct binder_transaction *t)
t->buffer->transaction = NULL;
binder_inner_proc_unlock(target_proc);
}
+ if (trace_binder_txn_latency_free_enabled())
+ binder_txn_latency_free(t);
/*
* If the transaction has no target_proc, then
* t->buffer->transaction has already been cleared.
@@ -3103,7 +2713,7 @@ static void binder_transaction(struct binder_proc *proc,
if (extra_buffers_size < added_size) {
/* integer overflow of extra_buffers_size */
return_error = BR_FAILED_REPLY;
- return_error_param = EINVAL;
+ return_error_param = -EINVAL;
return_error_line = __LINE__;
goto err_bad_extra_size;
}
@@ -3479,6 +3089,8 @@ err_get_secctx_failed:
kfree(tcomplete);
binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
err_alloc_tcomplete_failed:
+ if (trace_binder_txn_latency_free_enabled())
+ binder_txn_latency_free(t);
kfree(t);
binder_stats_deleted(BINDER_STAT_TRANSACTION);
err_alloc_t_failed:
@@ -3614,6 +3226,7 @@ static int binder_thread_write(struct binder_proc *proc,
ret = -1;
if (increment && !target) {
struct binder_node *ctx_mgr_node;
+
mutex_lock(&context->context_mgr_node_lock);
ctx_mgr_node = context->binder_context_mgr_node;
if (ctx_mgr_node) {
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index 283d3cb9c16e..6cd79011e35d 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -12,6 +12,8 @@
#include <linux/stddef.h>
#include <linux/types.h>
#include <linux/uidgid.h>
+#include <uapi/linux/android/binderfs.h>
+#include "binder_alloc.h"
struct binder_context {
struct binder_node *binder_context_mgr_node;
@@ -141,6 +143,410 @@ struct binder_transaction_log {
struct binder_transaction_log_entry entry[32];
};
+enum binder_stat_types {
+ BINDER_STAT_PROC,
+ BINDER_STAT_THREAD,
+ BINDER_STAT_NODE,
+ BINDER_STAT_REF,
+ BINDER_STAT_DEATH,
+ BINDER_STAT_TRANSACTION,
+ BINDER_STAT_TRANSACTION_COMPLETE,
+ BINDER_STAT_COUNT
+};
+
+struct binder_stats {
+ atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
+ atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
+ atomic_t obj_created[BINDER_STAT_COUNT];
+ atomic_t obj_deleted[BINDER_STAT_COUNT];
+};
+
+/**
+ * struct binder_work - work enqueued on a worklist
+ * @entry: node enqueued on list
+ * @type: type of work to be performed
+ *
+ * There are separate work lists for proc, thread, and node (async).
+ */
+struct binder_work {
+ struct list_head entry;
+
+ enum binder_work_type {
+ BINDER_WORK_TRANSACTION = 1,
+ BINDER_WORK_TRANSACTION_COMPLETE,
+ BINDER_WORK_RETURN_ERROR,
+ BINDER_WORK_NODE,
+ BINDER_WORK_DEAD_BINDER,
+ BINDER_WORK_DEAD_BINDER_AND_CLEAR,
+ BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
+ } type;
+};
+
+struct binder_error {
+ struct binder_work work;
+ uint32_t cmd;
+};
+
+/**
+ * struct binder_node - binder node bookkeeping
+ * @debug_id: unique ID for debugging
+ * (invariant after initialized)
+ * @lock: lock for node fields
+ * @work: worklist element for node work
+ * (protected by @proc->inner_lock)
+ * @rb_node: element for proc->nodes tree
+ * (protected by @proc->inner_lock)
+ * @dead_node: element for binder_dead_nodes list
+ * (protected by binder_dead_nodes_lock)
+ * @proc: binder_proc that owns this node
+ * (invariant after initialized)
+ * @refs: list of references on this node
+ * (protected by @lock)
+ * @internal_strong_refs: used to take strong references when
+ * initiating a transaction
+ * (protected by @proc->inner_lock if @proc
+ * and by @lock)
+ * @local_weak_refs: weak user refs from local process
+ * (protected by @proc->inner_lock if @proc
+ * and by @lock)
+ * @local_strong_refs: strong user refs from local process
+ * (protected by @proc->inner_lock if @proc
+ * and by @lock)
+ * @tmp_refs: temporary kernel refs
+ * (protected by @proc->inner_lock while @proc
+ * is valid, and by binder_dead_nodes_lock
+ * if @proc is NULL. During inc/dec and node release
+ * it is also protected by @lock to provide safety
+ * as the node dies and @proc becomes NULL)
+ * @ptr: userspace pointer for node
+ * (invariant, no lock needed)
+ * @cookie: userspace cookie for node
+ * (invariant, no lock needed)
+ * @has_strong_ref: userspace notified of strong ref
+ * (protected by @proc->inner_lock if @proc
+ * and by @lock)
+ * @pending_strong_ref: userspace has acked notification of strong ref
+ * (protected by @proc->inner_lock if @proc
+ * and by @lock)
+ * @has_weak_ref: userspace notified of weak ref
+ * (protected by @proc->inner_lock if @proc
+ * and by @lock)
+ * @pending_weak_ref: userspace has acked notification of weak ref
+ * (protected by @proc->inner_lock if @proc
+ * and by @lock)
+ * @has_async_transaction: async transaction to node in progress
+ * (protected by @lock)
+ * @accept_fds: file descriptor operations supported for node
+ * (invariant after initialized)
+ * @min_priority: minimum scheduling priority
+ * (invariant after initialized)
+ * @txn_security_ctx: require sender's security context
+ * (invariant after initialized)
+ * @async_todo: list of async work items
+ * (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder nodes.
+ */
+struct binder_node {
+ int debug_id;
+ spinlock_t lock;
+ struct binder_work work;
+ union {
+ struct rb_node rb_node;
+ struct hlist_node dead_node;
+ };
+ struct binder_proc *proc;
+ struct hlist_head refs;
+ int internal_strong_refs;
+ int local_weak_refs;
+ int local_strong_refs;
+ int tmp_refs;
+ binder_uintptr_t ptr;
+ binder_uintptr_t cookie;
+ struct {
+ /*
+ * bitfield elements protected by
+ * proc inner_lock
+ */
+ u8 has_strong_ref:1;
+ u8 pending_strong_ref:1;
+ u8 has_weak_ref:1;
+ u8 pending_weak_ref:1;
+ };
+ struct {
+ /*
+ * invariant after initialization
+ */
+ u8 accept_fds:1;
+ u8 txn_security_ctx:1;
+ u8 min_priority;
+ };
+ bool has_async_transaction;
+ struct list_head async_todo;
+};
+
+struct binder_ref_death {
+ /**
+ * @work: worklist element for death notifications
+ * (protected by inner_lock of the proc that
+ * this ref belongs to)
+ */
+ struct binder_work work;
+ binder_uintptr_t cookie;
+};
+
+/**
+ * struct binder_ref_data - binder_ref counts and id
+ * @debug_id: unique ID for the ref
+ * @desc: unique userspace handle for ref
+ * @strong: strong ref count (debugging only if not locked)
+ * @weak: weak ref count (debugging only if not locked)
+ *
+ * Structure to hold ref count and ref id information. Since
+ * the actual ref can only be accessed with a lock, this structure
+ * is used to return information about the ref to callers of
+ * ref inc/dec functions.
+ */
+struct binder_ref_data {
+ int debug_id;
+ uint32_t desc;
+ int strong;
+ int weak;
+};
+
+/**
+ * struct binder_ref - struct to track references on nodes
+ * @data: binder_ref_data containing id, handle, and current refcounts
+ * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
+ * @rb_node_node: node for lookup by @node in proc's rb_tree
+ * @node_entry: list entry for node->refs list in target node
+ * (protected by @node->lock)
+ * @proc: binder_proc containing ref
+ * @node: binder_node of target node. When cleaning up a
+ * ref for deletion in binder_cleanup_ref, a non-NULL
+ * @node indicates the node must be freed
+ * @death: pointer to death notification (ref_death) if requested
+ * (protected by @node->lock)
+ *
+ * Structure to track references from procA to target node (on procB). This
+ * structure is unsafe to access without holding @proc->outer_lock.
+ */
+struct binder_ref {
+ /* Lookups needed: */
+ /* node + proc => ref (transaction) */
+ /* desc + proc => ref (transaction, inc/dec ref) */
+ /* node => refs + procs (proc exit) */
+ struct binder_ref_data data;
+ struct rb_node rb_node_desc;
+ struct rb_node rb_node_node;
+ struct hlist_node node_entry;
+ struct binder_proc *proc;
+ struct binder_node *node;
+ struct binder_ref_death *death;
+};
+
+/**
+ * struct binder_proc - binder process bookkeeping
+ * @proc_node: element for binder_procs list
+ * @threads: rbtree of binder_threads in this proc
+ * (protected by @inner_lock)
+ * @nodes: rbtree of binder nodes associated with
+ * this proc ordered by node->ptr
+ * (protected by @inner_lock)
+ * @refs_by_desc: rbtree of refs ordered by ref->desc
+ * (protected by @outer_lock)
+ * @refs_by_node: rbtree of refs ordered by ref->node
+ * (protected by @outer_lock)
+ * @waiting_threads: threads currently waiting for proc work
+ * (protected by @inner_lock)
+ * @pid PID of group_leader of process
+ * (invariant after initialized)
+ * @tsk task_struct for group_leader of process
+ * (invariant after initialized)
+ * @deferred_work_node: element for binder_deferred_list
+ * (protected by binder_deferred_lock)
+ * @deferred_work: bitmap of deferred work to perform
+ * (protected by binder_deferred_lock)
+ * @is_dead: process is dead and awaiting free
+ * when outstanding transactions are cleaned up
+ * (protected by @inner_lock)
+ * @todo: list of work for this process
+ * (protected by @inner_lock)
+ * @stats: per-process binder statistics
+ * (atomics, no lock needed)
+ * @delivered_death: list of delivered death notification
+ * (protected by @inner_lock)
+ * @max_threads: cap on number of binder threads
+ * (protected by @inner_lock)
+ * @requested_threads: number of binder threads requested but not
+ * yet started. In current implementation, can
+ * only be 0 or 1.
+ * (protected by @inner_lock)
+ * @requested_threads_started: number binder threads started
+ * (protected by @inner_lock)
+ * @tmp_ref: temporary reference to indicate proc is in use
+ * (protected by @inner_lock)
+ * @default_priority: default scheduler priority
+ * (invariant after initialized)
+ * @debugfs_entry: debugfs node
+ * @alloc: binder allocator bookkeeping
+ * @context: binder_context for this proc
+ * (invariant after initialized)
+ * @inner_lock: can nest under outer_lock and/or node lock
+ * @outer_lock: no nesting under innor or node lock
+ * Lock order: 1) outer, 2) node, 3) inner
+ * @binderfs_entry: process-specific binderfs log file
+ *
+ * Bookkeeping structure for binder processes
+ */
+struct binder_proc {
+ struct hlist_node proc_node;
+ struct rb_root threads;
+ struct rb_root nodes;
+ struct rb_root refs_by_desc;
+ struct rb_root refs_by_node;
+ struct list_head waiting_threads;
+ int pid;
+ struct task_struct *tsk;
+ struct hlist_node deferred_work_node;
+ int deferred_work;
+ bool is_dead;
+
+ struct list_head todo;
+ struct binder_stats stats;
+ struct list_head delivered_death;
+ int max_threads;
+ int requested_threads;
+ int requested_threads_started;
+ int tmp_ref;
+ long default_priority;
+ struct dentry *debugfs_entry;
+ struct binder_alloc alloc;
+ struct binder_context *context;
+ spinlock_t inner_lock;
+ spinlock_t outer_lock;
+ struct dentry *binderfs_entry;
+};
+
+/**
+ * struct binder_thread - binder thread bookkeeping
+ * @proc: binder process for this thread
+ * (invariant after initialization)
+ * @rb_node: element for proc->threads rbtree
+ * (protected by @proc->inner_lock)
+ * @waiting_thread_node: element for @proc->waiting_threads list
+ * (protected by @proc->inner_lock)
+ * @pid: PID for this thread
+ * (invariant after initialization)
+ * @looper: bitmap of looping state
+ * (only accessed by this thread)
+ * @looper_needs_return: looping thread needs to exit driver
+ * (no lock needed)
+ * @transaction_stack: stack of in-progress transactions for this thread
+ * (protected by @proc->inner_lock)
+ * @todo: list of work to do for this thread
+ * (protected by @proc->inner_lock)
+ * @process_todo: whether work in @todo should be processed
+ * (protected by @proc->inner_lock)
+ * @return_error: transaction errors reported by this thread
+ * (only accessed by this thread)
+ * @reply_error: transaction errors reported by target thread
+ * (protected by @proc->inner_lock)
+ * @wait: wait queue for thread work
+ * @stats: per-thread statistics
+ * (atomics, no lock needed)
+ * @tmp_ref: temporary reference to indicate thread is in use
+ * (atomic since @proc->inner_lock cannot
+ * always be acquired)
+ * @is_dead: thread is dead and awaiting free
+ * when outstanding transactions are cleaned up
+ * (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder threads.
+ */
+struct binder_thread {
+ struct binder_proc *proc;
+ struct rb_node rb_node;
+ struct list_head waiting_thread_node;
+ int pid;
+ int looper; /* only modified by this thread */
+ bool looper_need_return; /* can be written by other thread */
+ struct binder_transaction *transaction_stack;
+ struct list_head todo;
+ bool process_todo;
+ struct binder_error return_error;
+ struct binder_error reply_error;
+ wait_queue_head_t wait;
+ struct binder_stats stats;
+ atomic_t tmp_ref;
+ bool is_dead;
+};
+
+/**
+ * struct binder_txn_fd_fixup - transaction fd fixup list element
+ * @fixup_entry: list entry
+ * @file: struct file to be associated with new fd
+ * @offset: offset in buffer data to this fixup
+ *
+ * List element for fd fixups in a transaction. Since file
+ * descriptors need to be allocated in the context of the
+ * target process, we pass each fd to be processed in this
+ * struct.
+ */
+struct binder_txn_fd_fixup {
+ struct list_head fixup_entry;
+ struct file *file;
+ size_t offset;
+};
+
+struct binder_transaction {
+ int debug_id;
+ struct binder_work work;
+ struct binder_thread *from;
+ struct binder_transaction *from_parent;
+ struct binder_proc *to_proc;
+ struct binder_thread *to_thread;
+ struct binder_transaction *to_parent;
+ unsigned need_reply:1;
+ /* unsigned is_dead:1; */ /* not used at the moment */
+
+ struct binder_buffer *buffer;
+ unsigned int code;
+ unsigned int flags;
+ long priority;
+ long saved_priority;
+ kuid_t sender_euid;
+ struct list_head fd_fixups;
+ binder_uintptr_t security_ctx;
+ /**
+ * @lock: protects @from, @to_proc, and @to_thread
+ *
+ * @from, @to_proc, and @to_thread can be set to NULL
+ * during thread teardown
+ */
+ spinlock_t lock;
+};
+
+/**
+ * struct binder_object - union of flat binder object types
+ * @hdr: generic object header
+ * @fbo: binder object (nodes and refs)
+ * @fdo: file descriptor object
+ * @bbo: binder buffer pointer
+ * @fdao: file descriptor array
+ *
+ * Used for type-independent object copies
+ */
+struct binder_object {
+ union {
+ struct binder_object_header hdr;
+ struct flat_binder_object fbo;
+ struct binder_fd_object fdo;
+ struct binder_buffer_object bbo;
+ struct binder_fd_array_object fdao;
+ };
+};
+
extern struct binder_transaction_log binder_transaction_log;
extern struct binder_transaction_log binder_transaction_log_failed;
#endif /* _LINUX_BINDER_INTERNAL_H */
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 6731c3cd8145..8eeccdc64724 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -95,6 +95,35 @@ TRACE_EVENT(binder_wait_for_work,
__entry->thread_todo)
);
+TRACE_EVENT(binder_txn_latency_free,
+ TP_PROTO(struct binder_transaction *t,
+ int from_proc, int from_thread,
+ int to_proc, int to_thread),
+ TP_ARGS(t, from_proc, from_thread, to_proc, to_thread),
+ TP_STRUCT__entry(
+ __field(int, debug_id)
+ __field(int, from_proc)
+ __field(int, from_thread)
+ __field(int, to_proc)
+ __field(int, to_thread)
+ __field(unsigned int, code)
+ __field(unsigned int, flags)
+ ),
+ TP_fast_assign(
+ __entry->debug_id = t->debug_id;
+ __entry->from_proc = from_proc;
+ __entry->from_thread = from_thread;
+ __entry->to_proc = to_proc;
+ __entry->to_thread = to_thread;
+ __entry->code = t->code;
+ __entry->flags = t->flags;
+ ),
+ TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
+ __entry->debug_id, __entry->from_proc, __entry->from_thread,
+ __entry->to_proc, __entry->to_thread, __entry->code,
+ __entry->flags)
+);
+
TRACE_EVENT(binder_transaction,
TP_PROTO(bool reply, struct binder_transaction *t,
struct binder_node *target_node),
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 0ec73917d8dd..862c2fd933c7 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -622,7 +622,6 @@ static int lp_do_ioctl(unsigned int minor, unsigned int cmd,
break;
case LPSETIRQ:
return -EINVAL;
- break;
case LPGETIRQ:
if (copy_to_user(argp, &LP_IRQ(minor),
sizeof(int)))
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index f6a147427029..ca5141ed5ef3 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -60,7 +60,7 @@ static DEFINE_MUTEX(misc_mtx);
/*
* Assigned numbers, used for dynamic minors
*/
-#define DYNAMIC_MINORS 64 /* like dynamic majors */
+#define DYNAMIC_MINORS 128 /* like dynamic majors */
static DECLARE_BITMAP(misc_minors, DYNAMIC_MINORS);
#ifdef CONFIG_PROC_FS
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index e43c876a9223..11272d605ecd 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -403,7 +403,6 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
default:
return -ENOTTY;
- break;
} /* switch */
PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl, exit retval %x\n", retval);
diff --git a/drivers/firmware/google/gsmi.c b/drivers/firmware/google/gsmi.c
index 7d9367b22010..3d77f26c1e8c 100644
--- a/drivers/firmware/google/gsmi.c
+++ b/drivers/firmware/google/gsmi.c
@@ -17,7 +17,6 @@
#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
@@ -85,7 +84,6 @@
struct gsmi_buf {
u8 *start; /* start of buffer */
size_t length; /* length of buffer */
- dma_addr_t handle; /* dma allocation handle */
u32 address; /* physical address of buffer */
};
@@ -97,7 +95,7 @@ static struct gsmi_device {
spinlock_t lock; /* serialize access to SMIs */
u16 smi_cmd; /* SMI command port */
int handshake_type; /* firmware handler interlock type */
- struct dma_pool *dma_pool; /* DMA buffer pool */
+ struct kmem_cache *mem_pool; /* kmem cache for gsmi_buf allocations */
} gsmi_dev;
/* Packed structures for communicating with the firmware */
@@ -157,8 +155,7 @@ static struct gsmi_buf *gsmi_buf_alloc(void)
}
/* allocate buffer in 32bit address space */
- smibuf->start = dma_pool_alloc(gsmi_dev.dma_pool, GFP_KERNEL,
- &smibuf->handle);
+ smibuf->start = kmem_cache_alloc(gsmi_dev.mem_pool, GFP_KERNEL);
if (!smibuf->start) {
printk(KERN_ERR "gsmi: failed to allocate name buffer\n");
kfree(smibuf);
@@ -176,8 +173,7 @@ static void gsmi_buf_free(struct gsmi_buf *smibuf)
{
if (smibuf) {
if (smibuf->start)
- dma_pool_free(gsmi_dev.dma_pool, smibuf->start,
- smibuf->handle);
+ kmem_cache_free(gsmi_dev.mem_pool, smibuf->start);
kfree(smibuf);
}
}
@@ -914,9 +910,20 @@ static __init int gsmi_init(void)
spin_lock_init(&gsmi_dev.lock);
ret = -ENOMEM;
- gsmi_dev.dma_pool = dma_pool_create("gsmi", &gsmi_dev.pdev->dev,
- GSMI_BUF_SIZE, GSMI_BUF_ALIGN, 0);
- if (!gsmi_dev.dma_pool)
+
+ /*
+ * SLAB cache is created using SLAB_CACHE_DMA32 to ensure that the
+ * allocations for gsmi_buf come from the DMA32 memory zone. These
+ * buffers have nothing to do with DMA. They are required for
+ * communication with firmware executing in SMI mode which can only
+ * access the bottom 4GiB of physical memory. Since DMA32 memory zone
+ * guarantees allocation under the 4GiB boundary, this driver creates
+ * a SLAB cache with SLAB_CACHE_DMA32 flag.
+ */
+ gsmi_dev.mem_pool = kmem_cache_create("gsmi", GSMI_BUF_SIZE,
+ GSMI_BUF_ALIGN,
+ SLAB_CACHE_DMA32, NULL);
+ if (!gsmi_dev.mem_pool)
goto out_err;
/*
@@ -1032,7 +1039,7 @@ out_err:
gsmi_buf_free(gsmi_dev.param_buf);
gsmi_buf_free(gsmi_dev.data_buf);
gsmi_buf_free(gsmi_dev.name_buf);
- dma_pool_destroy(gsmi_dev.dma_pool);
+ kmem_cache_destroy(gsmi_dev.mem_pool);
platform_device_unregister(gsmi_dev.pdev);
pr_info("gsmi: failed to load: %d\n", ret);
#ifdef CONFIG_PM
@@ -1057,7 +1064,7 @@ static void __exit gsmi_exit(void)
gsmi_buf_free(gsmi_dev.param_buf);
gsmi_buf_free(gsmi_dev.data_buf);
gsmi_buf_free(gsmi_dev.name_buf);
- dma_pool_destroy(gsmi_dev.dma_pool);
+ kmem_cache_destroy(gsmi_dev.mem_pool);
platform_device_unregister(gsmi_dev.pdev);
#ifdef CONFIG_PM
platform_driver_unregister(&gsmi_driver_info);
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 2371d08bdd17..30259dc9b805 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Defines interfaces for interacting wtih the Raspberry Pi firmware's
+ * Defines interfaces for interacting with the Raspberry Pi firmware's
* property channel.
*
* Copyright © 2015 Broadcom
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index cc9e8025c533..4ba801dffcb7 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -418,7 +418,7 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode)
if (ret) {
coresight_control_assoc_ectdev(csdev, false);
return ret;
- };
+ }
}
csdev->enable = true;
}
@@ -432,7 +432,7 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode)
* coresight_disable_source - Drop the reference count by 1 and disable
* the device if there are no users left.
*
- * @csdev - The coresight device to disable
+ * @csdev: The coresight device to disable
*
* Returns true if the device has been disabled.
*/
@@ -663,6 +663,9 @@ struct coresight_device *coresight_get_sink_by_id(u32 id)
/**
* coresight_get_ref- Helper function to increase reference count to module
* and device.
+ *
+ * @csdev: The coresight device to get a reference on.
+ *
* Return true in successful case and power up the device.
* Return false when failed to get reference of module.
*/
@@ -682,6 +685,8 @@ static inline bool coresight_get_ref(struct coresight_device *csdev)
/**
* coresight_put_ref- Helper function to decrease reference count to module
* and device. Power off the device.
+ *
+ * @csdev: The coresight device to decrement a reference from.
*/
static inline void coresight_put_ref(struct coresight_device *csdev)
{
@@ -744,6 +749,7 @@ static void coresight_drop_device(struct coresight_device *csdev)
/**
* _coresight_build_path - recursively build a path from a @csdev to a sink.
* @csdev: The device to start from.
+ * @sink: The final sink we want in this path.
* @path: The list to add devices to.
*
* The tree of Coresight device is traversed until an activated sink is
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index 248cc82c838e..1b320ab581ca 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -176,6 +176,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
unsigned long flags;
struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct perf_output_handle *handle = data;
+ struct cs_buffers *buf = etm_perf_sink_config(handle);
spin_lock_irqsave(&drvdata->spinlock, flags);
@@ -186,7 +187,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
}
/* Get a handle on the pid of the process to monitor */
- pid = task_pid_nr(handle->event->owner);
+ pid = buf->pid;
if (drvdata->pid != -1 && drvdata->pid != pid) {
ret = -EBUSY;
@@ -383,6 +384,7 @@ static void *etb_alloc_buffer(struct coresight_device *csdev,
if (!buf)
return NULL;
+ buf->pid = task_pid_nr(event->owner);
buf->snapshot = overwrite;
buf->nr_pages = nr_pages;
buf->data_pages = pages;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index abd706b216ac..d78a37b6592c 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -124,8 +124,8 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
dev_err(etm_dev,
"timeout while waiting for Idle Trace Status\n");
-
- writel_relaxed(config->pe_sel, drvdata->base + TRCPROCSELR);
+ if (drvdata->nr_pe)
+ writel_relaxed(config->pe_sel, drvdata->base + TRCPROCSELR);
writel_relaxed(config->cfg, drvdata->base + TRCCONFIGR);
/* nothing specific implemented */
writel_relaxed(0x0, drvdata->base + TRCAUXCTLR);
@@ -141,8 +141,9 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
writel_relaxed(config->viiectlr, drvdata->base + TRCVIIECTLR);
writel_relaxed(config->vissctlr,
drvdata->base + TRCVISSCTLR);
- writel_relaxed(config->vipcssctlr,
- drvdata->base + TRCVIPCSSCTLR);
+ if (drvdata->nr_pe_cmp)
+ writel_relaxed(config->vipcssctlr,
+ drvdata->base + TRCVIPCSSCTLR);
for (i = 0; i < drvdata->nrseqstate - 1; i++)
writel_relaxed(config->seq_ctrl[i],
drvdata->base + TRCSEQEVRn(i));
@@ -187,13 +188,15 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
writeq_relaxed(config->ctxid_pid[i],
drvdata->base + TRCCIDCVRn(i));
writel_relaxed(config->ctxid_mask0, drvdata->base + TRCCIDCCTLR0);
- writel_relaxed(config->ctxid_mask1, drvdata->base + TRCCIDCCTLR1);
+ if (drvdata->numcidc > 4)
+ writel_relaxed(config->ctxid_mask1, drvdata->base + TRCCIDCCTLR1);
for (i = 0; i < drvdata->numvmidc; i++)
writeq_relaxed(config->vmid_val[i],
drvdata->base + TRCVMIDCVRn(i));
writel_relaxed(config->vmid_mask0, drvdata->base + TRCVMIDCCTLR0);
- writel_relaxed(config->vmid_mask1, drvdata->base + TRCVMIDCCTLR1);
+ if (drvdata->numvmidc > 4)
+ writel_relaxed(config->vmid_mask1, drvdata->base + TRCVMIDCCTLR1);
if (!drvdata->skip_power_up) {
/*
@@ -722,8 +725,13 @@ static void etm4_init_arch_data(void *info)
else
drvdata->sysstall = false;
- /* NUMPROC, bits[30:28] the number of PEs available for tracing */
- drvdata->nr_pe = BMVAL(etmidr3, 28, 30);
+ /*
+ * NUMPROC - the number of PEs available for tracing, 5bits
+ * = TRCIDR3.bits[13:12]bits[30:28]
+ * bits[4:3] = TRCIDR3.bits[13:12] (since etm-v4.2, otherwise RES0)
+ * bits[3:0] = TRCIDR3.bits[30:28]
+ */
+ drvdata->nr_pe = (BMVAL(etmidr3, 12, 13) << 3) | BMVAL(etmidr3, 28, 30);
/* NOOVERFLOW, bit[31] is trace overflow prevention supported */
if (BMVAL(etmidr3, 31, 31))
@@ -779,7 +787,7 @@ static void etm4_init_arch_data(void *info)
* LPOVERRIDE, bit[23] implementation supports
* low-power state override
*/
- if (BMVAL(etmidr5, 23, 23))
+ if (BMVAL(etmidr5, 23, 23) && (!drvdata->skip_power_up))
drvdata->lpoverride = true;
else
drvdata->lpoverride = false;
@@ -1178,7 +1186,8 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
state = drvdata->save_state;
state->trcprgctlr = readl(drvdata->base + TRCPRGCTLR);
- state->trcprocselr = readl(drvdata->base + TRCPROCSELR);
+ if (drvdata->nr_pe)
+ state->trcprocselr = readl(drvdata->base + TRCPROCSELR);
state->trcconfigr = readl(drvdata->base + TRCCONFIGR);
state->trcauxctlr = readl(drvdata->base + TRCAUXCTLR);
state->trceventctl0r = readl(drvdata->base + TRCEVENTCTL0R);
@@ -1194,7 +1203,8 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
state->trcvictlr = readl(drvdata->base + TRCVICTLR);
state->trcviiectlr = readl(drvdata->base + TRCVIIECTLR);
state->trcvissctlr = readl(drvdata->base + TRCVISSCTLR);
- state->trcvipcssctlr = readl(drvdata->base + TRCVIPCSSCTLR);
+ if (drvdata->nr_pe_cmp)
+ state->trcvipcssctlr = readl(drvdata->base + TRCVIPCSSCTLR);
state->trcvdctlr = readl(drvdata->base + TRCVDCTLR);
state->trcvdsacctlr = readl(drvdata->base + TRCVDSACCTLR);
state->trcvdarcctlr = readl(drvdata->base + TRCVDARCCTLR);
@@ -1240,10 +1250,12 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
state->trcvmidcvr[i] = readq(drvdata->base + TRCVMIDCVRn(i));
state->trccidcctlr0 = readl(drvdata->base + TRCCIDCCTLR0);
- state->trccidcctlr1 = readl(drvdata->base + TRCCIDCCTLR1);
+ if (drvdata->numcidc > 4)
+ state->trccidcctlr1 = readl(drvdata->base + TRCCIDCCTLR1);
state->trcvmidcctlr0 = readl(drvdata->base + TRCVMIDCCTLR0);
- state->trcvmidcctlr1 = readl(drvdata->base + TRCVMIDCCTLR1);
+ if (drvdata->numvmidc > 4)
+ state->trcvmidcctlr1 = readl(drvdata->base + TRCVMIDCCTLR1);
state->trcclaimset = readl(drvdata->base + TRCCLAIMCLR);
@@ -1283,7 +1295,8 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
writel_relaxed(state->trcclaimset, drvdata->base + TRCCLAIMSET);
writel_relaxed(state->trcprgctlr, drvdata->base + TRCPRGCTLR);
- writel_relaxed(state->trcprocselr, drvdata->base + TRCPROCSELR);
+ if (drvdata->nr_pe)
+ writel_relaxed(state->trcprocselr, drvdata->base + TRCPROCSELR);
writel_relaxed(state->trcconfigr, drvdata->base + TRCCONFIGR);
writel_relaxed(state->trcauxctlr, drvdata->base + TRCAUXCTLR);
writel_relaxed(state->trceventctl0r, drvdata->base + TRCEVENTCTL0R);
@@ -1299,7 +1312,8 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
writel_relaxed(state->trcvictlr, drvdata->base + TRCVICTLR);
writel_relaxed(state->trcviiectlr, drvdata->base + TRCVIIECTLR);
writel_relaxed(state->trcvissctlr, drvdata->base + TRCVISSCTLR);
- writel_relaxed(state->trcvipcssctlr, drvdata->base + TRCVIPCSSCTLR);
+ if (drvdata->nr_pe_cmp)
+ writel_relaxed(state->trcvipcssctlr, drvdata->base + TRCVIPCSSCTLR);
writel_relaxed(state->trcvdctlr, drvdata->base + TRCVDCTLR);
writel_relaxed(state->trcvdsacctlr, drvdata->base + TRCVDSACCTLR);
writel_relaxed(state->trcvdarcctlr, drvdata->base + TRCVDARCCTLR);
@@ -1350,10 +1364,12 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
drvdata->base + TRCVMIDCVRn(i));
writel_relaxed(state->trccidcctlr0, drvdata->base + TRCCIDCCTLR0);
- writel_relaxed(state->trccidcctlr1, drvdata->base + TRCCIDCCTLR1);
+ if (drvdata->numcidc > 4)
+ writel_relaxed(state->trccidcctlr1, drvdata->base + TRCCIDCCTLR1);
writel_relaxed(state->trcvmidcctlr0, drvdata->base + TRCVMIDCCTLR0);
- writel_relaxed(state->trcvmidcctlr1, drvdata->base + TRCVMIDCCTLR1);
+ if (drvdata->numvmidc > 4)
+ writel_relaxed(state->trcvmidcctlr1, drvdata->base + TRCVMIDCCTLR1);
writel_relaxed(state->trcclaimset, drvdata->base + TRCCLAIMSET);
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
index af40814ce560..39be46b74dfe 100644
--- a/drivers/hwtracing/coresight/coresight-funnel.c
+++ b/drivers/hwtracing/coresight/coresight-funnel.c
@@ -356,7 +356,7 @@ static struct platform_driver static_funnel_driver = {
.remove = static_funnel_remove,
.driver = {
.name = "coresight-static-funnel",
- .owner = THIS_MODULE,
+ /* THIS_MODULE is taken care of by platform_driver_register() */
.of_match_table = static_funnel_match,
.acpi_match_table = ACPI_PTR(static_funnel_ids),
.pm = &funnel_dev_pm_ops,
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 65a29293b6cb..f5f654ea2994 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -87,6 +87,7 @@ enum cs_mode {
* struct cs_buffer - keep track of a recording session' specifics
* @cur: index of the current buffer
* @nr_pages: max number of pages granted to us
+ * @pid: PID this cs_buffer belongs to
* @offset: offset within the current buffer
* @data_size: how much we collected in this run
* @snapshot: is this run in snapshot mode
@@ -95,6 +96,7 @@ enum cs_mode {
struct cs_buffers {
unsigned int cur;
unsigned int nr_pages;
+ pid_t pid;
unsigned long offset;
local_t data_size;
bool snapshot;
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index 62afdde0e5ea..6772f23e5c4b 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -374,7 +374,7 @@ static struct platform_driver static_replicator_driver = {
.remove = static_replicator_remove,
.driver = {
.name = "coresight-static-replicator",
- .owner = THIS_MODULE,
+ /* THIS_MODULE is taken care of by platform_driver_register() */
.of_match_table = of_match_ptr(static_replicator_match),
.acpi_match_table = ACPI_PTR(static_replicator_acpi_ids),
.pm = &replicator_dev_pm_ops,
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
index b0ad912651a9..32d29704206b 100644
--- a/drivers/hwtracing/coresight/coresight-stm.c
+++ b/drivers/hwtracing/coresight/coresight-stm.c
@@ -96,7 +96,7 @@ module_param_named(
boot_nr_channel, boot_nr_channel, int, S_IRUGO
);
-/**
+/*
* struct channel_space - central management entity for extended ports
* @base: memory mapped base address where channels start.
* @phys: physical base address of channel region.
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index 44402d413ebb..989d965f3d90 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -227,6 +227,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct perf_output_handle *handle = data;
+ struct cs_buffers *buf = etm_perf_sink_config(handle);
spin_lock_irqsave(&drvdata->spinlock, flags);
do {
@@ -243,7 +244,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
}
/* Get a handle on the pid of the process to monitor */
- pid = task_pid_nr(handle->event->owner);
+ pid = buf->pid;
if (drvdata->pid != -1 && drvdata->pid != pid) {
ret = -EBUSY;
@@ -399,6 +400,7 @@ static void *tmc_alloc_etf_buffer(struct coresight_device *csdev,
if (!buf)
return NULL;
+ buf->pid = task_pid_nr(event->owner);
buf->snapshot = overwrite;
buf->nr_pages = nr_pages;
buf->data_pages = pages;
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 714f9e867e5f..a31a4d7ae25e 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -217,6 +217,8 @@ static int tmc_pages_alloc(struct tmc_pages *tmc_pages,
} else {
page = alloc_pages_node(node,
GFP_KERNEL | __GFP_ZERO, 0);
+ if (!page)
+ goto err;
}
paddr = dma_map_page(real_dev, page, 0, PAGE_SIZE, dir);
if (dma_mapping_error(real_dev, paddr))
@@ -954,11 +956,11 @@ static void tmc_sync_etr_buf(struct tmc_drvdata *drvdata)
dev_dbg(&drvdata->csdev->dev,
"tmc memory error detected, truncating buffer\n");
etr_buf->len = 0;
- etr_buf->full = 0;
+ etr_buf->full = false;
return;
}
- etr_buf->full = status & TMC_STS_FULL;
+ etr_buf->full = !!(status & TMC_STS_FULL);
WARN_ON(!etr_buf->ops || !etr_buf->ops->sync);
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
index 566c57e03596..010762a46087 100644
--- a/drivers/hwtracing/coresight/coresight-tpiu.c
+++ b/drivers/hwtracing/coresight/coresight-tpiu.c
@@ -49,7 +49,7 @@
DEFINE_CORESIGHT_DEVLIST(tpiu_devs, "tpiu");
-/**
+/*
* @base: memory mapped base address for this component.
* @atclk: optional clock for the core parts of the TPIU.
* @csdev: component vitals needed by the framework.
diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c
index d480a514c983..3940714e4397 100644
--- a/drivers/ipack/devices/ipoctal.c
+++ b/drivers/ipack/devices/ipoctal.c
@@ -544,7 +544,6 @@ static void ipoctal_set_termios(struct tty_struct *tty,
break;
default:
return;
- break;
}
baud = tty_get_baud_rate(tty);
diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c
index 80d87e8a0bea..fb9a1b49ff6d 100644
--- a/drivers/misc/c2port/core.c
+++ b/drivers/misc/c2port/core.c
@@ -899,7 +899,7 @@ struct c2port_device *c2port_device_register(char *name,
unlikely(!ops->c2d_get) || unlikely(!ops->c2d_set))
return ERR_PTR(-EINVAL);
- c2dev = kmalloc(sizeof(struct c2port_device), GFP_KERNEL);
+ c2dev = kzalloc(sizeof(struct c2port_device), GFP_KERNEL);
if (unlikely(!c2dev))
return ERR_PTR(-ENOMEM);
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 3b7d8b7584f4..b76e4901b4a4 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -22,6 +22,9 @@
* mean that some AT25 products are EEPROMs, and others are FLASH.
* Handle FLASH chips with the drivers/mtd/devices/m25p80.c driver,
* not this one!
+ *
+ * EEPROMs that can be used with this driver include, for example:
+ * AT25M02, AT25128B
*/
struct at25_data {
diff --git a/drivers/misc/hisi_hikey_usb.c b/drivers/misc/hisi_hikey_usb.c
index cc93569e601c..989d7d129469 100644
--- a/drivers/misc/hisi_hikey_usb.c
+++ b/drivers/misc/hisi_hikey_usb.c
@@ -168,10 +168,7 @@ static int hisi_hikey_usb_parse_kirin970(struct platform_device *pdev,
hisi_hikey_usb->reset = devm_gpiod_get(&pdev->dev, "hub_reset_en_gpio",
GPIOD_OUT_HIGH);
- if (IS_ERR(hisi_hikey_usb->reset))
- return PTR_ERR(hisi_hikey_usb->reset);
-
- return 0;
+ return PTR_ERR_OR_ZERO(hisi_hikey_usb->reset);
}
static int hisi_hikey_usb_probe(struct platform_device *pdev)
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 9cdaa7f3af23..7fe48baa103a 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -276,7 +276,8 @@ static void mei_cl_bus_rx_work(struct work_struct *work)
cldev->rx_cb(cldev);
mutex_lock(&bus->device_lock);
- mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
+ if (mei_cl_is_connected(cldev->cl))
+ mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
mutex_unlock(&bus->device_lock);
}
@@ -364,10 +365,16 @@ int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb)
INIT_WORK(&cldev->rx_work, mei_cl_bus_rx_work);
mutex_lock(&bus->device_lock);
- ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
+ if (mei_cl_is_connected(cldev->cl))
+ ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
+ else
+ ret = -ENODEV;
mutex_unlock(&bus->device_lock);
- if (ret && ret != -EBUSY)
+ if (ret && ret != -EBUSY) {
+ cancel_work_sync(&cldev->rx_work);
+ cldev->rx_cb = NULL;
return ret;
+ }
return 0;
}
@@ -401,8 +408,11 @@ int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,
mutex_lock(&bus->device_lock);
ret = mei_cl_notify_request(cldev->cl, NULL, 1);
mutex_unlock(&bus->device_lock);
- if (ret)
+ if (ret) {
+ cancel_work_sync(&cldev->notif_work);
+ cldev->notif_cb = NULL;
return ret;
+ }
return 0;
}
@@ -1037,7 +1047,7 @@ static struct mei_cl_device *mei_cl_bus_dev_alloc(struct mei_device *bus,
}
/**
- * mei_cl_dev_setup - setup me client device
+ * mei_cl_bus_dev_setup - setup me client device
* run fix up routines and set the device name
*
* @bus: mei device
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index a97eb5d47705..686e8b6a4c55 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -1377,7 +1377,6 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
dev_info(dev->dev, "hbm: stop response: resetting.\n");
/* force the reset */
return -EPROTO;
- break;
case CLIENT_DISCONNECT_REQ_CMD:
dev_dbg(dev->dev, "hbm: disconnect request: message received\n");
diff --git a/drivers/misc/ocxl/config.c b/drivers/misc/ocxl/config.c
index 4d490b92d951..a68738f38252 100644
--- a/drivers/misc/ocxl/config.c
+++ b/drivers/misc/ocxl/config.c
@@ -73,7 +73,7 @@ static int find_dvsec_afu_ctrl(struct pci_dev *dev, u8 afu_idx)
/**
* get_function_0() - Find a related PCI device (function 0)
- * @device: PCI device to match
+ * @dev: PCI device to match
*
* Returns a pointer to the related device, or null if not found
*/
diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
index 146ca6fb3260..ea9c2c085298 100644
--- a/drivers/misc/pci_endpoint_test.c
+++ b/drivers/misc/pci_endpoint_test.c
@@ -708,7 +708,7 @@ static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
switch (cmd) {
case PCITEST_BAR:
bar = arg;
- if (bar < 0 || bar > 5)
+ if (bar > BAR_5)
goto ret;
if (is_am654_pci_dev(pdev) && bar == BAR_0)
goto ret;
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
index f4ddd1e67015..5a0a5fc3d3ab 100644
--- a/drivers/misc/ti-st/st_core.c
+++ b/drivers/misc/ti-st/st_core.c
@@ -380,7 +380,7 @@ void st_int_recv(void *disc_data,
st_gdata->rx_state = ST_W4_HEADER;
st_gdata->rx_count = st_gdata->list[type]->hdr_len;
pr_debug("rx_count %ld\n", st_gdata->rx_count);
- };
+ }
ptr++;
count--;
}
diff --git a/drivers/misc/uacce/uacce.c b/drivers/misc/uacce/uacce.c
index 56dd98ab5a81..d07af4edfcac 100644
--- a/drivers/misc/uacce/uacce.c
+++ b/drivers/misc/uacce/uacce.c
@@ -231,17 +231,6 @@ static int uacce_fops_mmap(struct file *filep, struct vm_area_struct *vma)
switch (type) {
case UACCE_QFRT_MMIO:
- if (!uacce->ops->mmap) {
- ret = -EINVAL;
- goto out_with_lock;
- }
-
- ret = uacce->ops->mmap(q, vma, qfr);
- if (ret)
- goto out_with_lock;
-
- break;
-
case UACCE_QFRT_DUS:
if (!uacce->ops->mmap) {
ret = -EINVAL;
@@ -533,5 +522,5 @@ subsys_initcall(uacce_init);
module_exit(uacce_exit);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Hisilicon Tech. Co., Ltd.");
+MODULE_AUTHOR("HiSilicon Tech. Co., Ltd.");
MODULE_DESCRIPTION("Accelerator interface for Userland applications");
diff --git a/drivers/misc/xilinx_sdfec.c b/drivers/misc/xilinx_sdfec.c
index 92291292756a..23c8448a9c3b 100644
--- a/drivers/misc/xilinx_sdfec.c
+++ b/drivers/misc/xilinx_sdfec.c
@@ -944,8 +944,8 @@ static long xsdfec_dev_ioctl(struct file *fptr, unsigned int cmd,
unsigned long data)
{
struct xsdfec_dev *xsdfec;
- void __user *arg = NULL;
- int rval = -EINVAL;
+ void __user *arg = (void __user *)data;
+ int rval;
xsdfec = container_of(fptr->private_data, struct xsdfec_dev, miscdev);
@@ -956,16 +956,6 @@ static long xsdfec_dev_ioctl(struct file *fptr, unsigned int cmd,
return -EPERM;
}
- if (_IOC_TYPE(cmd) != XSDFEC_MAGIC)
- return -ENOTTY;
-
- /* check if ioctl argument is present and valid */
- if (_IOC_DIR(cmd) != _IOC_NONE) {
- arg = (void __user *)data;
- if (!arg)
- return rval;
- }
-
switch (cmd) {
case XSDFEC_START_DEV:
rval = xsdfec_start(xsdfec);
@@ -1010,20 +1000,12 @@ static long xsdfec_dev_ioctl(struct file *fptr, unsigned int cmd,
rval = xsdfec_is_active(xsdfec, (bool __user *)arg);
break;
default:
- /* Should not get here */
+ rval = -ENOTTY;
break;
}
return rval;
}
-#ifdef CONFIG_COMPAT
-static long xsdfec_dev_compat_ioctl(struct file *file, unsigned int cmd,
- unsigned long data)
-{
- return xsdfec_dev_ioctl(file, cmd, (unsigned long)compat_ptr(data));
-}
-#endif
-
static __poll_t xsdfec_poll(struct file *file, poll_table *wait)
{
__poll_t mask = 0;
@@ -1054,9 +1036,7 @@ static const struct file_operations xsdfec_fops = {
.release = xsdfec_dev_release,
.unlocked_ioctl = xsdfec_dev_ioctl,
.poll = xsdfec_poll,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = xsdfec_dev_compat_ioctl,
-#endif
+ .compat_ioctl = compat_ptr_ioctl,
};
static int xsdfec_parse_of(struct xsdfec_dev *xsdfec)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index a09ff8409f60..177f5bf27c6d 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -34,6 +34,8 @@ struct nvmem_device {
struct bin_attribute eeprom;
struct device *base_dev;
struct list_head cells;
+ const struct nvmem_keepout *keepout;
+ unsigned int nkeepout;
nvmem_reg_read_t reg_read;
nvmem_reg_write_t reg_write;
struct gpio_desc *wp_gpio;
@@ -66,8 +68,8 @@ static LIST_HEAD(nvmem_lookup_list);
static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
-static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
- void *val, size_t bytes)
+static int __nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
+ void *val, size_t bytes)
{
if (nvmem->reg_read)
return nvmem->reg_read(nvmem->priv, offset, val, bytes);
@@ -75,8 +77,8 @@ static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
return -EINVAL;
}
-static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset,
- void *val, size_t bytes)
+static int __nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset,
+ void *val, size_t bytes)
{
int ret;
@@ -90,6 +92,88 @@ static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset,
return -EINVAL;
}
+static int nvmem_access_with_keepouts(struct nvmem_device *nvmem,
+ unsigned int offset, void *val,
+ size_t bytes, int write)
+{
+
+ unsigned int end = offset + bytes;
+ unsigned int kend, ksize;
+ const struct nvmem_keepout *keepout = nvmem->keepout;
+ const struct nvmem_keepout *keepoutend = keepout + nvmem->nkeepout;
+ int rc;
+
+ /*
+ * Skip all keepouts before the range being accessed.
+ * Keepouts are sorted.
+ */
+ while ((keepout < keepoutend) && (keepout->end <= offset))
+ keepout++;
+
+ while ((offset < end) && (keepout < keepoutend)) {
+ /* Access the valid portion before the keepout. */
+ if (offset < keepout->start) {
+ kend = min(end, keepout->start);
+ ksize = kend - offset;
+ if (write)
+ rc = __nvmem_reg_write(nvmem, offset, val, ksize);
+ else
+ rc = __nvmem_reg_read(nvmem, offset, val, ksize);
+
+ if (rc)
+ return rc;
+
+ offset += ksize;
+ val += ksize;
+ }
+
+ /*
+ * Now we're aligned to the start of this keepout zone. Go
+ * through it.
+ */
+ kend = min(end, keepout->end);
+ ksize = kend - offset;
+ if (!write)
+ memset(val, keepout->value, ksize);
+
+ val += ksize;
+ offset += ksize;
+ keepout++;
+ }
+
+ /*
+ * If we ran out of keepouts but there's still stuff to do, send it
+ * down directly
+ */
+ if (offset < end) {
+ ksize = end - offset;
+ if (write)
+ return __nvmem_reg_write(nvmem, offset, val, ksize);
+ else
+ return __nvmem_reg_read(nvmem, offset, val, ksize);
+ }
+
+ return 0;
+}
+
+static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
+ void *val, size_t bytes)
+{
+ if (!nvmem->nkeepout)
+ return __nvmem_reg_read(nvmem, offset, val, bytes);
+
+ return nvmem_access_with_keepouts(nvmem, offset, val, bytes, false);
+}
+
+static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset,
+ void *val, size_t bytes)
+{
+ if (!nvmem->nkeepout)
+ return __nvmem_reg_write(nvmem, offset, val, bytes);
+
+ return nvmem_access_with_keepouts(nvmem, offset, val, bytes, true);
+}
+
#ifdef CONFIG_NVMEM_SYSFS
static const char * const nvmem_type_str[] = {
[NVMEM_TYPE_UNKNOWN] = "Unknown",
@@ -533,6 +617,59 @@ nvmem_find_cell_by_name(struct nvmem_device *nvmem, const char *cell_id)
return cell;
}
+static int nvmem_validate_keepouts(struct nvmem_device *nvmem)
+{
+ unsigned int cur = 0;
+ const struct nvmem_keepout *keepout = nvmem->keepout;
+ const struct nvmem_keepout *keepoutend = keepout + nvmem->nkeepout;
+
+ while (keepout < keepoutend) {
+ /* Ensure keepouts are sorted and don't overlap. */
+ if (keepout->start < cur) {
+ dev_err(&nvmem->dev,
+ "Keepout regions aren't sorted or overlap.\n");
+
+ return -ERANGE;
+ }
+
+ if (keepout->end < keepout->start) {
+ dev_err(&nvmem->dev,
+ "Invalid keepout region.\n");
+
+ return -EINVAL;
+ }
+
+ /*
+ * Validate keepouts (and holes between) don't violate
+ * word_size constraints.
+ */
+ if ((keepout->end - keepout->start < nvmem->word_size) ||
+ ((keepout->start != cur) &&
+ (keepout->start - cur < nvmem->word_size))) {
+
+ dev_err(&nvmem->dev,
+ "Keepout regions violate word_size constraints.\n");
+
+ return -ERANGE;
+ }
+
+ /* Validate keepouts don't violate stride (alignment). */
+ if (!IS_ALIGNED(keepout->start, nvmem->stride) ||
+ !IS_ALIGNED(keepout->end, nvmem->stride)) {
+
+ dev_err(&nvmem->dev,
+ "Keepout regions violate stride.\n");
+
+ return -EINVAL;
+ }
+
+ cur = keepout->end;
+ keepout++;
+ }
+
+ return 0;
+}
+
static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
{
struct device_node *parent, *child;
@@ -647,6 +784,8 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
nvmem->type = config->type;
nvmem->reg_read = config->reg_read;
nvmem->reg_write = config->reg_write;
+ nvmem->keepout = config->keepout;
+ nvmem->nkeepout = config->nkeepout;
if (!config->no_of_node)
nvmem->dev.of_node = config->dev->of_node;
@@ -671,6 +810,12 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
nvmem->dev.groups = nvmem_dev_groups;
#endif
+ if (nvmem->nkeepout) {
+ rval = nvmem_validate_keepouts(nvmem);
+ if (rval)
+ goto err_put_device;
+ }
+
dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
rval = device_register(&nvmem->dev);
diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c
index 7a1ebd6fd08b..08f41328cc71 100644
--- a/drivers/nvmem/imx-ocotp.c
+++ b/drivers/nvmem/imx-ocotp.c
@@ -4,6 +4,8 @@
*
* Copyright (c) 2015 Pengutronix, Philipp Zabel <p.zabel@pengutronix.de>
*
+ * Copyright 2019 NXP
+ *
* Based on the barebox ocotp driver,
* Copyright (c) 2010 Baruch Siach <baruch@tkos.co.il>,
* Orex Computed Radiography
@@ -158,22 +160,30 @@ static int imx_ocotp_read(void *context, unsigned int offset,
{
struct ocotp_priv *priv = context;
unsigned int count;
- u32 *buf = val;
+ u8 *buf, *p;
int i, ret;
- u32 index;
+ u32 index, num_bytes;
index = offset >> 2;
- count = bytes >> 2;
+ num_bytes = round_up((offset % 4) + bytes, 4);
+ count = num_bytes >> 2;
if (count > (priv->params->nregs - index))
count = priv->params->nregs - index;
+ p = kzalloc(num_bytes, GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
mutex_lock(&ocotp_mutex);
+ buf = p;
+
ret = clk_prepare_enable(priv->clk);
if (ret < 0) {
mutex_unlock(&ocotp_mutex);
dev_err(priv->dev, "failed to prepare/enable ocotp clk\n");
+ kfree(p);
return ret;
}
@@ -184,7 +194,7 @@ static int imx_ocotp_read(void *context, unsigned int offset,
}
for (i = index; i < (index + count); i++) {
- *buf++ = readl(priv->base + IMX_OCOTP_OFFSET_B0W0 +
+ *(u32 *)buf = readl(priv->base + IMX_OCOTP_OFFSET_B0W0 +
i * IMX_OCOTP_OFFSET_PER_WORD);
/* 47.3.1.2
@@ -193,13 +203,21 @@ static int imx_ocotp_read(void *context, unsigned int offset,
* software before any new write, read or reload access can be
* issued
*/
- if (*(buf - 1) == IMX_OCOTP_READ_LOCKED_VAL)
+ if (*((u32 *)buf) == IMX_OCOTP_READ_LOCKED_VAL)
imx_ocotp_clr_err_if_set(priv);
+
+ buf += 4;
}
+ index = offset % 4;
+ memcpy(val, &p[index], bytes);
+
read_end:
clk_disable_unprepare(priv->clk);
mutex_unlock(&ocotp_mutex);
+
+ kfree(p);
+
return ret;
}
@@ -447,7 +465,7 @@ static struct nvmem_config imx_ocotp_nvmem_config = {
.name = "imx-ocotp",
.read_only = false,
.word_size = 4,
- .stride = 4,
+ .stride = 1,
.reg_read = imx_ocotp_read,
.reg_write = imx_ocotp_write,
};
diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
index 5e9e60e2e591..6cace24dfbf7 100644
--- a/drivers/nvmem/qfprom.c
+++ b/drivers/nvmem/qfprom.c
@@ -12,6 +12,7 @@
#include <linux/mod_devicetable.h>
#include <linux/nvmem-provider.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/regulator/consumer.h>
/* Blow timer clock frequency in Mhz */
@@ -89,6 +90,28 @@ struct qfprom_touched_values {
};
/**
+ * struct qfprom_soc_compatible_data - Data matched against the SoC
+ * compatible string.
+ *
+ * @keepout: Array of keepout regions for this SoC.
+ * @nkeepout: Number of elements in the keepout array.
+ */
+struct qfprom_soc_compatible_data {
+ const struct nvmem_keepout *keepout;
+ unsigned int nkeepout;
+};
+
+static const struct nvmem_keepout sc7180_qfprom_keepout[] = {
+ {.start = 0x128, .end = 0x148},
+ {.start = 0x220, .end = 0x228}
+};
+
+static const struct qfprom_soc_compatible_data sc7180_qfprom = {
+ .keepout = sc7180_qfprom_keepout,
+ .nkeepout = ARRAY_SIZE(sc7180_qfprom_keepout)
+};
+
+/**
* qfprom_disable_fuse_blowing() - Undo enabling of fuse blowing.
* @priv: Our driver data.
* @old: The data that was stashed from before fuse blowing.
@@ -281,6 +304,7 @@ static int qfprom_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct resource *res;
struct nvmem_device *nvmem;
+ const struct qfprom_soc_compatible_data *soc_data;
struct qfprom_priv *priv;
int ret;
@@ -299,6 +323,11 @@ static int qfprom_probe(struct platform_device *pdev)
econfig.priv = priv;
priv->dev = dev;
+ soc_data = device_get_match_data(dev);
+ if (soc_data) {
+ econfig.keepout = soc_data->keepout;
+ econfig.nkeepout = soc_data->nkeepout;
+ }
/*
* If more than one region is provided then the OS has the ability
@@ -354,6 +383,7 @@ static int qfprom_probe(struct platform_device *pdev)
static const struct of_device_id qfprom_of_match[] = {
{ .compatible = "qcom,qfprom",},
+ { .compatible = "qcom,sc7180-qfprom", .data = &sc7180_qfprom},
{/* sentinel */},
};
MODULE_DEVICE_TABLE(of, qfprom_of_match);
diff --git a/drivers/slimbus/Kconfig b/drivers/slimbus/Kconfig
index 8cd595148d17..7d59956b5dfb 100644
--- a/drivers/slimbus/Kconfig
+++ b/drivers/slimbus/Kconfig
@@ -22,9 +22,11 @@ config SLIM_QCOM_CTRL
config SLIM_QCOM_NGD_CTRL
tristate "Qualcomm SLIMbus Satellite Non-Generic Device Component"
- depends on HAS_IOMEM && DMA_ENGINE && NET
+ depends on HAS_IOMEM && DMA_ENGINE && NET && REMOTEPROC
depends on ARCH_QCOM || COMPILE_TEST
select QCOM_QMI_HELPERS
+ select QCOM_RPROC_COMMON
+ select QCOM_PDR_HELPERS
help
Select driver if Qualcomm's SLIMbus Satellite Non-Generic Device
Component is programmed using Linux kernel.
diff --git a/drivers/slimbus/messaging.c b/drivers/slimbus/messaging.c
index d5879142dbef..f2b5d347d227 100644
--- a/drivers/slimbus/messaging.c
+++ b/drivers/slimbus/messaging.c
@@ -258,6 +258,7 @@ int slim_xfer_msg(struct slim_device *sbdev, struct slim_val_inf *msg,
case SLIM_MSG_MC_REQUEST_CLEAR_INFORMATION:
case SLIM_MSG_MC_CLEAR_INFORMATION:
txn->rl += msg->num_bytes;
+ break;
default:
break;
}
diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c
index 218aefc3531c..c054e83ab636 100644
--- a/drivers/slimbus/qcom-ngd-ctrl.c
+++ b/drivers/slimbus/qcom-ngd-ctrl.c
@@ -13,9 +13,13 @@
#include <linux/slimbus.h>
#include <linux/delay.h>
#include <linux/pm_runtime.h>
+#include <linux/mutex.h>
+#include <linux/notifier.h>
+#include <linux/remoteproc/qcom_rproc.h>
#include <linux/of.h>
#include <linux/io.h>
#include <linux/soc/qcom/qmi.h>
+#include <linux/soc/qcom/pdr.h>
#include <net/sock.h>
#include "slimbus.h"
@@ -155,8 +159,15 @@ struct qcom_slim_ngd_ctrl {
struct qcom_slim_ngd_dma_desc txdesc[QCOM_SLIM_NGD_DESC_NUM];
struct completion reconf;
struct work_struct m_work;
+ struct work_struct ngd_up_work;
struct workqueue_struct *mwq;
+ struct completion qmi_up;
spinlock_t tx_buf_lock;
+ struct mutex tx_lock;
+ struct mutex ssr_lock;
+ struct notifier_block nb;
+ void *notifier;
+ struct pdr_handle *pdr;
enum qcom_slim_ngd_state state;
dma_addr_t rx_phys_base;
dma_addr_t tx_phys_base;
@@ -423,7 +434,7 @@ static int qcom_slim_qmi_send_power_request(struct qcom_slim_ngd_ctrl *ctrl,
return 0;
}
-static struct qmi_msg_handler qcom_slim_qmi_msg_handlers[] = {
+static const struct qmi_msg_handler qcom_slim_qmi_msg_handlers[] = {
{
.type = QMI_RESPONSE,
.msg_id = SLIMBUS_QMI_POWER_RESP_V01,
@@ -678,7 +689,6 @@ static int qcom_slim_ngd_init_rx_msgq(struct qcom_slim_ngd_ctrl *ctrl)
ctrl->rx_base = dma_alloc_coherent(dev, size, &ctrl->rx_phys_base,
GFP_KERNEL);
if (!ctrl->rx_base) {
- dev_err(dev, "dma_alloc_coherent failed\n");
ret = -ENOMEM;
goto rel_rx;
}
@@ -717,7 +727,6 @@ static int qcom_slim_ngd_init_tx_msgq(struct qcom_slim_ngd_ctrl *ctrl)
ctrl->tx_base = dma_alloc_coherent(dev, size, &ctrl->tx_phys_base,
GFP_KERNEL);
if (!ctrl->tx_base) {
- dev_err(dev, "dma_alloc_coherent failed\n");
ret = -EINVAL;
goto rel_tx;
}
@@ -868,14 +877,18 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,
if (txn->msg && txn->msg->wbuf)
memcpy(puc, txn->msg->wbuf, txn->msg->num_bytes);
+ mutex_lock(&ctrl->tx_lock);
ret = qcom_slim_ngd_tx_msg_post(ctrl, pbuf, txn->rl);
- if (ret)
+ if (ret) {
+ mutex_unlock(&ctrl->tx_lock);
return ret;
+ }
timeout = wait_for_completion_timeout(&tx_sent, HZ);
if (!timeout) {
dev_err(sctrl->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc,
txn->mt);
+ mutex_unlock(&ctrl->tx_lock);
return -ETIMEDOUT;
}
@@ -884,10 +897,12 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,
if (!timeout) {
dev_err(sctrl->dev, "TX timed out:MC:0x%x,mt:0x%x",
txn->mc, txn->mt);
+ mutex_unlock(&ctrl->tx_lock);
return -ETIMEDOUT;
}
}
+ mutex_unlock(&ctrl->tx_lock);
return 0;
}
@@ -1200,11 +1215,21 @@ capability_retry:
}
}
+static int qcom_slim_ngd_update_device_status(struct device *dev, void *null)
+{
+ slim_report_absent(to_slim_device(dev));
+
+ return 0;
+}
+
static int qcom_slim_ngd_runtime_resume(struct device *dev)
{
struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev);
int ret = 0;
+ if (!ctrl->qmi.handle)
+ return 0;
+
if (ctrl->state >= QCOM_SLIM_NGD_CTRL_ASLEEP)
ret = qcom_slim_ngd_power_up(ctrl);
if (ret) {
@@ -1267,7 +1292,7 @@ static int qcom_slim_ngd_qmi_new_server(struct qmi_handle *hdl,
qmi->svc_info.sq_node = service->node;
qmi->svc_info.sq_port = service->port;
- qcom_slim_ngd_enable(ctrl, true);
+ complete(&ctrl->qmi_up);
return 0;
}
@@ -1280,13 +1305,12 @@ static void qcom_slim_ngd_qmi_del_server(struct qmi_handle *hdl,
struct qcom_slim_ngd_ctrl *ctrl =
container_of(qmi, struct qcom_slim_ngd_ctrl, qmi);
+ reinit_completion(&ctrl->qmi_up);
qmi->svc_info.sq_node = 0;
qmi->svc_info.sq_port = 0;
-
- qcom_slim_ngd_enable(ctrl, false);
}
-static struct qmi_ops qcom_slim_ngd_qmi_svc_event_ops = {
+static const struct qmi_ops qcom_slim_ngd_qmi_svc_event_ops = {
.new_server = qcom_slim_ngd_qmi_new_server,
.del_server = qcom_slim_ngd_qmi_del_server,
};
@@ -1333,6 +1357,72 @@ static const struct of_device_id qcom_slim_ngd_dt_match[] = {
MODULE_DEVICE_TABLE(of, qcom_slim_ngd_dt_match);
+static void qcom_slim_ngd_down(struct qcom_slim_ngd_ctrl *ctrl)
+{
+ mutex_lock(&ctrl->ssr_lock);
+ device_for_each_child(ctrl->ctrl.dev, NULL,
+ qcom_slim_ngd_update_device_status);
+ qcom_slim_ngd_enable(ctrl, false);
+ mutex_unlock(&ctrl->ssr_lock);
+}
+
+static void qcom_slim_ngd_up_worker(struct work_struct *work)
+{
+ struct qcom_slim_ngd_ctrl *ctrl;
+
+ ctrl = container_of(work, struct qcom_slim_ngd_ctrl, ngd_up_work);
+
+ /* Make sure qmi service is up before continuing */
+ wait_for_completion_interruptible(&ctrl->qmi_up);
+
+ mutex_lock(&ctrl->ssr_lock);
+ qcom_slim_ngd_enable(ctrl, true);
+ mutex_unlock(&ctrl->ssr_lock);
+}
+
+static int qcom_slim_ngd_ssr_pdr_notify(struct qcom_slim_ngd_ctrl *ctrl,
+ unsigned long action)
+{
+ switch (action) {
+ case QCOM_SSR_BEFORE_SHUTDOWN:
+ case SERVREG_SERVICE_STATE_DOWN:
+ /* Make sure the last dma xfer is finished */
+ mutex_lock(&ctrl->tx_lock);
+ if (ctrl->state != QCOM_SLIM_NGD_CTRL_DOWN) {
+ pm_runtime_get_noresume(ctrl->dev);
+ ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
+ qcom_slim_ngd_down(ctrl);
+ qcom_slim_ngd_exit_dma(ctrl);
+ }
+ mutex_unlock(&ctrl->tx_lock);
+ break;
+ case QCOM_SSR_AFTER_POWERUP:
+ case SERVREG_SERVICE_STATE_UP:
+ schedule_work(&ctrl->ngd_up_work);
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static int qcom_slim_ngd_ssr_notify(struct notifier_block *nb,
+ unsigned long action,
+ void *data)
+{
+ struct qcom_slim_ngd_ctrl *ctrl = container_of(nb,
+ struct qcom_slim_ngd_ctrl, nb);
+
+ return qcom_slim_ngd_ssr_pdr_notify(ctrl, action);
+}
+
+static void slim_pd_status(int state, char *svc_path, void *priv)
+{
+ struct qcom_slim_ngd_ctrl *ctrl = (struct qcom_slim_ngd_ctrl *)priv;
+
+ qcom_slim_ngd_ssr_pdr_notify(ctrl, state);
+}
static int of_qcom_slim_ngd_register(struct device *parent,
struct qcom_slim_ngd_ctrl *ctrl)
{
@@ -1397,6 +1487,7 @@ static int qcom_slim_ngd_probe(struct platform_device *pdev)
}
INIT_WORK(&ctrl->m_work, qcom_slim_ngd_master_worker);
+ INIT_WORK(&ctrl->ngd_up_work, qcom_slim_ngd_up_worker);
ctrl->mwq = create_singlethread_workqueue("ngd_master");
if (!ctrl->mwq) {
dev_err(&pdev->dev, "Failed to start master worker\n");
@@ -1419,6 +1510,7 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
struct qcom_slim_ngd_ctrl *ctrl;
struct resource *res;
int ret;
+ struct pdr_service *pds;
ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
if (!ctrl)
@@ -1444,6 +1536,11 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
return ret;
}
+ ctrl->nb.notifier_call = qcom_slim_ngd_ssr_notify;
+ ctrl->notifier = qcom_register_ssr_notifier("lpass", &ctrl->nb);
+ if (IS_ERR(ctrl->notifier))
+ return PTR_ERR(ctrl->notifier);
+
ctrl->dev = dev;
ctrl->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
ctrl->framer.superfreq =
@@ -1457,9 +1554,24 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
ctrl->ctrl.wakeup = NULL;
ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
+ mutex_init(&ctrl->tx_lock);
+ mutex_init(&ctrl->ssr_lock);
spin_lock_init(&ctrl->tx_buf_lock);
init_completion(&ctrl->reconf);
init_completion(&ctrl->qmi.qmi_comp);
+ init_completion(&ctrl->qmi_up);
+
+ ctrl->pdr = pdr_handle_alloc(slim_pd_status, ctrl);
+ if (IS_ERR(ctrl->pdr)) {
+ dev_err(dev, "Failed to init PDR handle\n");
+ return PTR_ERR(ctrl->pdr);
+ }
+
+ pds = pdr_add_lookup(ctrl->pdr, "avs/audio", "msm/adsp/audio_pd");
+ if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) {
+ dev_err(dev, "pdr add lookup failed: %d\n", ret);
+ return PTR_ERR(pds);
+ }
platform_driver_register(&qcom_slim_ngd_driver);
return of_qcom_slim_ngd_register(dev, ctrl);
@@ -1477,6 +1589,8 @@ static int qcom_slim_ngd_remove(struct platform_device *pdev)
struct qcom_slim_ngd_ctrl *ctrl = platform_get_drvdata(pdev);
pm_runtime_disable(&pdev->dev);
+ pdr_handle_release(ctrl->pdr);
+ qcom_unregister_ssr_notifier(ctrl->notifier, &ctrl->nb);
qcom_slim_ngd_enable(ctrl, false);
qcom_slim_ngd_exit_dma(ctrl);
qcom_slim_ngd_qmi_svc_event_deinit(&ctrl->qmi);
@@ -1503,6 +1617,9 @@ static int __maybe_unused qcom_slim_ngd_runtime_suspend(struct device *dev)
struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev);
int ret = 0;
+ if (!ctrl->qmi.handle)
+ return 0;
+
ret = qcom_slim_qmi_power_request(ctrl, false);
if (ret && ret != -EBUSY)
dev_info(ctrl->dev, "slim resource not idle:%d\n", ret);
diff --git a/drivers/slimbus/slimbus.h b/drivers/slimbus/slimbus.h
index c73035915f1d..00a7f112574b 100644
--- a/drivers/slimbus/slimbus.h
+++ b/drivers/slimbus/slimbus.h
@@ -244,7 +244,7 @@ enum slim_ch_data_fmt {
};
/**
- * enum slim_ch_aux_fmt: SLIMbus channel Aux Field format IDs according to
+ * enum slim_ch_aux_bit_fmt: SLIMbus channel Aux Field format IDs according to
* Table 63 of SLIMbus Spec 2.0
* @SLIM_CH_AUX_FMT_NOT_APPLICABLE: Undefined
* @SLIM_CH_AUX_FMT_ZCUV_TUNNEL_IEC60958: ZCUV for tunneling IEC60958
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index be06f1a961c2..ea96e319c8a0 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -906,7 +906,7 @@ static void uio_device_release(struct device *dev)
}
/**
- * uio_register_device - register a new userspace IO device
+ * __uio_register_device - register a new userspace IO device
* @owner: module that creates the new device
* @parent: parent device
* @info: UIO device capabilities
@@ -1002,7 +1002,7 @@ static void devm_uio_unregister_device(struct device *dev, void *res)
}
/**
- * devm_uio_register_device - Resource managed uio_register_device()
+ * __devm_uio_register_device - Resource managed uio_register_device()
* @owner: module that creates the new device
* @parent: parent device
* @info: UIO device capabilities
diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c
index dde5cbb27178..1c6c09e1280d 100644
--- a/drivers/uio/uio_pci_generic.c
+++ b/drivers/uio/uio_pci_generic.c
@@ -74,23 +74,19 @@ static int probe(struct pci_dev *pdev,
struct uio_pci_generic_dev *gdev;
int err;
- err = pci_enable_device(pdev);
+ err = pcim_enable_device(pdev);
if (err) {
dev_err(&pdev->dev, "%s: pci_enable_device failed: %d\n",
__func__, err);
return err;
}
- if (pdev->irq && !pci_intx_mask_supported(pdev)) {
- err = -ENODEV;
- goto err_verify;
- }
+ if (pdev->irq && !pci_intx_mask_supported(pdev))
+ return -ENOMEM;
- gdev = kzalloc(sizeof(struct uio_pci_generic_dev), GFP_KERNEL);
- if (!gdev) {
- err = -ENOMEM;
- goto err_alloc;
- }
+ gdev = devm_kzalloc(&pdev->dev, sizeof(struct uio_pci_generic_dev), GFP_KERNEL);
+ if (!gdev)
+ return -ENOMEM;
gdev->info.name = "uio_pci_generic";
gdev->info.version = DRIVER_VERSION;
@@ -105,34 +101,19 @@ static int probe(struct pci_dev *pdev,
"no support for interrupts?\n");
}
- err = uio_register_device(&pdev->dev, &gdev->info);
+ err = devm_uio_register_device(&pdev->dev, &gdev->info);
if (err)
- goto err_register;
+ return err;
+
pci_set_drvdata(pdev, gdev);
return 0;
-err_register:
- kfree(gdev);
-err_alloc:
-err_verify:
- pci_disable_device(pdev);
- return err;
-}
-
-static void remove(struct pci_dev *pdev)
-{
- struct uio_pci_generic_dev *gdev = pci_get_drvdata(pdev);
-
- uio_unregister_device(&gdev->info);
- pci_disable_device(pdev);
- kfree(gdev);
}
static struct pci_driver uio_pci_driver = {
.name = "uio_pci_generic",
.id_table = NULL, /* only dynamic id's */
.probe = probe,
- .remove = remove,
};
module_pci_driver(uio_pci_driver);
diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
index 1cc175d3c25c..41470c4dba02 100644
--- a/drivers/uio/uio_pruss.c
+++ b/drivers/uio/uio_pruss.c
@@ -99,7 +99,6 @@ static void pruss_cleanup(struct device *dev, struct uio_pruss_dev *gdev)
for (cnt = 0; cnt < MAX_PRUSS_EVT; cnt++, p++) {
uio_unregister_device(p);
- kfree(p->name);
}
iounmap(gdev->prussio_vaddr);
if (gdev->ddr_vaddr) {
@@ -110,10 +109,8 @@ static void pruss_cleanup(struct device *dev, struct uio_pruss_dev *gdev)
gen_pool_free(gdev->sram_pool,
gdev->sram_vaddr,
sram_pool_sz);
- kfree(gdev->info);
clk_disable(gdev->pruss_clk);
clk_put(gdev->pruss_clk);
- kfree(gdev);
}
static int pruss_probe(struct platform_device *pdev)
@@ -125,22 +122,19 @@ static int pruss_probe(struct platform_device *pdev)
int ret, cnt, i, len;
struct uio_pruss_pdata *pdata = dev_get_platdata(dev);
- gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL);
+ gdev = devm_kzalloc(dev, sizeof(struct uio_pruss_dev), GFP_KERNEL);
if (!gdev)
return -ENOMEM;
- gdev->info = kcalloc(MAX_PRUSS_EVT, sizeof(*p), GFP_KERNEL);
- if (!gdev->info) {
- ret = -ENOMEM;
- goto err_free_gdev;
- }
+ gdev->info = devm_kcalloc(dev, MAX_PRUSS_EVT, sizeof(*p), GFP_KERNEL);
+ if (!gdev->info)
+ return -ENOMEM;
/* Power on PRU in case its not done as part of boot-loader */
gdev->pruss_clk = clk_get(dev, "pruss");
if (IS_ERR(gdev->pruss_clk)) {
dev_err(dev, "Failed to get clock\n");
- ret = PTR_ERR(gdev->pruss_clk);
- goto err_free_info;
+ return PTR_ERR(gdev->pruss_clk);
}
ret = clk_enable(gdev->pruss_clk);
@@ -206,7 +200,7 @@ static int pruss_probe(struct platform_device *pdev)
p->mem[2].size = extram_pool_sz;
p->mem[2].memtype = UIO_MEM_PHYS;
- p->name = kasprintf(GFP_KERNEL, "pruss_evt%d", cnt);
+ p->name = devm_kasprintf(dev, GFP_KERNEL, "pruss_evt%d", cnt);
p->version = DRV_VERSION;
/* Register PRUSS IRQ lines */
@@ -215,10 +209,8 @@ static int pruss_probe(struct platform_device *pdev)
p->priv = gdev;
ret = uio_register_device(dev, p);
- if (ret < 0) {
- kfree(p->name);
+ if (ret < 0)
goto err_unloop;
- }
}
platform_set_drvdata(pdev, gdev);
@@ -227,7 +219,6 @@ static int pruss_probe(struct platform_device *pdev)
err_unloop:
for (i = 0, p = gdev->info; i < cnt; i++, p++) {
uio_unregister_device(p);
- kfree(p->name);
}
iounmap(gdev->prussio_vaddr);
err_free_ddr_vaddr:
@@ -240,10 +231,6 @@ err_clk_disable:
clk_disable(gdev->pruss_clk);
err_clk_put:
clk_put(gdev->pruss_clk);
-err_free_info:
- kfree(gdev->info);
-err_free_gdev:
- kfree(gdev);
return ret;
}
diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c
index 50ae26977a02..1227ea937059 100644
--- a/drivers/vme/bridges/vme_tsi148.c
+++ b/drivers/vme/bridges/vme_tsi148.c
@@ -506,7 +506,6 @@ static int tsi148_slave_set(struct vme_slave_resource *image, int enabled,
default:
dev_err(tsi148_bridge->parent, "Invalid address space\n");
return -EINVAL;
- break;
}
/* Convert 64-bit variables to 2x 32-bit variables */
@@ -995,7 +994,6 @@ static int tsi148_master_set(struct vme_master_resource *image, int enabled,
dev_err(tsi148_bridge->parent, "Invalid address space\n");
retval = -EINVAL;
goto err_aspace;
- break;
}
temp_ctl &= ~(3<<4);
@@ -1503,7 +1501,6 @@ static int tsi148_dma_set_vme_src_attributes(struct device *dev, __be32 *attr,
default:
dev_err(dev, "Invalid address space\n");
return -EINVAL;
- break;
}
if (cycle & VME_SUPER)
@@ -1603,7 +1600,6 @@ static int tsi148_dma_set_vme_dest_attributes(struct device *dev, __be32 *attr,
default:
dev_err(dev, "Invalid address space\n");
return -EINVAL;
- break;
}
if (cycle & VME_SUPER)
@@ -1701,7 +1697,6 @@ static int tsi148_dma_list_add(struct vme_dma_list *list,
dev_err(tsi148_bridge->parent, "Invalid source type\n");
retval = -EINVAL;
goto err_source;
- break;
}
/* Assume last link - this will be over-written by adding another */
@@ -1738,7 +1733,6 @@ static int tsi148_dma_list_add(struct vme_dma_list *list,
dev_err(tsi148_bridge->parent, "Invalid destination type\n");
retval = -EINVAL;
goto err_dest;
- break;
}
/* Fill out count */
@@ -1964,7 +1958,6 @@ static int tsi148_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base,
mutex_unlock(&lm->mtx);
dev_err(tsi148_bridge->parent, "Invalid address space\n");
return -EINVAL;
- break;
}
if (cycle & VME_SUPER)
diff --git a/drivers/vme/vme.c b/drivers/vme/vme.c
index b398293980b6..54d7963c1078 100644
--- a/drivers/vme/vme.c
+++ b/drivers/vme/vme.c
@@ -52,28 +52,23 @@ static struct vme_bridge *find_bridge(struct vme_resource *resource)
case VME_MASTER:
return list_entry(resource->entry, struct vme_master_resource,
list)->parent;
- break;
case VME_SLAVE:
return list_entry(resource->entry, struct vme_slave_resource,
list)->parent;
- break;
case VME_DMA:
return list_entry(resource->entry, struct vme_dma_resource,
list)->parent;
- break;
case VME_LM:
return list_entry(resource->entry, struct vme_lm_resource,
list)->parent;
- break;
default:
printk(KERN_ERR "Unknown resource type\n");
return NULL;
- break;
}
}
/**
- * vme_free_consistent - Allocate contiguous memory.
+ * vme_alloc_consistent - Allocate contiguous memory.
* @resource: Pointer to VME resource.
* @size: Size of allocation required.
* @dma: Pointer to variable to store physical address of allocation.
@@ -179,7 +174,6 @@ size_t vme_get_size(struct vme_resource *resource)
return 0;
return size;
- break;
case VME_SLAVE:
retval = vme_slave_get(resource, &enabled, &base, &size,
&buf_base, &aspace, &cycle);
@@ -187,14 +181,11 @@ size_t vme_get_size(struct vme_resource *resource)
return 0;
return size;
- break;
case VME_DMA:
return 0;
- break;
default:
printk(KERN_ERR "Unknown resource type\n");
return 0;
- break;
}
}
EXPORT_SYMBOL(vme_get_size);
@@ -647,7 +638,7 @@ int vme_master_get(struct vme_resource *resource, int *enabled,
EXPORT_SYMBOL(vme_master_get);
/**
- * vme_master_write - Read data from VME space into a buffer.
+ * vme_master_read - Read data from VME space into a buffer.
* @resource: Pointer to VME master resource.
* @buf: Pointer to buffer where data should be transferred.
* @count: Number of bytes to transfer.
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index cddf60b7309c..3712b1e6dc71 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -315,7 +315,7 @@ static ssize_t resolution_show(struct device *device,
static ssize_t resolution_store(struct device *device,
struct device_attribute *attr, const char *buf, size_t size);
-static ssize_t eeprom_store(struct device *device,
+static ssize_t eeprom_cmd_store(struct device *device,
struct device_attribute *attr, const char *buf, size_t size);
static ssize_t alarms_store(struct device *device,
@@ -350,7 +350,7 @@ static DEVICE_ATTR_RO(w1_seq);
static DEVICE_ATTR_RO(temperature);
static DEVICE_ATTR_RO(ext_power);
static DEVICE_ATTR_RW(resolution);
-static DEVICE_ATTR_WO(eeprom);
+static DEVICE_ATTR_WO(eeprom_cmd);
static DEVICE_ATTR_RW(alarms);
static DEVICE_ATTR_RW(conv_time);
static DEVICE_ATTR_RW(features);
@@ -386,7 +386,7 @@ static struct attribute *w1_therm_attrs[] = {
&dev_attr_temperature.attr,
&dev_attr_ext_power.attr,
&dev_attr_resolution.attr,
- &dev_attr_eeprom.attr,
+ &dev_attr_eeprom_cmd.attr,
&dev_attr_alarms.attr,
&dev_attr_conv_time.attr,
&dev_attr_features.attr,
@@ -397,7 +397,7 @@ static struct attribute *w1_ds18s20_attrs[] = {
&dev_attr_w1_slave.attr,
&dev_attr_temperature.attr,
&dev_attr_ext_power.attr,
- &dev_attr_eeprom.attr,
+ &dev_attr_eeprom_cmd.attr,
&dev_attr_alarms.attr,
&dev_attr_conv_time.attr,
&dev_attr_features.attr,
@@ -410,7 +410,7 @@ static struct attribute *w1_ds28ea00_attrs[] = {
&dev_attr_temperature.attr,
&dev_attr_ext_power.attr,
&dev_attr_resolution.attr,
- &dev_attr_eeprom.attr,
+ &dev_attr_eeprom_cmd.attr,
&dev_attr_alarms.attr,
&dev_attr_conv_time.attr,
&dev_attr_features.attr,
@@ -1740,7 +1740,7 @@ static ssize_t resolution_store(struct device *device,
return size;
}
-static ssize_t eeprom_store(struct device *device,
+static ssize_t eeprom_cmd_store(struct device *device,
struct device_attribute *attr, const char *buf, size_t size)
{
struct w1_slave *sl = dev_to_w1_slave(device);
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index 06409a6c40bc..e162b757b6d5 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -31,6 +31,19 @@ enum nvmem_type {
#define NVMEM_DEVID_AUTO (-2)
/**
+ * struct nvmem_keepout - NVMEM register keepout range.
+ *
+ * @start: The first byte offset to avoid.
+ * @end: One beyond the last byte offset to avoid.
+ * @value: The byte to fill reads with for this region.
+ */
+struct nvmem_keepout {
+ unsigned int start;
+ unsigned int end;
+ unsigned char value;
+};
+
+/**
* struct nvmem_config - NVMEM device configuration
*
* @dev: Parent device.
@@ -39,6 +52,8 @@ enum nvmem_type {
* @owner: Pointer to exporter module. Used for refcounting.
* @cells: Optional array of pre-defined NVMEM cells.
* @ncells: Number of elements in cells.
+ * @keepout: Optional array of keepout ranges (sorted ascending by start).
+ * @nkeepout: Number of elements in the keepout array.
* @type: Type of the nvmem storage
* @read_only: Device is read-only.
* @root_only: Device is accessibly to root only.
@@ -66,6 +81,8 @@ struct nvmem_config {
struct gpio_desc *wp_gpio;
const struct nvmem_cell_info *cells;
int ncells;
+ const struct nvmem_keepout *keepout;
+ unsigned int nkeepout;
enum nvmem_type type;
bool read_only;
bool root_only;
diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h
index 54bf6b118401..47c5962b876b 100644
--- a/include/linux/uio_driver.h
+++ b/include/linux/uio_driver.h
@@ -117,6 +117,14 @@ extern int __must_check
struct uio_info *info);
/* use a define to avoid include chaining to get THIS_MODULE */
+
+/**
+ * uio_register_device - register a new userspace IO device
+ * @parent: parent device
+ * @info: UIO device capabilities
+ *
+ * returns zero on success or a negative error code.
+ */
#define uio_register_device(parent, info) \
__uio_register_device(THIS_MODULE, parent, info)
@@ -129,6 +137,14 @@ extern int __must_check
struct uio_info *info);
/* use a define to avoid include chaining to get THIS_MODULE */
+
+/**
+ * devm_uio_register_device - Resource managed uio_register_device()
+ * @parent: parent device
+ * @info: UIO device capabilities
+ *
+ * returns zero on success or a negative error code.
+ */
#define devm_uio_register_device(parent, info) \
__devm_uio_register_device(THIS_MODULE, parent, info)