Kernel
Threads by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- 38 participants
- 24734 discussions
14 Sep '26
hulk inclusion
category: bugfix
bugzilla: https://atomgit.com/openeuler/kernel/issues/9803
--------------------------------
syzbot reported a UBSAN undefined behavior issue in vif_delete():
UBSAN: Undefined behaviour in net/ipv4/ipmr.c:720:43
signed integer overflow: -2147483648 - 1 cannot be represented
in type 'int'
MC_FORWARDING is a read-only sysctl (0444), but netlink RTM_SETLINK
allows userspace to modify it via inet_validate_link_af() without
permission checks, bypassing the read-only restriction. A corrupted
counter can lead to inconsistent multicast routing state.
Fix by rejecting IPV4_DEVCONF_MC_FORWARDING in inet_validate_link_af()
with -EINVAL.
Fixes: 9f0f7272ac95 ("ipv4: AF_INET link address family")
Signed-off-by: JiangJieHua <jiangjiehua1(a)huawei.com>
---
net/ipv4/devinet.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 9ac7d47d27b81..6822408e8f8d2 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1987,6 +1987,9 @@ static int inet_validate_link_af(const struct net_device *dev,
if (cfgid <= 0 || cfgid > IPV4_DEVCONF_MAX)
return -EINVAL;
+
+ if (cfgid == IPV4_DEVCONF_MC_FORWARDING)
+ return -EINVAL;
}
}
--
2.33.8
2
1
14 Sep '26
hulk inclusion
category: bugfix
bugzilla: https://atomgit.com/openeuler/kernel/issues/9803
--------------------------------
syzbot reported a UBSAN undefined behavior issue in vif_delete():
UBSAN: Undefined behaviour in net/ipv4/ipmr.c:720:43
signed integer overflow: -2147483648 - 1 cannot be represented
in type 'int'
MC_FORWARDING is a read-only sysctl (0444), but netlink RTM_SETLINK
allows userspace to modify it via inet_validate_link_af() without
permission checks, bypassing the read-only restriction. A corrupted
counter can lead to inconsistent multicast routing state.
Fix by rejecting IPV4_DEVCONF_MC_FORWARDING in inet_validate_link_af()
with -EINVAL.
Fixes: 9f0f7272ac95 ("ipv4: AF_INET link address family")
Signed-off-by: JiangJieHua <jiangjiehua1(a)huawei.com>
---
net/ipv4/devinet.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 798497c8b1923..9b42ef2cc4ae2 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -2028,6 +2028,9 @@ static int inet_validate_link_af(const struct net_device *dev,
if (cfgid <= 0 || cfgid > IPV4_DEVCONF_MAX)
return -EINVAL;
+
+ if (cfgid == IPV4_DEVCONF_MC_FORWARDING)
+ return -EINVAL;
}
}
--
2.33.8
2
1
[PATCH OLK-6.6] tracing/probes: Fix use-after-free on field name/type of events with multiple probes
by Tengda Wu 14 Sep '26
by Tengda Wu 14 Sep '26
14 Sep '26
From: Henry Martin <bsdhenrymartin(a)gmail.com>
mainline inclusion
from mainline-v7.3-rc2
commit 86b7a239ec6b14a7544200ede85474c6f5526049
category: bugfix
bugzilla: https://atomgit.com/openeuler/kernel/issues/9956
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
--------------------------------
The fields of a probe-based dynamic event (kprobe, uprobe, eprobe and
fprobe events) are created in traceprobe_define_arg_fields() by handing
the probe_arg name/type strings to trace_define_field(), which only
stores the pointers without copying. Those strings are owned by the
trace_probe and are freed when that probe is removed.
An event can have several probes attached. The field list is defined
only once, by the first probe that registers the event, but it is kept
alive by any surviving sibling probe. Deleting just that first probe by
symbol -
# primary A: fields are defined from A's args
echo 'p:kprobes/ev vfs_read a1=$arg1' > kprobe_events
# append B: shares A's event call
echo 'p:kprobes/ev vfs_write a1=$arg1' >> kprobe_events
# delete only A (matched by symbol), B survives
echo '-:kprobes/ev vfs_read' >> kprobe_events
frees A's args (trace_probe_cleanup() -> traceprobe_free_probe_arg()),
but trace_probe_unlink() keeps the trace_probe_event because the probe
list is not empty. The event call stays registered via B while its
fields now reference freed memory. Any field lookup then reads it, e.g.
echo 'a1 == 1' > events/kprobes/ev/filter
BUG: KASAN: slab-use-after-free in strcmp+0xa7/0xb0
Call Trace:
strcmp
trace_find_event_field
parse_pred
process_preds
create_filter
apply_event_filter
event_filter_write
field->name references parg->name (kstrdup'd, freed with the probe) and,
for array arguments, field->type references parg->fmt (kmalloc'd, freed
with the probe) - the scalar type otherwise points at the static
fmttype rodata, which is safe.
Have traceprobe_define_arg_fields() duplicate the name and type strings
and anchor the copies on the trace_probe_event, which embeds the event
call and outlives every individual probe; trace_probe_event_free()
releases them.
The reproducer above triggers reliably; the field lookup and the delete
both run under event_mutex, so this is a dangling reference after
removal rather than a race.
The issue was found by the autokbug dynamic kernel fuzzer at Tencent
Yunding Lab.
Link: https://lore.kernel.org/all/20260826030009.1855331-1-bsdhenrymartin@gmail.c…
Fixes: ca89bc071d5e4 ("tracing/kprobe: Add multi-probe per event support")
Signed-off-by: Henry Martin <bsdhenrymartin(a)gmail.com>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat(a)kernel.org>
Signed-off-by: Tengda Wu <wutengda2(a)huawei.com>
---
kernel/trace/trace_probe.c | 48 +++++++++++++++++++++++++++++++++++++-
kernel/trace/trace_probe.h | 2 ++
2 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index 066e154b91ee..1c05937d2ee0 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -1782,19 +1782,60 @@ int traceprobe_set_print_fmt(struct trace_probe *tp, enum probe_print_type ptype
int traceprobe_define_arg_fields(struct trace_event_call *event_call,
size_t offset, struct trace_probe *tp)
{
+ struct trace_probe_event *tpe = trace_probe_event_from_call(event_call);
int ret, i;
+ /*
+ * A field created by trace_define_field() only stores the name and
+ * type pointers, it does not copy the strings. Here they point into
+ * the probe_arg of @tp, which is freed when @tp is removed. For an
+ * event with multiple probes attached, the field list is defined
+ * once by the first probe but kept alive by the surviving siblings,
+ * so removing that first probe would leave the fields referencing
+ * freed memory. Duplicate the strings and anchor the copies on the
+ * trace_probe_event, which lives as long as the field list itself.
+ *
+ * event_define_fields() ignores the return value of this hook, so
+ * if a previous attempt failed before creating any field, it may
+ * call here again. Release duplicates left behind by such an
+ * attempt before starting over.
+ */
+ for (i = 0; i < tpe->nr_field_strings; i++)
+ kfree(tpe->field_strings[i]);
+ kfree(tpe->field_strings);
+ tpe->field_strings = NULL;
+ tpe->nr_field_strings = 0;
+
+ if (tp->nr_args) {
+ tpe->field_strings = kcalloc(tp->nr_args * 2, sizeof(char *),
+ GFP_KERNEL);
+ if (!tpe->field_strings)
+ return -ENOMEM;
+ }
+
/* Set argument names as fields */
for (i = 0; i < tp->nr_args; i++) {
struct probe_arg *parg = &tp->args[i];
const char *fmt = parg->type->fmttype;
int size = parg->type->size;
+ char *name, *type;
if (parg->fmt)
fmt = parg->fmt;
if (parg->count)
size *= parg->count;
- ret = trace_define_field(event_call, fmt, parg->name,
+
+ name = kstrdup(parg->name, GFP_KERNEL);
+ type = kstrdup(fmt, GFP_KERNEL);
+ if (!name || !type) {
+ kfree(name);
+ kfree(type);
+ return -ENOMEM;
+ }
+ tpe->field_strings[tpe->nr_field_strings++] = name;
+ tpe->field_strings[tpe->nr_field_strings++] = type;
+
+ ret = trace_define_field(event_call, type, name,
offset + parg->offset, size,
parg->type->is_signed,
FILTER_OTHER);
@@ -1806,6 +1847,11 @@ int traceprobe_define_arg_fields(struct trace_event_call *event_call,
static void trace_probe_event_free(struct trace_probe_event *tpe)
{
+ int i;
+
+ for (i = 0; i < tpe->nr_field_strings; i++)
+ kfree(tpe->field_strings[i]);
+ kfree(tpe->field_strings);
kfree(tpe->class.system);
kfree(tpe->call.name);
kfree(tpe->call.print_fmt);
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h
index e8efa55b3a18..47982338bd42 100644
--- a/kernel/trace/trace_probe.h
+++ b/kernel/trace/trace_probe.h
@@ -246,6 +246,8 @@ struct trace_probe_event {
struct trace_event_call call;
struct list_head files;
struct list_head probes;
+ char **field_strings;
+ int nr_field_strings;
struct trace_uprobe_filter filter[];
};
--
2.34.1
2
1
14 Sep '26
From: Hui Su <sh_def(a)163.com>
mainline inclusion
from mainline-v7.3-rc1
commit 649bc7df3e5d7be6f7996a95084037dbf3cad1e5
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18775
CVE: CVE-2026-89749
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
--------------------------------
event_test_stuff() calls kthread_run() and unconditionally passes the
returned task_struct pointer to kthread_stop(). kthread_run() returns an
error pointer such as ERR_PTR(-ENOMEM) when kthread creation fails, for
example under memory pressure during the boot-time event self-test.
kthread_stop() then dereferences the invalid pointer, crashing the kernel.
Check the result of kthread_run() before passing it to kthread_stop(). Use
WARN_ON() so that a failure to create the self-test thread does not go
unnoticed, matching the ring-buffer self-test fix in commit
91542863abad ("ring-buffer: Fix crash passing ERR_PTR to kthread_stop()").
Cc: stable(a)vger.kernel.org
Fixes: e6187007d6c3 ("tracing/events: add startup tests for events")
Link: https://patch.msgid.link/20260817120642.668375-3-sh_def@163.com
Signed-off-by: Hui Su <sh_def(a)163.com>
Signed-off-by: Steven Rostedt <rostedt(a)goodmis.org>
Signed-off-by: Tengda Wu <wutengda2(a)huawei.com>
---
kernel/trace/trace_events.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 7326cfafcc23..48a29993b95d 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -4291,6 +4291,8 @@ static __init void event_test_stuff(void)
struct task_struct *test_thread;
test_thread = kthread_run(event_test_thread, NULL, "test-events");
+ if (WARN_ON(IS_ERR(test_thread)))
+ return;
msleep(1);
kthread_stop(test_thread);
}
--
2.34.1
2
1
14 Sep '26
From: Hui Su <sh_def(a)163.com>
mainline inclusion
from mainline-v7.3-rc1
commit a7318172aa332a161fb9618286e64454c827f8fd
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18798
CVE: CVE-2026-89746
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
--------------------------------
When two hist triggers on different events are registered with the same
name=, the second one reuses the first as named_data. Both are added to
tr->hist_vars by save_hist_vars() during event_hist_trigger_parse(),
because save_hist_vars() is called before event_trigger_register() while
the named reuse is only detected later, in hist_register_trigger().
In the named-data branch hist_register_trigger() then frees the second
histogram's hist_data via destroy_hist_data(), but never removes its
tr->hist_vars list entry, leaving a dangling pointer and leaking the
trace_array reference it holds.
A later hist trigger that references a variable makes find_var_file()
walk tr->hist_vars and dereference the freed hist_data. The bug is
reproducible from userspace by writing three hist triggers to tracefs:
cd /sys/kernel/tracing
echo 'hist:keys=common_pid:x=common_pid:name=mh' > events/sched/sched_switch/trigger
echo 'hist:keys=common_pid:x=common_pid:name=mh' > events/sched/sched_process_fork/trigger
echo 'hist:keys=common_pid:vals=$x' > events/sched/sched_process_exit/trigger
The third write panics the kernel:
BUG: KASAN: slab-use-after-free in find_var_file.part.0+0x272/0x290
Read of size 8 at addr ffff888001f8a0e0 by task sh/1
CPU: 1 UID: 0 PID: 1 Comm: sh Tainted: G D N
Call Trace:
find_var_file.part.0
find_event_var
parse_atom
parse_expr
__create_val_field
event_hist_trigger_parse
trigger_process_regex
event_trigger_write
vfs_write
ksys_write
do_syscall_64
entry_SYSCALL_64_after_hwframe
Allocated by task 1:
event_hist_trigger_parse
Freed by task 1:
hist_register_trigger+0x618/0xa30
event_hist_trigger_parse
The buggy address belongs to freed 2048-byte region
Oops: general protection fault ... RIP: find_var_file.part.0
Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
Fix by removing the hist_data from tr->hist_vars and releasing the
trace_array reference in the named-data branch of hist_register_trigger()
before freeing the hist_data.
Cc: stable(a)vger.kernel.org
Fixes: 6f86bdeab633 ("tracing: Fix bad hist from corrupting named_triggers list")
Link: https://patch.msgid.link/20260816100427.33642-3-sh_def@163.com
Signed-off-by: Hui Su <sh_def(a)163.com>
Signed-off-by: Steven Rostedt <rostedt(a)goodmis.org>
Signed-off-by: Tengda Wu <wutengda2(a)huawei.com>
---
kernel/trace/trace_events_hist.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index a5fe1776d2a9..40e81642c75d 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -6421,8 +6421,10 @@ static int hist_register_trigger(char *glob,
tracing_set_filter_buffering(file->tr, true);
}
- if (named_data)
+ if (named_data) {
+ remove_hist_vars(hist_data);
destroy_hist_data(hist_data);
+ }
out:
return ret;
}
--
2.34.1
2
1
14 Sep '26
From: Deepanshu Kartikey <kartikey406(a)gmail.com>
mainline inclusion
from mainline-v7.3-rc1
commit 1704aaaf5d22bc765c168402350d191e24e245bc
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18805
CVE: CVE-2026-89618
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
--------------------------------
eventfs_create_dir() allocates the eventfs_inode and initializes it with
init_ei(). But this does not initialize the eventfs_inode list_heads. If
the eventfs_create_dir() fails due to memory pressure, it will call
free_ei() before it initialized the lists, and that checks to make sure
the eventfs_inode has no children. But because the list wasn't
initialized, it will give a false warning.
Fix it by moving the list initialization into init_ei().
Cc: stable(a)vger.kernel.org
Fixes: 5790b1fb3d67 ("eventfs: Remove eventfs_file and just use eventfs_inode")
Reported-by: syzbot+3ef80b4ed02226d04a06(a)syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=3ef80b4ed02226d04a06
Link: https://patch.msgid.link/20260824144653.54044-1-kartikey406@gmail.com
Signed-off-by: Deepanshu Kartikey <kartikey406(a)gmail.com>
[ Rewrote change log ]
Signed-off-by: Steven Rostedt <rostedt(a)goodmis.org>
Conflicts:
fs/tracefs/event_inode.c
[Context conflict]
Signed-off-by: Tengda Wu <wutengda2(a)huawei.com>
---
fs/tracefs/event_inode.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c
index 0a004263a769..8efb9c467b7d 100644
--- a/fs/tracefs/event_inode.c
+++ b/fs/tracefs/event_inode.c
@@ -521,6 +521,8 @@ static inline struct eventfs_inode *init_ei(struct eventfs_inode *ei, const char
if (!ei->name)
return NULL;
kref_init(&ei->kref);
+ INIT_LIST_HEAD(&ei->children);
+ INIT_LIST_HEAD(&ei->list);
return ei;
}
@@ -823,8 +825,6 @@ struct eventfs_inode *eventfs_create_dir(const char *name, struct eventfs_inode
ei->entries = entries;
ei->nr_entries = size;
ei->data = data;
- INIT_LIST_HEAD(&ei->children);
- INIT_LIST_HEAD(&ei->list);
mutex_lock(&eventfs_mutex);
if (!parent->is_freed)
@@ -900,9 +900,6 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
*/
ei->attr.mode |= EVENTFS_SAVE_UID | EVENTFS_SAVE_GID;
- INIT_LIST_HEAD(&ei->children);
- INIT_LIST_HEAD(&ei->list);
-
ti = get_tracefs(inode);
ti->flags |= TRACEFS_EVENT_INODE;
ti->private = ei;
--
2.34.1
2
1
From: Jiayuan Chen <jiayuan.chen(a)linux.dev>
mainline inclusion
from mainline-v7.3-rc2
commit 0895a0c0734703be5532f3883c42db95615fd98b
category: bugfix
bugzilla: https://atomgit.com/openeuler/kernel/issues/9949
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
--------------------------------
map_check_btf() allows a key-less BTF (btf_key_type_id == 0) only for
maps that have a ->map_check_btf callback, and leaves the actual
decision to that callback. Hash maps used to have no ->map_check_btf,
so a key-less BTF was rejected outright.
That changed when htab and rhtab gained a ->map_check_btf to register a
dtor - htab in commit 1df97a7453ee ("bpf: Register dtor for freeing
special fields") and rhtab in commit 6905f8601298 ("bpf: Allow special
fields in resizable hashtab"). Neither looks at the key, so a key-less
hash map now passes map_check_btf() and gets created. Reading it back
through bpffs feeds the key type_id 0 into btf_type_seq_show();
btf_type_by_id() returns the void type, kind_ops[BTF_KIND_UNKN] is NULL,
and btf_type_show() dereferences it:
RIP: 0010:btf_type_show+0x223/0x2e0 kernel/bpf/btf.c:8232
RSP: 0018:ffffc9000399f868 EFLAGS: 00010206
RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000000000
RDX: 0000000000000005 RSI: 0000000000000000 RDI: 0000000000000028
RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000
R10: ffffc9000399f970 R11: 0000000000000001 R12: ffffffff9b96b140
R13: ffffc9000399f8e0 R14: ffff88803d393c00 R15: 0000000000000003
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000200000000000 CR3: 000000003d213000 CR4: 0000000000352ef0
DR0: 0000000039ae8f55 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Call Trace:
<TASK>
btf_type_seq_show_flags+0xca/0x120 kernel/bpf/btf.c:8250
htab_map_seq_show_elem+0x12e/0x350 kernel/bpf/hashtab.c:1669
map_seq_show+0x13d/0x1e0 kernel/bpf/inode.c:293
traverse.part.0.constprop.0+0x107/0x650 fs/seq_file.c:112
traverse fs/seq_file.c:99 [inline]
seq_read_iter+0x93f/0x1270 fs/seq_file.c:196
seq_read+0x344/0x4d0 fs/seq_file.c:163
vfs_read+0x1e4/0xb40 fs/read_write.c:572
ksys_pread64 fs/read_write.c:764 [inline]
__do_sys_pread64 fs/read_write.c:772 [inline]
__se_sys_pread64 fs/read_write.c:769 [inline]
__x64_sys_pread64+0x1eb/0x250 fs/read_write.c:769
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Reject a key-less BTF in htab_map_check_btf() and rhtab_map_check_btf(),
restoring the previous behavior.
Fixes: 1df97a7453ee ("bpf: Register dtor for freeing special fields")
Fixes: 6905f8601298 ("bpf: Allow special fields in resizable hashtab")
Reported-by: syzbot+37b56485bbbf90ad8489(a)syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/6a8f4e88.27659fcc.2ceef7.0008.GAE@google.com/T/
Signed-off-by: Jiayuan Chen <jiayuan.chen(a)linux.dev>
Acked-by: Ihor Solodrai <ihor.solodrai(a)linux.dev>
Link: https://lore.kernel.org/r/20260901104924.346187-2-jiayuan.chen@linux.dev
Signed-off-by: Alexei Starovoitov <ast(a)kernel.org>
Conflicts:
kernel/bpf/hashtab.c
[not merged commit 6905f8601298]
Signed-off-by: Pu Lehui <pulehui(a)huawei.com>
---
kernel/bpf/hashtab.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index 9221625c256a..8aafe8db5883 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -486,6 +486,9 @@ static int htab_map_check_btf(const struct bpf_map *map, const struct btf *btf,
{
struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
+ if (btf_type_is_void(key_type))
+ return -EINVAL;
+
if (htab_is_prealloc(htab))
return 0;
/*
--
2.34.1
2
1
[PATCH openEuler-1.0-LTS] [Backport] serial: amba-pl011: synchronize DMA teardown
by Cai Xinchen 14 Sep '26
by Cai Xinchen 14 Sep '26
14 Sep '26
From: Fan Wu <fanwu01(a)zju.edu.cn>
stable inclusion
from stable-v5.10.267
commit a38fae9d212e2d3ed5e9ec0ef773f8c0a27fb76e
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18582
CVE: CVE-2026-80737
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
------------------------------
[ Upstream commit 440915499231e9db1c361aa45bb702e8fd3b4a32 ]
dmaengine_terminate_all() does not wait for a running callback, so the TX
callback can still touch the TX buffer after it is freed. The RX poll
timer reads the RX buffers without the port lock.
Switch to dmaengine_terminate_sync() and delete the RX timer before
freeing the buffers.
Fixes: ead76f329f77 ("ARM: 6763/1: pl011: add optional RX DMA to PL011 v2")
Cc: stable <stable(a)kernel.org>
Assisted-by: Codex:gpt-5.6
Signed-off-by: Fan Wu <fanwu01(a)zju.edu.cn>
Link: https://patch.msgid.link/20260731085915.326775-4-fanwu01@zju.edu.cn
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
[ changed upstream's `timer_delete_sync()` deletion to match this tree's `del_timer_sync()` spelling at the old call site ]
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Conflicts:
drivers/tty/serial/amba-pl011.c
[The commit 9b13df3fb64ee95e2397585404e442afee2c7d4f ("timers: Rename
del_timer_sync() to timer_delete_sync()") is not merged. Use
del_timer_sync in this patch.]
Signed-off-by: Cai Xinchen <caixinchen1(a)huawei.com>
---
drivers/tty/serial/amba-pl011.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index c987db50757c..d229f36b929d 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1206,7 +1206,7 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
if (uap->using_tx_dma) {
/* In theory, this should already be done by pl011_dma_flush_buffer */
- dmaengine_terminate_all(uap->dmatx.chan);
+ dmaengine_terminate_sync(uap->dmatx.chan);
if (uap->dmatx.queued) {
dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1,
DMA_TO_DEVICE);
@@ -1218,12 +1218,12 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
}
if (uap->using_rx_dma) {
- dmaengine_terminate_all(uap->dmarx.chan);
+ if (uap->dmarx.poll_rate)
+ del_timer_sync(&uap->dmarx.timer);
+ dmaengine_terminate_sync(uap->dmarx.chan);
/* Clean up the RX DMA */
pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_a, DMA_FROM_DEVICE);
pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_b, DMA_FROM_DEVICE);
- if (uap->dmarx.poll_rate)
- del_timer_sync(&uap->dmarx.timer);
uap->using_rx_dma = false;
}
}
--
2.34.1
2
1
Background
==========
On x86, the resctrl allows creating up to num_rmids monitoring groups
under parent control group. However, ARM64 MPAM is currently limited by
the PMG (Performance Monitoring Group) count, which is typically much
smaller than the theoretical RMID limit. This creates a significant
scalability gap: users expecting fine-grained per-process or per-thread
monitoring quickly exhaust the PMG space, even when plenty of reqPARTIDs
remain available.
The Narrow-PARTID feature, defined in the ARM MPAM architecture,
addresses this by associating reqPARTIDs with intPARTIDs through a
programmable many-to-one mapping. This allows the kernel to present more
logical monitoring contexts.
Design Overview
===============
The implementation extends the RMID encoding to carry reqPARTID
information:
RMID = reqPARTID * NUM_PMG + PMG
In this patchset, a monitoring group is uniquely identified by the
combination of reqPARTID and PMG. The closid is represented by intPARTID,
which is exactly the original PARTID.
For systems with homogeneous MSCs (all supporting Narrow-PARTID), the
driver exposes the full reqPARTID range directly. For heterogeneous
systems where some MSCs lack Narrow-PARTID support, the driver utilizes
PARTIDs beyond the intPARTID range as reqPARTIDs to expand monitoring
capacity. The sole exception is when MBA MSCs lack Narrow-PARTID support,
their percentage-based control mechanism prevents the use of PARTIDs as
reqPARTIDs.
Capacity Improvements
=====================
--------------------------------------------------------------------------
The maximum | Sub-monitoring groups | System-wide
number of | under a control group | monitoring groups
--------------------------------------------------------------------------
Without | |
reqPARTID | PMG | intPARTID * PMG
--------------------------------------------------------------------------
reqPARTID | |
static allocation | (reqPARTID // intPARTID) * PMG | reqPARTID * PMG
--------------------------------------------------------------------------
reqPARTID | |
dynamic allocation | (reqPARTID − intPARTID + 1) * PMG | reqPARTID * PMG
--------------------------------------------------------------------------
Under MPAM, the number of reqPARTID is always greater than or equal to
intPARTID.
Dave Martin (1):
arm_mpam: Set INTERNAL as needed when setting MSC controls
James Morse (1):
debugfs: Add helpers for creating cpumask entries in debugfs
Zeng Heng (30):
arm_mpam: Add intPARTID and reqPARTID support for narrow PARTID
feature
arm_mpam: Refactor rmid to reqPARTID/PMG mapping
arm_mpam: Propagate control group config to sub-monitoring groups
fs/resctrl: Add rmid_entry state helpers
arm_mpam: Implement dynamic reqPARTID allocation for monitoring groups
fs/resctrl: Wire up rmid expansion and reclaim functions
arm64/mpam: Add mpam_sync_config() for dynamic rmid expansion
fs/resctrl: Prevent rmid parsing errors by flushing limbo on umount
arm_mpam: Disable reqPARTID expansion when Narrow-PARTID is
unavailable
arm_mpam: Add MBWU counter scaling support
fs/resctrl: Fix incorrect closid propagation during monitor group
reparenting
arm64/mpam: Fix wd boundary check and GENMASK range in percent-mbw
conversion
arm64/mpam: Add HISI_HIP13 support
fs/resctrl: Introduce per-resource MBM enable check
fs/resctrl: Add arch-specific MBM overflow setup helpers
arm64/mpam: Add selective L2 MBM overflow checking
arm64/mpam: Add MBM overflow handling for HIP13
arm64/mpam: Allow zero-bit CPBM for L2 cache
arm64/mpam: Adapt SMMU IOMMU interface for Narrow PARTID support
arm64/mpam: Add MBOPT (Memory Bandwidth Optimal) feature
resctrl: Remove unused mbm_core field from rdt_domain
fs/resctrl: Introduce resctrl_arch_mbm_update() for arch-specific MBM
event handling
arm64/mpam: Add MBM_TOTAL_EVENT configurability check
arm64/mpam: Add debugfs entries to show the MSC/RIS the driver
discovered
iommu/arm-smmu-v3: Add debug logging for MPAM STE configuration
Revert "fs/resctrl: Re-allocate rmid for the monitor when migrating
across control groups"
fs/resctrl: Fix iommu_group and kobject reference leaks
arm_mpam: Fix NULL pointer dereference after freeing comp->cfg
arm_mpam: Wait for SRCU grace period before destroying RIS
arm_mpam: Fix percpu memory leak in __setup_ppi() error path
arch/arm64/include/asm/mpam.h | 17 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 3 +
drivers/platform/mpam/mpam_devices.c | 271 ++++++++-
drivers/platform/mpam/mpam_internal.h | 21 +-
drivers/platform/mpam/mpam_resctrl.c | 617 ++++++++++++++++----
fs/debugfs/file.c | 64 ++
fs/resctrl/internal.h | 1 -
fs/resctrl/monitor.c | 123 ++--
fs/resctrl/rdtgroup.c | 132 +++--
include/linux/arm_mpam.h | 20 +-
include/linux/debugfs.h | 6 +
include/linux/resctrl.h | 35 +-
include/linux/resctrl_types.h | 2 +
13 files changed, 1031 insertions(+), 281 deletions(-)
--
2.43.0
2
33
LeapIO inclusion
category: feature
bugzilla: https://atomgit.com/openeuler/kernel/issues/9946
------------------------------------------
leapraid driver changes from v2.00.01.02 to v2.00.01.10.
This update includes:
- AI-assisted code inspection rollout and follow-up bug fixes
- Clang, Sparse, and Smatch issue cleanup
- recovery-wait and nested hard-reset stabilization
- SCSI EH, task-management, and AER recovery fixes
- timeout, IOC-fault, and I/O diagnostic improvements
- MSI-X/IRQ affinity and sparse-CPU mapping fixes
- SAS topology, event bitmap, and VPHY handling fixes
- async-event and SMP payload validation hardening
- ioctl and passthrough bounds-checking cleanup
- adapter-removal and firmware-event race fixes
- firmware-log mmap lifetime and reference-count fixes
- active-command teardown and IRQ synchronization
- probe rollback and host-memory cleanup hardening
- config-page stack usage reduction
- SMART polling and NCQ sysfs alignment
- drive matching and adapter metadata cleanup
Signed-off-by: haodongdong <doubled(a)leap-io.com>
---
drivers/scsi/leapraid/leapraid.h | 37 +-
drivers/scsi/leapraid/leapraid_app.c | 169 ++-
drivers/scsi/leapraid/leapraid_func.c | 1126 +++++++-------------
drivers/scsi/leapraid/leapraid_func.h | 130 +--
drivers/scsi/leapraid/leapraid_os.c | 276 ++---
drivers/scsi/leapraid/leapraid_transport.c | 40 +-
6 files changed, 693 insertions(+), 1085 deletions(-)
diff --git a/drivers/scsi/leapraid/leapraid.h b/drivers/scsi/leapraid/leapraid.h
index 2a99417143ad..c2d28359be5b 100644
--- a/drivers/scsi/leapraid/leapraid.h
+++ b/drivers/scsi/leapraid/leapraid.h
@@ -27,8 +27,6 @@
/* Maximum number of retries waiting for doorbell to become operational. */
#define LEAPRAID_DB_WAIT_OP_SHORT 10
#define LEAPRAID_DB_WAIT_OP_LONG 200
-/* Sleep interval (in seconds) between doorbell polls. */
-#define LEAPRAID_DB_POLL_INTERVAL_S 1
/* Maximum number of retries waiting for host to end recovery. */
#define LEAPRAID_WAIT_SHOST_RECOVERY 400
@@ -43,7 +41,6 @@
/* The number of debug register. */
#define LEAPRAID_DEBUGLOG_SZ_MAX 16
-#define LEAPRAID_DEBUGLOG_DWORDS_PER_LINE 4
/* Reply post host register definitions. */
#define REP_POST_HOST_IDX_REG_CNT 16
@@ -180,8 +177,6 @@
#define LEAPRAID_CFG_PAGE_NUM_DEV0 0x0
/* SAS device page 0 flags. */
-#define LEAPRAID_SAS_DEV_P0_FLG_FP_CAP 0x2000
-#define LEAPRAID_SAS_DEV_P0_FLG_SATA_SMART 0x0040
#define LEAPRAID_SAS_DEV_P0_FLG_ENC_LEVEL_VALID 0x0002
#define LEAPRAID_SAS_DEV_P0_FLG_DEV_PRESENT 0x0001
#define LEAPRAID_SAS_DEV_P0_CON_NAME_LEN 4
@@ -207,15 +202,9 @@
/* Physical disk page number. */
#define LEAPRAID_CFG_PAGE_NUM_PD0 0x0
-/* Adapter page number. */
-#define LEAPRAID_CFG_PAGE_NUM_ADAPTER1 0x1
-
#define LEAPRAID_CFG_UNIT_SIZE 4
/* Raid volume type and state. */
-#define LEAPRAID_VOL_STATE_MISSING 0x00
-#define LEAPRAID_VOL_STATE_FAILED 0x01
-#define LEAPRAID_VOL_STATE_INITIALIZING 0x02
#define LEAPRAID_VOL_STATE_ONLINE 0x03
#define LEAPRAID_VOL_STATE_DEGRADED 0x04
#define LEAPRAID_VOL_STATE_OPTIMAL 0x05
@@ -231,10 +220,6 @@
#define LEAPRAID_RAIDCFG_P0_EFLG_HOT_SPARE_ELEMENT 0x0002
#define LEAPRAID_RAIDCFG_P0_EFLG_OCE_ELEMENT 0x0003
-/* Raid action. */
-#define LEAPRAID_RAID_ACT_SYSTEM_SHUTDOWN_INITIATED 0x20
-#define LEAPRAID_RAID_ACT_PHYSDISK_HIDDEN 0x24
-
/* SAS negotiated link rates. */
#define LEAPRAID_SAS_NEG_LINK_RATE_MASK_PHYSICAL 0x0F
#define LEAPRAID_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE 0x00
@@ -290,8 +275,6 @@
#define LEAPRAID_TM_MSGFLAGS_LINK_RESET 0x00
#define LEAPRAID_TM_RSP_INVALID_FRAME 0x02
-#define LEAPRAID_TM_RSP_TM_SUCCEEDED 0x08
-#define LEAPRAID_TM_RSP_IO_QUEUED_ON_ADAPTER 0x80
/* SCSI enclosure processor request defines. */
#define LEAPRAID_SEP_REQ_ACT_WRITE_STATUS 0x00
@@ -301,8 +284,6 @@
/* The capabilities of the adapter. */
#define LEAPRAID_ADAPTER_FEATURES_CAP_ATOMIC_REQ 0x00080000
-#define LEAPRAID_ADAPTER_FEATURES_CAP_RDPQ_ARRAY_CAPABLE 0x00040000
-#define LEAPRAID_ADAPTER_FEATURES_CAP_EVENT_REPLAY 0x00002000
#define LEAPRAID_ADAPTER_FEATURES_CAP_INTEGRATED_RAID 0x00001000
/* Event code definitions for the firmware. */
@@ -338,10 +319,6 @@
#define LEAPRAID_EVT_SAS_TOPO_RC_TARG_ADDED 0x01
#define LEAPRAID_EVT_SAS_TOPO_RC_TARG_NOT_RESPONDING 0x02
-/* SAS discovery event defines. */
-#define LEAPRAID_EVT_SAS_DISC_RC_STARTED 0x01
-#define LEAPRAID_EVT_SAS_DISC_RC_COMPLETED 0x02
-
/* Enclosure device status change event. */
#define LEAPRAID_EVT_SAS_ENCL_RC_ADDED 0x01
#define LEAPRAID_EVT_SAS_ENCL_RC_NOT_RESPONDING 0x02
@@ -543,7 +520,7 @@ struct leapraid_sge_simple_union {
union {
__le32 addr32;
__le64 addr64;
- } u;
+ } __packed __aligned(4) u;
} __packed __aligned(4);
/**
@@ -562,7 +539,7 @@ struct leapraid_sge_chain_union {
union {
__le32 addr32;
__le64 addr64;
- } u;
+ } __packed __aligned(4) u;
} __packed __aligned(4);
/**
@@ -1672,7 +1649,7 @@ struct leapraid_adapter_features_req {
* @r9: Reserved.
*/
struct leapraid_adapter_features_rep {
- u16 msg_ver;
+ __le16 msg_ver;
u8 msg_len;
u8 func;
u16 header_ver;
@@ -1686,7 +1663,7 @@ struct leapraid_adapter_features_rep {
u8 r4;
u8 max_msix_vectors;
__le16 req_slot;
- u8 r5[2];
+ __le16 product_id;
__le32 adapter_caps;
__le32 fw_version;
__le16 sas_wide_max_qdepth;
@@ -1871,7 +1848,7 @@ struct leapraid_evt_sas_topo_phy_entry {
* @exp_dev_hdl: Expander device handle.
* @num_phys: Number of PHYs in this entry.
* @r1: Reserved.
- * @entry_num: Entry index.
+ * @entry_num: Number of PHY elements.
* @start_phy_num: Start PHY number.
* @exp_status: Expander status.
* @physical_port: Physical port number.
@@ -1909,7 +1886,7 @@ struct leapraid_evt_data_sas_enc_dev_status_change {
__le16 num_slots;
__le16 start_slot;
__le32 phy_bits;
-};
+} __packed __aligned(4);
/**
* struct leapraid_io_unit_ctrl_req - I/O unit control request
@@ -1933,7 +1910,7 @@ struct leapraid_io_unit_ctrl_req {
u8 r1;
u8 chain_offset;
u8 func;
- u16 dev_hdl;
+ __le16 dev_hdl;
u8 adapter_para;
u8 msg_flag;
u8 r2[6];
diff --git a/drivers/scsi/leapraid/leapraid_app.c b/drivers/scsi/leapraid/leapraid_app.c
index 25ec57c2ce4b..c4d4aace8112 100644
--- a/drivers/scsi/leapraid/leapraid_app.c
+++ b/drivers/scsi/leapraid/leapraid_app.c
@@ -134,13 +134,59 @@ struct leapraid_ioctl_command {
u8 mf[];
};
-static struct leapraid_adapter *leapraid_ctl_lookup_adapter(int adapter_id)
+static int leapraid_ctl_validate_sge_offset(struct leapraid_adapter *adapter,
+ const struct leapraid_req *req,
+ u32 offset_bytes,
+ size_t h2c_size,
+ size_t c2h_size)
+{
+ size_t sge_bytes;
+
+ switch (req->func) {
+ case LEAPRAID_FUNC_SCSIIO:
+ case LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH:
+ case LEAPRAID_FUNC_SMP_PASSTHROUGH:
+ case LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH:
+ case LEAPRAID_FUNC_FW_DOWNLOAD:
+ case LEAPRAID_FUNC_FW_UPLOAD:
+ sge_bytes = LEAPRAID_IEEE_SGE64_ENTRY_SIZE;
+ break;
+ default:
+ sge_bytes = adapter->adapter_attr.use_32_dma_mask ?
+ sizeof(struct leapraid_sge_simple32) :
+ sizeof(struct leapraid_sge_simple64);
+ break;
+ }
+
+ if (h2c_size && c2h_size)
+ sge_bytes *= 2;
+
+ if (offset_bytes > LEAPRAID_REQUEST_SIZE - sge_bytes) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Invalid offset_bytes=%u for func=0x%x\n",
+ __func__, offset_bytes, req->func);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct leapraid_adapter *leapraid_ctl_lookup_adapter(int adapter_id,
+ bool track_mmap)
{
struct leapraid_adapter *adapter;
+ struct Scsi_Host *shost;
spin_lock(&leapraid_adapter_lock);
list_for_each_entry(adapter, &leapraid_adapter_list, list) {
if (adapter->adapter_attr.id == adapter_id) {
+ if (READ_ONCE(adapter->access_ctrl.host_removing))
+ break;
+ shost = adapter->shost;
+ if (!shost || !scsi_host_get(shost))
+ break;
+ if (track_mmap)
+ atomic_inc(&adapter->fw_log_desc.mmap_refcnt);
spin_unlock(&leapraid_adapter_lock);
return adapter;
}
@@ -150,6 +196,12 @@ static struct leapraid_adapter *leapraid_ctl_lookup_adapter(int adapter_id)
return NULL;
}
+static void leapraid_ctl_put_adapter(struct leapraid_adapter *adapter)
+{
+ if (adapter && adapter->shost)
+ scsi_host_put(adapter->shost);
+}
+
static void leapraid_ctl_scsiio_cmd(struct leapraid_adapter *adapter,
void *ctl_sp_mpi_req,
u16 taskid,
@@ -245,6 +297,7 @@ static int leapraid_ctl_do_command(struct leapraid_adapter *adapter,
unsigned long timeout;
u16 dev_hdl = LEAPRAID_INVALID_DEV_HANDLE;
bool issue_reset = false;
+ u32 data_sge_offset_bytes;
u32 sz;
int rc;
@@ -257,9 +310,17 @@ static int leapraid_ctl_do_command(struct leapraid_adapter *adapter,
if (!leap_mpi_req)
return -ENOMEM;
- if (karg->data_sge_offset > (UINT_MAX / LEAPRAID_SGE_OFFSET_SIZE) ||
- karg->data_sge_offset * LEAPRAID_SGE_OFFSET_SIZE >
- LEAPRAID_REQUEST_SIZE) {
+ if (karg->data_sge_offset > (UINT_MAX / LEAPRAID_SGE_OFFSET_SIZE)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Invalid data_sge_offset=%u\n",
+ __func__, karg->data_sge_offset);
+ rc = -EINVAL;
+ goto out_cleanup;
+ }
+
+ data_sge_offset_bytes = karg->data_sge_offset *
+ LEAPRAID_SGE_OFFSET_SIZE;
+ if (data_sge_offset_bytes > LEAPRAID_REQUEST_SIZE) {
dev_err(&adapter->pdev->dev,
"%s: Invalid data_sge_offset=%u\n",
__func__, karg->data_sge_offset);
@@ -267,8 +328,7 @@ static int leapraid_ctl_do_command(struct leapraid_adapter *adapter,
goto out_cleanup;
}
- if (copy_from_user(leap_mpi_req, mf,
- karg->data_sge_offset * LEAPRAID_SGE_OFFSET_SIZE)) {
+ if (copy_from_user(leap_mpi_req, mf, data_sge_offset_bytes)) {
dev_err(&adapter->pdev->dev,
"%s: Failed to copy request message from user\n",
__func__);
@@ -276,16 +336,21 @@ static int leapraid_ctl_do_command(struct leapraid_adapter *adapter,
goto out_cleanup;
}
+ h2c_size = karg->h2c_size;
+ c2h_size = karg->c2h_size;
+ rc = leapraid_ctl_validate_sge_offset(adapter, leap_mpi_req,
+ data_sge_offset_bytes,
+ h2c_size, c2h_size);
+ if (rc)
+ goto out_cleanup;
+
taskid = adapter->driver_cmds.ctl_cmd.taskid;
adapter->driver_cmds.ctl_cmd.status = LEAPRAID_CMD_PENDING;
- memset(&adapter->driver_cmds.ctl_cmd.reply, 0,
- LEAPRAID_REPLY_SIZE);
+ memset(&adapter->driver_cmds.ctl_cmd.reply, 0, LEAPRAID_REPLY_SIZE);
ctl_sp_mpi_req = leapraid_get_task_desc(adapter, taskid);
memset(ctl_sp_mpi_req, 0, LEAPRAID_REQUEST_SIZE);
- memcpy(ctl_sp_mpi_req,
- leap_mpi_req,
- karg->data_sge_offset * LEAPRAID_SGE_OFFSET_SIZE);
+ memcpy(ctl_sp_mpi_req, leap_mpi_req, data_sge_offset_bytes);
if (ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSIIO ||
ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH ||
@@ -305,8 +370,6 @@ static int leapraid_ctl_do_command(struct leapraid_adapter *adapter,
goto out_cleanup;
}
- h2c_size = karg->h2c_size;
- c2h_size = karg->c2h_size;
if (h2c_size) {
h2c = dma_alloc_coherent(&adapter->pdev->dev, h2c_size,
&h2c_dma_addr, GFP_KERNEL);
@@ -331,8 +394,7 @@ static int leapraid_ctl_do_command(struct leapraid_adapter *adapter,
}
}
- psge = (void *)ctl_sp_mpi_req + (karg->data_sge_offset *
- LEAPRAID_SGE_OFFSET_SIZE);
+ psge = (void *)ctl_sp_mpi_req + data_sge_offset_bytes;
init_completion(&adapter->driver_cmds.ctl_cmd.done);
switch (ctl_sp_mpi_req->func) {
@@ -388,6 +450,7 @@ static int leapraid_ctl_do_command(struct leapraid_adapter *adapter,
dev_err(&adapter->pdev->dev,
"%s: ctl_cmd timeout, status=0x%x\n",
__func__, adapter->driver_cmds.ctl_cmd.status);
+ leapraid_log_req_context(adapter, taskid, ctl_sp_mpi_req);
}
if ((leap_mpi_req->func == LEAPRAID_FUNC_SMP_PASSTHROUGH ||
@@ -517,7 +580,7 @@ static int leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd,
void __user *arg)
{
struct leapraid_ioctl_header ioctl_header;
- struct leapraid_adapter *adapter;
+ struct leapraid_adapter *adapter = NULL;
struct leapraid_ioctl_command __user *uarg;
struct leapraid_ioctl_command karg;
int rc = -ENOIOCTLCMD;
@@ -529,7 +592,7 @@ static int leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd,
return -EFAULT;
}
- adapter = leapraid_ctl_lookup_adapter(ioctl_header.adapter_id);
+ adapter = leapraid_ctl_lookup_adapter(ioctl_header.adapter_id, false);
if (!adapter)
return -EFAULT;
@@ -538,7 +601,8 @@ static int leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd,
"%s: Failed, thermal_alert=%d\n",
__func__,
atomic_read(&adapter->overheat_desc.thermal_alert));
- return -EFAULT;
+ rc = -EFAULT;
+ goto out_put;
}
mutex_lock(&adapter->access_ctrl.pci_access_lock);
@@ -590,7 +654,7 @@ static int leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd,
break;
}
- if (karg.hdr.adapter_id != ioctl_header.adapter_id) {
+ if (karg.hdr.adapter_id != ioctl_header.adapter_id) {
rc = -EINVAL;
break;
}
@@ -618,46 +682,78 @@ static int leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd,
unlock:
mutex_unlock(&adapter->access_ctrl.pci_access_lock);
+out_put:
+ leapraid_ctl_put_adapter(adapter);
return rc;
}
-static long bad_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- return -ENOTTY;
-}
-
static long leapraid_ctl_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
return leapraid_ctl_ioctl_main(file, cmd, (void __user *)arg);
}
+static void leapraid_fw_mmap_open(struct vm_area_struct *vma)
+{
+ struct leapraid_adapter *adapter = vma->vm_private_data;
+
+ if (!adapter)
+ return;
+
+ get_device(&adapter->shost->shost_gendev);
+ atomic_inc(&adapter->fw_log_desc.mmap_refcnt);
+}
+
+static void leapraid_fw_mmap_close(struct vm_area_struct *vma)
+{
+ struct leapraid_adapter *adapter = vma->vm_private_data;
+
+ if (!adapter)
+ return;
+
+ if (atomic_dec_and_test(&adapter->fw_log_desc.mmap_refcnt))
+ wake_up(&adapter->fw_log_desc.mmap_waitq);
+ leapraid_ctl_put_adapter(adapter);
+}
+
+static const struct vm_operations_struct leapraid_fw_mmap_vm_ops = {
+ .open = leapraid_fw_mmap_open,
+ .close = leapraid_fw_mmap_close,
+};
+
static int leapraid_fw_mmap(struct file *filp, struct vm_area_struct *vma)
{
- struct leapraid_adapter *adapter;
+ struct leapraid_adapter *adapter = NULL;
/* Userspace passes the adapter ID via vma->vm_pgoff. */
u32 adapter_id = vma->vm_pgoff;
unsigned long length;
- int rc;
+ int rc = -EINVAL;
length = vma->vm_end - vma->vm_start;
- adapter = leapraid_ctl_lookup_adapter(adapter_id);
+ adapter = leapraid_ctl_lookup_adapter(adapter_id, true);
if (!adapter) {
pr_err("%s: No adapter found!\n", __func__);
return -EINVAL;
}
+ if (READ_ONCE(adapter->access_ctrl.host_removing)) {
+ rc = -EAGAIN;
+ goto out_put;
+ }
+
if (length > (LEAPRAID_SYS_LOG_BUF_SIZE +
LEAPRAID_SYS_LOG_BUF_RESERVE)) {
dev_err(&adapter->pdev->dev,
"Requested mapping size is too large!\n");
- return -EINVAL;
+ rc = -EINVAL;
+ goto out_put;
}
if (!adapter->fw_log_desc.fw_log_buffer) {
dev_err(&adapter->pdev->dev, "No log buffer!\n");
- return -EINVAL;
+ rc = -EINVAL;
+ goto out_put;
}
vma->vm_pgoff = 0;
@@ -669,17 +765,26 @@ static int leapraid_fw_mmap(struct file *filp, struct vm_area_struct *vma)
if (rc) {
dev_err(&adapter->pdev->dev,
"Failed to map memory to user space!\n");
- return rc;
+ goto out_put;
}
- return 0;
+ vma->vm_private_data = adapter;
+ vma->vm_ops = &leapraid_fw_mmap_vm_ops;
+ leapraid_fw_mmap_open(vma);
+
+ rc = 0;
+out_put:
+ if (adapter &&
+ atomic_dec_and_test(&adapter->fw_log_desc.mmap_refcnt))
+ wake_up(&adapter->fw_log_desc.mmap_waitq);
+ leapraid_ctl_put_adapter(adapter);
+ return rc;
}
static const struct file_operations leapraid_ctl_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = leapraid_ctl_ioctl,
.mmap = leapraid_fw_mmap,
- .compat_ioctl = bad_ioctl,
};
static struct miscdevice leapraid_ctl_dev = {
diff --git a/drivers/scsi/leapraid/leapraid_func.c b/drivers/scsi/leapraid/leapraid_func.c
index f2574feb2514..32683f205d10 100644
--- a/drivers/scsi/leapraid/leapraid_func.c
+++ b/drivers/scsi/leapraid/leapraid_func.c
@@ -8,21 +8,6 @@
#include "leapraid_func.h"
-static int msix_disable;
-module_param(msix_disable, int, 0444);
-MODULE_PARM_DESC(msix_disable,
- "disable msix routed interrupts (default=0)");
-
-static int smart_poll;
-module_param(smart_poll, int, 0444);
-MODULE_PARM_DESC(smart_poll,
- "check SATA drive health via SMART polling: (default=0)");
-
-static int interrupt_mode;
-module_param(interrupt_mode, int, 0444);
-MODULE_PARM_DESC(interrupt_mode,
- "intr mode: 0 is MSI-X, 1 is MSI, 2 is legacy. (default=0)");
-
static int poll_queues;
module_param(poll_queues, int, 0444);
MODULE_PARM_DESC(poll_queues,
@@ -42,45 +27,23 @@ static void leapraid_ublk_io_dev(struct leapraid_adapter *adapter,
static void leapraid_clear_cached_boot_dev(struct leapraid_adapter *adapter,
void *dev, u32 chnl);
static int leapraid_make_adapter_available(struct leapraid_adapter *adapter);
+static void leapraid_sync_irqs_for_cleanup(struct leapraid_adapter *adapter);
static int leapraid_fw_log_init(struct leapraid_adapter *adapter);
static bool leapraid_should_skip_poll_work(struct leapraid_adapter *adapter);
static int leapraid_make_adapter_ready(struct leapraid_adapter *adapter,
enum reset_type type);
-static void leapraid_debug_log_info(struct leapraid_adapter *adapter)
+static noinline bool leapraid_shost_in_recovery(struct Scsi_Host *shost)
{
- struct leapraid_reg_base __iomem *iomem_base = adapter->iomem_base;
- u32 debug_log[LEAPRAID_DEBUGLOG_SZ_MAX];
- bool changed = false;
- int i;
+ enum scsi_host_state state;
- if (leapraid_should_skip_poll_work(adapter))
- return;
-
- for (i = 0; i < LEAPRAID_DEBUGLOG_SZ_MAX; i++) {
- debug_log[i] = leapraid_readl(&iomem_base->debug_log[i]);
- if (debug_log[i] != adapter->fw_log_desc.pre_debug_log[i])
- changed = true;
- }
-
- if (!changed)
- return;
-
- memcpy(adapter->fw_log_desc.pre_debug_log,
- debug_log,
- sizeof(debug_log));
-
- for (i = 0; i < LEAPRAID_DEBUGLOG_SZ_MAX;
- i += LEAPRAID_DEBUGLOG_DWORDS_PER_LINE)
- dev_warn(&adapter->pdev->dev,
- "debug_log[%d-%d]: 0x%08x 0x%08x 0x%08x 0x%08x\n",
- i,
- i + LEAPRAID_DEBUGLOG_DWORDS_PER_LINE - 1,
- debug_log[i],
- debug_log[i + 1],
- debug_log[i + 2],
- debug_log[i + 3]);
+ state = READ_ONCE(shost->shost_state);
+ return state == SHOST_RECOVERY ||
+ state == SHOST_CANCEL_RECOVERY ||
+ state == SHOST_DEL_RECOVERY ||
+ shost->tmf_in_progress;
}
+
static inline bool leapraid_is_end_dev(u32 dev_type)
{
return (dev_type & LEAPRAID_DEVTYP_END_DEV) &&
@@ -171,7 +134,6 @@ static void leapraid_overheat_suspend(struct leapraid_adapter *adapter)
pdev = adapter->pdev;
shost = pci_get_drvdata(pdev);
-
if (!shost) {
dev_warn(&pdev->dev,
"Overheat suspend failed, invalid host or adapter\n");
@@ -361,6 +323,12 @@ int leapraid_check_adapter_is_op(struct leapraid_adapter *adapter, int wait,
int wait_count;
for (wait_count = wait; wait_count > 0; wait_count--) {
+ if (READ_ONCE(adapter->access_ctrl.host_removing)) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Host is removing\n", caller);
+ return -EFAULT;
+ }
+
if (leapraid_pci_removed(adapter)) {
dev_warn(&adapter->pdev->dev,
"%s: PCI device removed\n", __func__);
@@ -499,11 +467,9 @@ static bool leapraid_is_fixed_taskid(struct leapraid_adapter *adapter,
struct leapraid_driver_cmds *driver_cmds = &adapter->driver_cmds;
return (taskid == driver_cmds->ctl_cmd.taskid ||
- taskid == driver_cmds->driver_scsiio_cmd.taskid ||
taskid == driver_cmds->tm_cmd.hp_taskid ||
taskid == driver_cmds->ctl_cmd.hp_taskid ||
taskid == driver_cmds->scan_dev_cmd.inter_taskid ||
- taskid == driver_cmds->timestamp_sync_cmd.inter_taskid ||
taskid == driver_cmds->transport_cmd.inter_taskid ||
taskid == driver_cmds->cfg_op_cmd.inter_taskid ||
taskid == driver_cmds->enc_cmd.inter_taskid ||
@@ -606,6 +572,8 @@ void leapraid_clean_active_scsi_cmds(struct leapraid_adapter *adapter)
void *task_desc;
u16 taskid;
+ leapraid_sync_irqs_for_cleanup(adapter);
+
for (taskid = 1; taskid <= adapter->shost->can_queue; taskid++) {
scmd = leapraid_get_scmd_from_taskid(adapter, taskid);
if (!scmd)
@@ -643,8 +611,6 @@ static void leapraid_clean_active_driver_cmds(struct leapraid_adapter *adapter)
struct leapraid_driver_cmds *driver_cmds;
driver_cmds = &adapter->driver_cmds;
- leapraid_clean_active_driver_cmd(&driver_cmds->timestamp_sync_cmd);
- leapraid_clean_active_driver_cmd(&driver_cmds->driver_scsiio_cmd);
leapraid_clean_active_driver_cmd(&driver_cmds->tm_cmd);
leapraid_clean_active_driver_cmd(&driver_cmds->transport_cmd);
leapraid_clean_active_driver_cmd(&driver_cmds->enc_cmd);
@@ -1912,16 +1878,6 @@ static const char *leapraid_sas_op_name(u8 op)
}
}
-static const char *leapraid_io_param_name(u8 adapter_param)
-{
- switch (adapter_param) {
- case LEAPRAID_SET_PARAMETER_SYNC_TIMESTAMP:
- return "SYNC_TIMESTAMP";
- default:
- return "UNKNOWN";
- }
-}
-
static const char *leapraid_tm_type_name(u8 task_type)
{
switch (task_type) {
@@ -1948,7 +1904,7 @@ static const char *leapraid_tm_type_name(u8 task_type)
}
}
-void leapraid_log_req_context(struct leapraid_adapter *adapter,
+void leapraid_log_req_context(struct leapraid_adapter *adapter, u16 smid,
const void *req_data)
{
const struct leapraid_req *req = req_data;
@@ -1961,8 +1917,8 @@ void leapraid_log_req_context(struct leapraid_adapter *adapter,
const struct leapraid_cfg_req *cfg_req = req_data;
dev_err(&adapter->pdev->dev,
- "cfg-req: func=0x%02x(%s) act=0x%02x(%s)\n",
- req->func, leapraid_func_name(req->func),
+ "cfg-req: smid=%u func=0x%02x(%s) action=0x%02x(%s)\n",
+ smid, req->func, leapraid_func_name(req->func),
cfg_req->action,
leapraid_cfg_action_name(cfg_req->action));
dev_err(&adapter->pdev->dev,
@@ -1984,12 +1940,12 @@ void leapraid_log_req_context(struct leapraid_adapter *adapter,
const struct leapraid_scsi_tm_req *tm_req = req_data;
dev_err(&adapter->pdev->dev,
- "scsi_tm: func=0x%02x(%s) task=0x%02x(%s)\n",
- req->func, leapraid_func_name(req->func),
+ "scsi_tm:: smid=%u func=0x%02x(%s) task=0x%02x(%s)\n",
+ smid, req->func, leapraid_func_name(req->func),
tm_req->task_type,
leapraid_tm_type_name(tm_req->task_type));
dev_err(&adapter->pdev->dev,
- "scsi_tm: dev_hdl=0x%04x task_mid=%u\n",
+ "scsi_tm:: dev_hdl=0x%04x task_mid=%u\n",
le16_to_cpu(tm_req->dev_hdl),
le16_to_cpu(tm_req->task_mid));
break;
@@ -1998,8 +1954,8 @@ void leapraid_log_req_context(struct leapraid_adapter *adapter,
const struct leapraid_sep_req *sep_req = req_data;
dev_err(&adapter->pdev->dev,
- "sep: func=0x%02x(%s) act=0x%02x(%s)\n",
- req->func, leapraid_func_name(req->func),
+ "sep: smid=%u func=0x%02x(%s) action=0x%02x(%s)\n",
+ smid, req->func, leapraid_func_name(req->func),
sep_req->act,
leapraid_sep_action_name(sep_req->act));
dev_err(&adapter->pdev->dev,
@@ -2013,32 +1969,34 @@ void leapraid_log_req_context(struct leapraid_adapter *adapter,
const struct leapraid_io_unit_ctrl_req *io_req = req_data;
dev_err(&adapter->pdev->dev,
- "timestamp sync: func=0x%02x(%s) op=0x%02x(%s)\n",
- req->func, leapraid_func_name(req->func),
+ "ctl_cmd: smid=%u func=0x%02x(%s) action=0x%02x(%s)\n",
+ smid, req->func, leapraid_func_name(req->func),
io_req->op, leapraid_sas_op_name(io_req->op));
dev_err(&adapter->pdev->dev,
- "timestamp sync: dev_hdl=0x%04x param=0x%02x(%s)\n",
+ "ctl_cmd: dev_hdl=0x%04x param=0x%02x\n",
le16_to_cpu(io_req->dev_hdl),
- io_req->adapter_para,
- leapraid_io_param_name(io_req->adapter_para));
+ io_req->adapter_para);
break;
}
case LEAPRAID_FUNC_SMP_PASSTHROUGH: {
const struct leapraid_smp_passthrough_req *smp_req = req_data;
dev_err(&adapter->pdev->dev,
- "transport: func=0x%02x(%s) port=%u req_len=%u\n",
- req->func, leapraid_func_name(req->func),
+ "smp_cmd: smid=%u func=0x%02x(%s) action=0x%02x\n",
+ smid, req->func, leapraid_func_name(req->func),
+ smp_req->passthrough_flg);
+ dev_err(&adapter->pdev->dev,
+ "smp_cmd: port=%u req_len=%u\n",
smp_req->physical_port,
le16_to_cpu(smp_req->req_data_len));
- dev_err(&adapter->pdev->dev, "transport: sas_addr=0x%016llx\n",
+ dev_err(&adapter->pdev->dev, "smp_cmd: sas_addr=0x%016llx\n",
(unsigned long long)le64_to_cpu(smp_req->sas_address));
break;
}
default:
dev_err(&adapter->pdev->dev,
- "%s: func=0x%02x(%s)\n",
- __func__, req->func, leapraid_func_name(req->func));
+ "cmd: smid=%u func=0x%02x(%s)\n",
+ smid, req->func, leapraid_func_name(req->func));
break;
}
}
@@ -2049,19 +2007,18 @@ static void leapraid_build_and_fire_cfg_req(
struct leapraid_cfg_rep *leap_mpi_cfgp_rep)
{
struct leapraid_cfg_req *local_leap_cfg_req;
+ u16 smid;
memset(leap_mpi_cfgp_rep, 0, sizeof(struct leapraid_cfg_rep));
memset(&adapter->driver_cmds.cfg_op_cmd.reply, 0,
sizeof(struct leapraid_cfg_rep));
adapter->driver_cmds.cfg_op_cmd.status = LEAPRAID_CMD_PENDING;
- local_leap_cfg_req = leapraid_get_task_desc(
- adapter,
- adapter->driver_cmds.cfg_op_cmd.inter_taskid);
+ smid = adapter->driver_cmds.cfg_op_cmd.inter_taskid;
+ local_leap_cfg_req = leapraid_get_task_desc(adapter, smid);
memcpy(local_leap_cfg_req, leap_mpi_cfgp_req,
sizeof(struct leapraid_cfg_req));
init_completion(&adapter->driver_cmds.cfg_op_cmd.done);
- leapraid_fire_task(adapter,
- adapter->driver_cmds.cfg_op_cmd.inter_taskid);
+ leapraid_fire_task(adapter, smid);
wait_for_completion_timeout(&adapter->driver_cmds.cfg_op_cmd.done,
LEAPRAID_CFG_OP_TIMEOUT * HZ);
}
@@ -2074,11 +2031,13 @@ static int leapraid_req_cfg_func(struct leapraid_adapter *adapter,
{
u32 adapter_status = UINT_MAX;
bool issue_reset = false;
+ u16 smid;
u8 retry_cnt;
int rc;
retry_cnt = 0;
mutex_lock(&adapter->driver_cmds.cfg_op_cmd.mutex);
+ smid = adapter->driver_cmds.cfg_op_cmd.inter_taskid;
retry:
if (retry_cnt) {
if (retry_cnt > LEAPRAID_CFG_REQ_RETRY_TIMES) {
@@ -2115,14 +2074,16 @@ static int leapraid_req_cfg_func(struct leapraid_adapter *adapter,
adapter->access_ctrl.shost_recovering ?
"shost recovery" : "pcie recovery",
adapter->driver_cmds.cfg_op_cmd.status);
- leapraid_log_req_context(adapter, leap_mpi_cfgp_req);
+ leapraid_log_req_context(adapter, smid,
+ leap_mpi_cfgp_req);
issue_reset = false;
rc = -EFAULT;
} else {
dev_err(&adapter->pdev->dev,
"cfg-req: timeout, status=0x%x, reset\n",
adapter->driver_cmds.cfg_op_cmd.status);
- leapraid_log_req_context(adapter, leap_mpi_cfgp_req);
+ leapraid_log_req_context(adapter, smid,
+ leap_mpi_cfgp_req);
issue_reset = true;
}
@@ -2162,7 +2123,7 @@ static int leapraid_req_cfg_func(struct leapraid_adapter *adapter,
mutex_unlock(&adapter->driver_cmds.cfg_op_cmd.mutex);
if (issue_reset) {
if (adapter->scan_dev_desc.first_scan_dev_fired) {
- dev_info(&adapter->pdev->dev,
+ dev_warn(&adapter->pdev->dev,
"%s:%d cfg-req: Failure, issuing reset\n",
__func__, __LINE__);
leapraid_hard_reset_handler(adapter, FULL_RESET);
@@ -2433,14 +2394,12 @@ static int leapraid_cfg_find_vol_in_page(
u16 phys_hdl;
phys_hdl = le16_to_cpu(elem->phys_disk_dev_hdl);
-
if (phys_hdl == pd_hdl) {
*vol_hdl = le16_to_cpu(elem->vol_dev_hdl);
return 0;
}
break;
}
-
case LEAPRAID_RAIDCFG_P0_EFLG_HOT_SPARE_ELEMENT:
*vol_hdl = 0;
return 0;
@@ -2607,7 +2566,6 @@ static int leapraid_cfg_get_number_pds(struct leapraid_adapter *adapter,
cfgp2.handle = hdl;
rc = leapraid_op_config_page(adapter, &raidvol_p0, cfgp1,
cfgp2, GET_RAID_VOLUME_PG0);
-
if (!rc)
*num_pds = raidvol_p0.num_phys_disks;
@@ -2821,61 +2779,6 @@ void leapraid_fw_log_start(struct leapraid_adapter *adapter)
spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
}
-static void leapraid_timestamp_sync(struct leapraid_adapter *adapter)
-{
- struct leapraid_io_unit_ctrl_req *io_unit_ctrl_req;
- ktime_t current_time;
- bool issue_reset = false;
- u64 time_stamp;
-
- mutex_lock(&adapter->driver_cmds.timestamp_sync_cmd.mutex);
- adapter->driver_cmds.timestamp_sync_cmd.status = LEAPRAID_CMD_PENDING;
- io_unit_ctrl_req =
- leapraid_get_task_desc(
- adapter,
- adapter->driver_cmds.timestamp_sync_cmd.inter_taskid);
- memset(io_unit_ctrl_req, 0, sizeof(struct leapraid_io_unit_ctrl_req));
- io_unit_ctrl_req->func = LEAPRAID_FUNC_SAS_IO_UNIT_CTRL;
- io_unit_ctrl_req->op = LEAPRAID_SAS_OP_SET_PARAMETER;
- io_unit_ctrl_req->adapter_para = LEAPRAID_SET_PARAMETER_SYNC_TIMESTAMP;
-
- current_time = ktime_get_real();
- time_stamp = ktime_to_ms(current_time);
-
- io_unit_ctrl_req->adapter_para_value =
- cpu_to_le32(time_stamp & 0xFFFFFFFF);
- io_unit_ctrl_req->adapter_para_value2 =
- cpu_to_le32(time_stamp >> 32);
- init_completion(&adapter->driver_cmds.timestamp_sync_cmd.done);
- leapraid_fire_task(
- adapter,
- adapter->driver_cmds.timestamp_sync_cmd.inter_taskid);
- leapraid_debug_log_info(adapter);
- wait_for_completion_timeout(&adapter->driver_cmds
- .timestamp_sync_cmd.done,
- LEAPRAID_TIMESTAMP_SYNC_CMD_TIMEOUT * HZ);
- if (!(adapter->driver_cmds.timestamp_sync_cmd.status &
- LEAPRAID_CMD_DONE)) {
- dev_err(&adapter->pdev->dev,
- "%s: timestamp sync timeout, status=0x%x\n",
- __func__,
- adapter->driver_cmds.timestamp_sync_cmd.status);
- leapraid_log_req_context(adapter, io_unit_ctrl_req);
- issue_reset =
- leapraid_check_reset(
- adapter->driver_cmds.timestamp_sync_cmd.status);
- }
-
- if (issue_reset) {
- dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
- __func__, __LINE__);
- leapraid_hard_reset_handler(adapter, FULL_RESET);
- }
-
- adapter->driver_cmds.timestamp_sync_cmd.status = LEAPRAID_CMD_NOT_USED;
- mutex_unlock(&adapter->driver_cmds.timestamp_sync_cmd.mutex);
-}
-
static void leapraid_check_scheduled_fault_work(struct work_struct *work)
{
struct leapraid_adapter *adapter;
@@ -2891,21 +2794,16 @@ static void leapraid_check_scheduled_fault_work(struct work_struct *work)
adapter_state = leapraid_get_adapter_state(adapter);
if (adapter_state != LEAPRAID_DB_OPERATIONAL) {
- dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
- __func__, __LINE__);
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset 0x%x\n",
+ __func__, __LINE__, adapter_state);
rc = leapraid_hard_reset_handler(adapter, FULL_RESET);
- dev_warn(&adapter->pdev->dev, "%s: Hard reset %s\n",
- __func__, rc == 0 ? "success" : "failed");
-
adapter_state = leapraid_get_adapter_state(adapter);
- if (rc && adapter_state != LEAPRAID_DB_OPERATIONAL)
+ if (rc && adapter_state != LEAPRAID_DB_OPERATIONAL) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Hard reset failed, state=0x%x rc=%d\n",
+ __func__, adapter_state, rc);
return;
- }
-
- if (++adapter->timestamp_sync_cnt >=
- LEAPRAID_TIMESTAMP_SYNC_INTERVAL) {
- adapter->timestamp_sync_cnt = 0;
- leapraid_timestamp_sync(adapter);
+ }
}
scheduled_timer:
@@ -2925,7 +2823,6 @@ void leapraid_check_scheduled_fault_start(struct leapraid_adapter *adapter)
if (adapter->reset_desc.fault_reset_wq)
return;
- adapter->timestamp_sync_cnt = 0;
INIT_DELAYED_WORK(&adapter->reset_desc.fault_reset_work,
leapraid_check_scheduled_fault_work);
snprintf(adapter->reset_desc.fault_reset_wq_name,
@@ -2968,308 +2865,6 @@ void leapraid_check_scheduled_fault_stop(struct leapraid_adapter *adapter)
destroy_workqueue(wq);
}
-static bool leapraid_ready_for_scsi_io(struct leapraid_adapter *adapter,
- u16 hdl)
-{
- if (adapter->access_ctrl.pcie_recovering ||
- adapter->access_ctrl.shost_recovering) {
- dev_err(&adapter->pdev->dev,
- "%s: Failed, pcie_recovering=%d shost_recovering=%d\n",
- __func__,
- adapter->access_ctrl.pcie_recovering,
- adapter->access_ctrl.shost_recovering);
- return false;
- }
-
- if (leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
- __func__))
- return false;
-
- if (hdl == LEAPRAID_INVALID_DEV_HANDLE) {
- dev_err(&adapter->pdev->dev,
- "%s: Device handle is invalid\n", __func__);
- return false;
- }
-
- return true;
-}
-
-static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter,
- struct leapraid_scsi_cmd_desc *cmd_desc)
-{
- struct scsi_device *sdev;
- struct scsi_device *target_sdev = NULL;
- struct leapraid_sdev_priv *sdev_priv;
- struct scsi_cmnd *scmd;
- void *dma_buffer = NULL;
- dma_addr_t dma_addr;
- bool issue_reset = false;
- int rc;
-
- if (WARN_ON(!adapter->driver_cmds.internal_scmd))
- return -EINVAL;
-
- if (!leapraid_ready_for_scsi_io(adapter, cmd_desc->hdl))
- return -EINVAL;
-
- mutex_lock(&adapter->driver_cmds.driver_scsiio_cmd.mutex);
- if (adapter->driver_cmds.driver_scsiio_cmd.status !=
- LEAPRAID_CMD_NOT_USED) {
- dev_err(&adapter->pdev->dev,
- "%s: scsiio cmd busy\n", __func__);
- rc = -EAGAIN;
- goto out_cleanup;
- }
- adapter->driver_cmds.driver_scsiio_cmd.status = LEAPRAID_CMD_PENDING;
-
- shost_for_each_device(sdev, adapter->shost) {
- sdev_priv = sdev->hostdata;
-
- if (sdev_priv->starget_priv->hdl == cmd_desc->hdl &&
- sdev_priv->lun == cmd_desc->lun) {
- target_sdev = sdev;
- break;
- }
- }
-
- if (!target_sdev) {
- dev_warn(&adapter->pdev->dev,
- "%s: Device not found\n", __func__);
- rc = -ENXIO;
- goto out_cleanup;
- }
-
- if (cmd_desc->data_length) {
- dma_buffer = dma_alloc_coherent(&adapter->pdev->dev,
- cmd_desc->data_length,
- &dma_addr, GFP_ATOMIC);
- if (!dma_buffer) {
- rc = -ENOMEM;
- goto out_cleanup;
- }
- if (cmd_desc->dir == DMA_TO_DEVICE)
- memcpy(dma_buffer, cmd_desc->data_buffer,
- cmd_desc->data_length);
- }
-
- scmd = adapter->driver_cmds.internal_scmd;
- scmd->device = target_sdev;
- scmd->cmd_len = cmd_desc->cdb_length;
- memcpy(scmd->cmnd, cmd_desc->cdb, cmd_desc->cdb_length);
- scmd->sc_data_direction = cmd_desc->dir;
- scmd->sdb.length = cmd_desc->data_length;
- scmd->sdb.table.nents = 1;
- scmd->sdb.table.orig_nents = 1;
- sg_init_one(scmd->sdb.table.sgl, dma_buffer, cmd_desc->data_length);
- init_completion(&adapter->driver_cmds.driver_scsiio_cmd.done);
- if (leapraid_queuecommand(adapter->shost, scmd)) {
- adapter->driver_cmds.driver_scsiio_cmd.status &=
- ~LEAPRAID_CMD_PENDING;
- complete(&adapter->driver_cmds.driver_scsiio_cmd.done);
- dev_err(&adapter->pdev->dev,
- "%s: queuecommand failed\n", __func__);
- rc = -EINVAL;
- goto out_cleanup;
- }
-
- wait_for_completion_timeout(&adapter->driver_cmds
- .driver_scsiio_cmd.done,
- cmd_desc->time_out * HZ);
-
- if (!(adapter->driver_cmds.driver_scsiio_cmd.status &
- LEAPRAID_CMD_DONE)) {
- issue_reset =
- leapraid_check_reset(
- adapter->driver_cmds.driver_scsiio_cmd.status);
- rc = -ENODATA;
- goto reset;
- }
-
- rc = adapter->driver_cmds.internal_scmd->result;
- if (!rc && cmd_desc->dir == DMA_FROM_DEVICE)
- memcpy(cmd_desc->data_buffer, dma_buffer,
- cmd_desc->data_length);
-
-reset:
- if (issue_reset) {
- rc = -ENODATA;
- dev_err(&adapter->pdev->dev, "fire tgt reset: hdl=0x%04x\n",
- cmd_desc->hdl);
- leapraid_issue_locked_tm(
- adapter, cmd_desc->hdl, 0, 0, 0,
- LEAPRAID_TM_TASKTYPE_TARGET_RESET,
- adapter->driver_cmds.driver_scsiio_cmd.taskid,
- LEAPRAID_TM_MSGFLAGS_LINK_RESET);
- }
-out_cleanup:
- if (target_sdev)
- scsi_device_put(target_sdev);
-
- if (dma_buffer)
- dma_free_coherent(&adapter->pdev->dev,
- cmd_desc->data_length,
- dma_buffer,
- dma_addr);
-
- adapter->driver_cmds.driver_scsiio_cmd.status = LEAPRAID_CMD_NOT_USED;
- mutex_unlock(&adapter->driver_cmds.driver_scsiio_cmd.mutex);
- return rc;
-}
-
-static int leapraid_dispatch_logsense(struct leapraid_adapter *adapter,
- u16 hdl, u32 lun)
-{
- struct leapraid_scsi_cmd_desc *desc;
- char *buf;
- int rc;
-
- desc = kzalloc(sizeof(*desc), GFP_KERNEL);
- if (!desc)
- return -ENOMEM;
-
- desc->hdl = hdl;
- desc->lun = lun;
- desc->data_length = LEAPRAID_LOGSENSE_DATA_LENGTH;
- desc->dir = DMA_FROM_DEVICE;
- desc->cdb_length = LEAPRAID_LOGSENSE_CDB_LENGTH;
- desc->cdb[0] = LOG_SENSE;
- desc->cdb[2] = LEAPRAID_LOGSENSE_CDB_CODE;
- desc->cdb[8] = desc->data_length;
- desc->raid_member = 0;
- desc->time_out = LEAPRAID_LOGSENSE_TIMEOUT;
-
- desc->data_buffer = kzalloc(desc->data_length, GFP_KERNEL);
- if (!desc->data_buffer) {
- kfree(desc);
- return -ENOMEM;
- }
-
- rc = leapraid_dispatch_scsi_io(adapter, desc);
- buf = desc->data_buffer;
-
- if (!rc && buf[8] == LEAPRAID_LOGSENSE_SMART_CODE)
- leapraid_smart_fault_detect(adapter, hdl);
-
- kfree(desc->data_buffer);
- kfree(desc);
-
- return rc;
-}
-
-static bool leapraid_smart_poll_check(struct leapraid_adapter *adapter,
- struct leapraid_sdev_priv *sdev_priv,
- u32 reset_flg)
-{
- struct leapraid_sas_dev *sas_dev;
-
- if (!sdev_priv || !sdev_priv->starget_priv->card_port)
- return false;
-
- sas_dev = leapraid_get_sas_dev_by_addr(
- adapter,
- sdev_priv->starget_priv->sas_address,
- sdev_priv->starget_priv->card_port);
- if (!sas_dev || !sas_dev->support_smart)
- goto out_fail;
-
- if (reset_flg)
- sas_dev->led_on = 0;
- else if (sas_dev->led_on)
- goto out_fail;
-
- if (sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER ||
- sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME ||
- sdev_priv->block)
- goto out_fail;
-
- leapraid_sdev_put(sas_dev);
- return true;
-
-out_fail:
- if (sas_dev)
- leapraid_sdev_put(sas_dev);
- return false;
-}
-
-static void leapraid_sata_smart_poll_work(struct work_struct *work)
-{
- struct leapraid_adapter *adapter =
- container_of(work, struct leapraid_adapter,
- smart_poll_desc.smart_poll_work.work);
- struct scsi_device *sdev;
- struct leapraid_sdev_priv *sdev_priv;
- bool reset_flg = false;
-
- if (leapraid_should_skip_poll_work(adapter))
- goto scheduled_timer;
-
- if (leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
- __func__))
- goto scheduled_timer;
-
- if (adapter->reset_desc.last_reset_cnt < adapter->reset_desc.reset_cnt)
- reset_flg = true;
-
- adapter->reset_desc.last_reset_cnt = adapter->reset_desc.reset_cnt;
-
- shost_for_each_device(sdev, adapter->shost) {
- sdev_priv = sdev->hostdata;
- if (leapraid_smart_poll_check(adapter, sdev_priv, reset_flg))
- leapraid_dispatch_logsense(adapter,
- sdev_priv->starget_priv->hdl,
- sdev_priv->lun);
- }
-
-scheduled_timer:
- if (adapter->smart_poll_desc.smart_poll_wq)
- queue_delayed_work(
- adapter->smart_poll_desc.smart_poll_wq,
- &adapter->smart_poll_desc.smart_poll_work,
- msecs_to_jiffies(LEAPRAID_SMART_POLLING_INTERVAL));
-}
-
-void leapraid_smart_polling_start(struct leapraid_adapter *adapter)
-{
- if (adapter->smart_poll_desc.smart_poll_wq || !smart_poll)
- return;
-
- INIT_DELAYED_WORK(&adapter->smart_poll_desc.smart_poll_work,
- leapraid_sata_smart_poll_work);
-
- snprintf(adapter->smart_poll_desc.smart_poll_wq_name,
- sizeof(adapter->smart_poll_desc.smart_poll_wq_name),
- "poll_%s%u_smart_poll",
- LEAPRAID_DRIVER_NAME,
- adapter->adapter_attr.id);
- adapter->smart_poll_desc.smart_poll_wq =
- create_singlethread_workqueue(
- adapter->smart_poll_desc.smart_poll_wq_name);
- if (!adapter->smart_poll_desc.smart_poll_wq)
- return;
- queue_delayed_work(adapter->smart_poll_desc.smart_poll_wq,
- &adapter->smart_poll_desc.smart_poll_work,
- msecs_to_jiffies(LEAPRAID_SMART_POLLING_INTERVAL));
-}
-
-void leapraid_smart_polling_stop(struct leapraid_adapter *adapter)
-{
- struct workqueue_struct *wq;
- struct leapraid_smart_poll_desc *desc;
-
- desc = &adapter->smart_poll_desc;
- if (!desc->smart_poll_wq)
- return;
-
- wq = desc->smart_poll_wq;
- desc->smart_poll_wq = NULL;
-
- if (wq) {
- if (!cancel_delayed_work_sync(&desc->smart_poll_work))
- flush_workqueue(wq);
- destroy_workqueue(wq);
- }
-}
-
static void leapraid_overheat_work(struct work_struct *work)
{
struct leapraid_overheat_desc *desc;
@@ -3304,13 +2899,11 @@ static void leapraid_overheat_work(struct work_struct *work)
adapter->scan_dev_desc.scan_start = 0;
adapter->scan_dev_desc.wait_scan_dev_done = 0;
adapter->scan_dev_desc.driver_loading = 0;
- wake_up(&adapter->access_ctrl.recovery_waitq);
wake_up(&adapter->access_ctrl.shost_recover_wq);
wake_up(&adapter->scan_dev_desc.wait_driver_loading);
leapraid_mask_int(adapter);
- leapraid_smart_polling_stop(adapter);
leapraid_check_scheduled_fault_stop(adapter);
leapraid_fw_log_stop(adapter);
leapraid_mq_polling_pause(adapter);
@@ -3393,10 +2986,10 @@ static struct leapraid_fw_evt_work *leapraid_alloc_fw_evt_work(void)
{
struct leapraid_fw_evt_work *fw_evt =
kzalloc(sizeof(*fw_evt), GFP_ATOMIC);
- if (!fw_evt)
- return NULL;
- kref_init(&fw_evt->refcnt);
+ if (fw_evt)
+ kref_init(&fw_evt->refcnt);
+
return fw_evt;
}
@@ -3413,10 +3006,14 @@ static void leapraid_fw_evt_add(struct leapraid_adapter *adapter,
{
unsigned long flags;
- if (!adapter->fw_evt_s.fw_evt_thread)
+ spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags);
+ if (adapter->access_ctrl.host_removing ||
+ adapter->access_ctrl.pcie_recovering ||
+ !adapter->fw_evt_s.fw_evt_thread) {
+ spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags);
return;
+ }
- spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags);
leapraid_fw_evt_get(fw_evt);
INIT_LIST_HEAD(&fw_evt->list);
list_add_tail(&fw_evt->list, &adapter->fw_evt_s.fw_evt_list);
@@ -3467,7 +3064,6 @@ void leapraid_clean_active_fw_evt(struct leapraid_adapter *adapter)
return;
adapter->fw_evt_s.fw_evt_cleanup = 1;
- wake_up(&adapter->access_ctrl.recovery_waitq);
if (adapter->access_ctrl.shost_recovering &&
adapter->fw_evt_s.cur_evt)
adapter->fw_evt_s.cur_evt->ignore = 1;
@@ -3742,8 +3338,6 @@ static struct leapraid_sas_dev *leapraid_init_sas_dev(
sas_dev->dev_name = le64_to_cpu(sas_dev_pg0->dev_name);
sas_dev->port_connection = sas_dev_pg0->max_port_connections;
sas_dev->slot = sas_dev->enc_hdl ? le16_to_cpu(sas_dev_pg0->slot) : 0;
- sas_dev->support_smart = (le16_to_cpu(sas_dev_pg0->flg) &
- LEAPRAID_SAS_DEV_P0_FLG_SATA_SMART);
if (le16_to_cpu(sas_dev_pg0->flg) &
LEAPRAID_SAS_DEV_P0_FLG_ENC_LEVEL_VALID) {
sas_dev->enc_level = sas_dev_pg0->enc_level;
@@ -3991,11 +3585,11 @@ static int leapraid_refresh_card_phy(struct leapraid_adapter *adapter,
return 0;
if (le32_to_cpu(phy_pg0.phy_info) &
- LEAPRAID_SAS_PHYINFO_VPHY &&
- !leapraid_alloc_vphy(adapter, port_id, i))
- return -EINVAL;
-
- card->card_phy[i].vphy = 1;
+ LEAPRAID_SAS_PHYINFO_VPHY) {
+ if (!leapraid_alloc_vphy(adapter, port_id, i))
+ return -ENOMEM;
+ card->card_phy[i].vphy = 1;
+ }
}
card->card_phy[i].hdl = card->hdl;
@@ -4382,7 +3976,7 @@ void leapraid_exp_rm(struct leapraid_adapter *adapter, u64 sas_addr,
leapraid_exp_node_rm(adapter, topo_node_exp);
}
-static int leapraid_internal_sas_topo_chg_evt(
+static void leapraid_internal_sas_topo_chg_evt(
struct leapraid_adapter *adapter,
struct leapraid_card_port *card_port,
struct leapraid_topo_node *topo_node_exp,
@@ -4399,11 +3993,11 @@ static int leapraid_internal_sas_topo_chg_evt(
evt_data = fw_evt->evt_data;
for (i = 0; i < evt_data->entry_num; i++) {
if (fw_evt->ignore)
- return 0;
+ return;
if (adapter->access_ctrl.host_removing ||
adapter->access_ctrl.pcie_recovering)
- return 0;
+ return;
phy_number = evt_data->start_phy_num + i;
if (phy_number >= max_phys)
@@ -4441,12 +4035,10 @@ static int leapraid_internal_sas_topo_chg_evt(
if (evt_data->exp_status == LEAPRAID_EVT_SAS_TOPO_ES_NOT_RESPONDING &&
topo_node_exp)
leapraid_exp_rm(adapter, sas_addr, card_port);
-
- return 0;
}
-static int leapraid_sas_topo_chg_evt(struct leapraid_adapter *adapter,
- struct leapraid_fw_evt_work *fw_evt)
+static void leapraid_sas_topo_chg_evt(struct leapraid_adapter *adapter,
+ struct leapraid_fw_evt_work *fw_evt)
{
struct leapraid_topo_node *topo_node_exp;
struct leapraid_card_port *card_port;
@@ -4459,13 +4051,13 @@ static int leapraid_sas_topo_chg_evt(struct leapraid_adapter *adapter,
if (adapter->access_ctrl.shost_recovering ||
adapter->access_ctrl.host_removing ||
adapter->access_ctrl.pcie_recovering)
- return 0;
+ return;
evt_data = fw_evt->evt_data;
leapraid_sas_host_add(adapter, adapter->dev_topo.card.phys_num > 0);
if (fw_evt->ignore)
- return 0;
+ return;
phdl = le16_to_cpu(evt_data->exp_dev_hdl);
card_port = leapraid_get_port_by_id(adapter,
@@ -4473,7 +4065,7 @@ static int leapraid_sas_topo_chg_evt(struct leapraid_adapter *adapter,
false);
if (evt_data->exp_status == LEAPRAID_EVT_SAS_TOPO_ES_ADDED &&
leapraid_exp_add(adapter, phdl) != 0)
- return 0;
+ return;
spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
topo_node_exp = leapraid_exp_find_by_hdl(adapter, phdl);
@@ -4487,13 +4079,13 @@ static int leapraid_sas_topo_chg_evt(struct leapraid_adapter *adapter,
} else {
spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock,
flags);
- return 0;
+ return;
}
spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags);
- return leapraid_internal_sas_topo_chg_evt(adapter, card_port,
- topo_node_exp, fw_evt,
- sas_addr, max_phys);
+ leapraid_internal_sas_topo_chg_evt(adapter, card_port,
+ topo_node_exp, fw_evt,
+ sas_addr, max_phys);
}
static void leapraid_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
@@ -4603,7 +4195,6 @@ static void leapraid_sas_pd_hide(
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
if (starget) {
- dev_info(&adapter->pdev->dev, "hide sas_dev, hdl=0x%x\n", hdl);
starget_for_each_device(starget,
(void *)LEAPRAID_NO_ULD_ATTACH_FLAG,
leapraid_reprobe_lun);
@@ -4623,7 +4214,6 @@ static void leapraid_sas_pd_expose(
u16 hdl;
hdl = le16_to_cpu(evt_data->phys_disk_dev_hdl);
-
if (!hdl || hdl > adapter->adapter_attr.features.max_dev_handle) {
dev_warn(&adapter->pdev->dev,
"%s: Invalid device handle\n", __func__);
@@ -4652,10 +4242,8 @@ static void leapraid_sas_pd_expose(
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
if (starget) {
- dev_info(&adapter->pdev->dev,
- "expose sas_dev, hdl=0x%x\n", hdl);
starget_for_each_device(starget,
- LEAPRAID_ULD_ATTACH_FLAG,
+ NULL,
leapraid_reprobe_lun);
}
@@ -4986,7 +4574,7 @@ static void leapraid_remove_unresp_sas_end_dev(
leapraid_sdev_put(sas_dev);
}
- dev_info(&adapter->pdev->dev,
+ dev_warn(&adapter->pdev->dev,
"Unresponsive SAS end devices removed\n");
}
@@ -5011,7 +4599,7 @@ static void leapraid_remove_unresp_raid_volumes(
leapraid_sas_volume_delete_by_ptr(adapter, raid_volume);
}
- dev_info(&adapter->pdev->dev,
+ dev_warn(&adapter->pdev->dev,
"Unresponsive RAID volumes removed\n");
}
@@ -5035,7 +4623,7 @@ static void leapraid_remove_unresp_sas_exp(struct leapraid_adapter *adapter)
&head, list)
leapraid_exp_node_rm(adapter, topo_node_exp);
- dev_info(&adapter->pdev->dev,
+ dev_warn(&adapter->pdev->dev,
"Unresponsive SAS expanders removed\n");
}
@@ -5153,8 +4741,6 @@ static void leapraid_scan_exp_after_reset(struct leapraid_adapter *adapter)
u16 hdl;
u8 port_id;
- dev_info(&adapter->pdev->dev, "Begin scanning expanders\n");
-
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (hdl = 0xFFFF, cfgp2.handle = hdl;
!leapraid_op_config_page(adapter, &exp_p0, cfgp1, cfgp2,
@@ -5185,8 +4771,6 @@ static void leapraid_scan_exp_after_reset(struct leapraid_adapter *adapter)
exp_p0.sas_address));
}
}
-
- dev_info(&adapter->pdev->dev, "Expanders scan complete\n");
}
static void leapraid_scan_phy_disks_after_reset(
@@ -5203,8 +4787,6 @@ static void leapraid_scan_phy_disks_after_reset(
u16 hdl, parent_hdl;
u64 sas_addr;
- dev_info(&adapter->pdev->dev, "Begin scanning phys disk\n");
-
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (phys_disk_num = 0xFF, cfgp2.form_specific = phys_disk_num;
!leapraid_op_config_page(adapter, &raidpd_p0,
@@ -5253,8 +4835,6 @@ static void leapraid_scan_phy_disks_after_reset(
}
}
}
-
- dev_info(&adapter->pdev->dev, "PHYs disk scan complete\n");
}
static void leapraid_scan_vol_after_reset(struct leapraid_adapter *adapter)
@@ -5279,7 +4859,6 @@ static void leapraid_scan_vol_after_reset(struct leapraid_adapter *adapter)
return;
}
- dev_info(&adapter->pdev->dev, "Begin scanning volumes\n");
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (hdl = 0xFFFF, cfgp2.handle = hdl;
!leapraid_op_config_page(adapter, vol_p1, cfgp1,
@@ -5316,8 +4895,6 @@ static void leapraid_scan_vol_after_reset(struct leapraid_adapter *adapter)
kfree(vol_p0);
kfree(vol_p1);
-
- dev_info(&adapter->pdev->dev, "Volumes scan complete\n");
}
static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter)
@@ -5330,9 +4907,6 @@ static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter)
u64 sas_address;
u8 port_id;
- dev_info(&adapter->pdev->dev,
- "Begin scanning SAS end devices\n");
-
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (hdl = 0xFFFF, cfgp2.handle = hdl;
!leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1, cfgp2,
@@ -5382,14 +4956,10 @@ static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter)
sas_dev_p0.sas_address));
}
}
-
- dev_info(&adapter->pdev->dev, "SAS end devices scan complete\n");
}
static void leapraid_scan_all_dev_after_reset(struct leapraid_adapter *adapter)
{
- dev_info(&adapter->pdev->dev, "Begin scanning devices\n");
-
leapraid_sas_host_add(adapter, adapter->dev_topo.card.phys_num > 0);
leapraid_scan_exp_after_reset(adapter);
if (adapter->adapter_attr.raid_support) {
@@ -5397,8 +4967,6 @@ static void leapraid_scan_all_dev_after_reset(struct leapraid_adapter *adapter)
leapraid_scan_vol_after_reset(adapter);
}
leapraid_scan_sas_dev_after_reset(adapter);
-
- dev_info(&adapter->pdev->dev, "Devices scan complete\n");
}
static void leapraid_hardreset_async_logic(struct leapraid_adapter *adapter)
@@ -5426,6 +4994,7 @@ static int leapraid_send_enc_cmd(struct leapraid_adapter *adapter,
void *req;
bool reset_flg = false;
int rc;
+ u16 smid;
mutex_lock(&adapter->driver_cmds.enc_cmd.mutex);
rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
@@ -5434,21 +5003,19 @@ static int leapraid_send_enc_cmd(struct leapraid_adapter *adapter,
goto unlock;
adapter->driver_cmds.enc_cmd.status = LEAPRAID_CMD_PENDING;
- req = leapraid_get_task_desc(
- adapter,
- adapter->driver_cmds.enc_cmd.inter_taskid);
+ smid = adapter->driver_cmds.enc_cmd.inter_taskid;
+ req = leapraid_get_task_desc(adapter, smid);
memset(req, 0, LEAPRAID_REQUEST_SIZE);
memcpy(req, sep_req, sizeof(struct leapraid_sep_req));
init_completion(&adapter->driver_cmds.enc_cmd.done);
- leapraid_fire_task(adapter,
- adapter->driver_cmds.enc_cmd.inter_taskid);
+ leapraid_fire_task(adapter, smid);
wait_for_completion_timeout(&adapter->driver_cmds.enc_cmd.done,
LEAPRAID_ENC_CMD_TIMEOUT * HZ);
if (!(adapter->driver_cmds.enc_cmd.status & LEAPRAID_CMD_DONE)) {
dev_err(&adapter->pdev->dev,
"%s: SEP command timeout, status=0x%x\n",
__func__, adapter->driver_cmds.enc_cmd.status);
- leapraid_log_req_context(adapter, sep_req);
+ leapraid_log_req_context(adapter, smid, sep_req);
reset_flg =
leapraid_check_reset(
adapter->driver_cmds.enc_cmd.status);
@@ -5512,10 +5079,10 @@ static int leapraid_wait_adapter_recovery(struct leapraid_adapter *adapter)
{
unsigned long flags;
- while (scsi_host_in_recovery(adapter->shost) ||
- adapter->access_ctrl.shost_recovering) {
- if (adapter->access_ctrl.host_removing ||
- adapter->fw_evt_s.fw_evt_cleanup) {
+ while (leapraid_shost_in_recovery(adapter->shost) ||
+ READ_ONCE(adapter->access_ctrl.shost_recovering)) {
+ if (READ_ONCE(adapter->access_ctrl.host_removing) ||
+ READ_ONCE(adapter->fw_evt_s.fw_evt_cleanup)) {
spin_lock_irqsave(
&adapter->reset_desc.adapter_reset_lock,
flags);
@@ -5535,12 +5102,13 @@ static int leapraid_wait_adapter_recovery(struct leapraid_adapter *adapter)
return -EFAULT;
}
- wait_event_timeout(adapter->access_ctrl.recovery_waitq,
- !adapter->access_ctrl.shost_recovering ||
- adapter->access_ctrl.host_removing ||
- adapter->fw_evt_s.fw_evt_cleanup,
- msecs_to_jiffies(1000));
+ wait_event_timeout(
+ adapter->access_ctrl.recovery_waitq,
+ (!leapraid_shost_in_recovery(adapter->shost) &&
+ !READ_ONCE(adapter->access_ctrl.shost_recovering)),
+ msecs_to_jiffies(1000));
}
+
return 0;
}
@@ -5625,7 +5193,6 @@ static void leapraid_sas_dev_stat_chg_evt(
leapraid_get_port_by_id(adapter,
event_data->physical_port,
false));
-
if (!sas_dev || !sas_dev->starget)
goto out_unlock;
@@ -5755,6 +5322,80 @@ static void leapraid_check_topo_del_evts(
leapraid_topo_del_evts_process_exp_status(adapter, evt_data);
}
+static bool leapraid_async_evt_validate(
+ struct leapraid_adapter *adapter,
+ struct leapraid_evt_notify_rep *event_notify_rep)
+{
+ size_t msg_len;
+ size_t evt_sz;
+ size_t evt_avail;
+ u16 evt;
+
+ msg_len = event_notify_rep->msg_len * sizeof(u32);
+ if (msg_len > LEAPRAID_REPLY_SIZE ||
+ msg_len < offsetof(struct leapraid_evt_notify_rep, evt_data)) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid async event msg_len=%zu\n",
+ __func__, msg_len);
+ return false;
+ }
+
+ evt_sz = le16_to_cpu(event_notify_rep->evt_data_len) * sizeof(u32);
+ evt_avail = msg_len -
+ offsetof(struct leapraid_evt_notify_rep, evt_data);
+ if (evt_sz > evt_avail) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid async event evt_data_len=%zu\n",
+ __func__, evt_sz);
+ return false;
+ }
+
+ evt = le16_to_cpu(event_notify_rep->evt);
+ switch (evt) {
+ case LEAPRAID_EVT_SAS_DEV_STATUS_CHANGE:
+ if (evt_sz <
+ sizeof(struct leapraid_evt_data_sas_dev_status_change))
+ goto invalid_evt_sz;
+ break;
+ case LEAPRAID_EVT_IR_CHANGE:
+ if (evt_sz < sizeof(struct leapraid_evt_data_ir_change))
+ goto invalid_evt_sz;
+ break;
+ case LEAPRAID_EVT_SAS_TOPO_CHANGE_LIST:
+ {
+ struct leapraid_evt_data_sas_topo_change_list *evt_data =
+ (void *)event_notify_rep->evt_data;
+ size_t hdr_sz;
+
+ hdr_sz =
+ offsetof(struct leapraid_evt_data_sas_topo_change_list,
+ phy);
+ if (evt_sz < hdr_sz)
+ goto invalid_evt_sz;
+
+ if (evt_data->entry_num >
+ (evt_sz - hdr_sz) / sizeof(evt_data->phy[0]))
+ goto invalid_evt_sz;
+ break;
+ }
+ case LEAPRAID_EVT_SAS_ENCL_DEV_STATUS_CHANGE:
+ if (evt_sz <
+ sizeof(struct leapraid_evt_data_sas_enc_dev_status_change))
+ goto invalid_evt_sz;
+ break;
+ default:
+ break;
+ }
+
+ return true;
+
+invalid_evt_sz:
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid async event size=%zu for evt=0x%x\n",
+ __func__, evt_sz, evt);
+ return false;
+}
+
static bool leapraid_async_process_evt(
struct leapraid_adapter *adapter,
struct leapraid_evt_notify_rep *event_notify_rep)
@@ -5762,6 +5403,10 @@ static bool leapraid_async_process_evt(
u16 evt = le16_to_cpu(event_notify_rep->evt);
bool exit_flag = false;
+ if (adapter->access_ctrl.host_removing ||
+ adapter->access_ctrl.pcie_recovering)
+ return true;
+
switch (evt) {
case LEAPRAID_EVT_SAS_DEV_STATUS_CHANGE:
leapraid_sas_dev_stat_chg_evt(
@@ -5824,13 +5469,17 @@ static void leapraid_async_evt_cb(struct leapraid_adapter *adapter,
{
struct leapraid_evt_notify_rep *evt_notify_rep;
- if (adapter->access_ctrl.pcie_recovering)
+ if (adapter->access_ctrl.host_removing ||
+ adapter->access_ctrl.pcie_recovering)
return;
evt_notify_rep = leapraid_get_reply_vaddr(adapter, rep_paddr);
if (unlikely(!evt_notify_rep))
return;
+ if (!leapraid_async_evt_validate(adapter, evt_notify_rep))
+ return;
+
if (leapraid_async_process_evt(adapter, evt_notify_rep))
return;
@@ -5895,9 +5544,9 @@ static void leapraid_scan_dev_complete(struct leapraid_adapter *adapter)
leapraid_fw_evt_put(fw_evt);
}
-static u8 leapraid_handle_scan_cb(struct leapraid_adapter *adapter,
- struct leapraid_driver_cmd *cmd,
- struct leapraid_rep *rep)
+static void leapraid_handle_scan_cb(struct leapraid_adapter *adapter,
+ struct leapraid_driver_cmd *cmd,
+ struct leapraid_rep *rep)
{
u16 status;
@@ -5905,21 +5554,18 @@ static u8 leapraid_handle_scan_cb(struct leapraid_adapter *adapter,
status = le16_to_cpu(rep->adapter_status) &
LEAPRAID_ADAPTER_STATUS_MASK;
-
if (status != LEAPRAID_ADAPTER_STATUS_SUCCESS)
adapter->scan_dev_desc.scan_dev_failed = 1;
if (!cmd->async_scan_dev) {
complete(&cmd->done);
- return 1;
+ return;
}
if (status == LEAPRAID_ADAPTER_STATUS_SUCCESS)
leapraid_scan_dev_complete(adapter);
else
adapter->scan_dev_desc.scan_start_failed = status;
-
- return 1;
}
static void leapraid_handle_ctl_cb(struct leapraid_adapter *adapter,
@@ -5933,7 +5579,6 @@ static void leapraid_handle_ctl_cb(struct leapraid_adapter *adapter,
return;
scsiio_reply = (struct leapraid_scsiio_rep *)rep;
-
if (!(scsiio_reply->scsi_state &
LEAPRAID_SCSI_STATE_AUTOSENSE_VALID))
return;
@@ -5976,10 +5621,11 @@ static bool leapraid_driver_cmds_done(struct leapraid_adapter *adapter,
memcpy(&_sp_cmd->reply, leap_mpi_rep, reply_len);
_sp_cmd->status |= LEAPRAID_CMD_REPLY_VALID;
- if (_sp_cmd->cb_idx == LEAPRAID_SCAN_DEV_CB_IDX)
- return leapraid_handle_scan_cb(adapter,
- _sp_cmd,
- leap_mpi_rep);
+ if (_sp_cmd->cb_idx == LEAPRAID_SCAN_DEV_CB_IDX) {
+ leapraid_handle_scan_cb(adapter, _sp_cmd,
+ leap_mpi_rep);
+ return true;
+ }
if (_sp_cmd->cb_idx == LEAPRAID_CTL_CB_IDX)
leapraid_handle_ctl_cb(adapter, leap_mpi_rep, taskid);
@@ -5994,8 +5640,9 @@ static bool leapraid_driver_cmds_done(struct leapraid_adapter *adapter,
static void leapraid_complete_task(struct leapraid_adapter *adapter,
u16 taskid, u8 msix_idx, u32 rep)
{
- if (taskid <= adapter->shost->can_queue ||
- taskid == adapter->driver_cmds.driver_scsiio_cmd.taskid) {
+ bool scsiio_task = taskid <= adapter->shost->can_queue;
+
+ if (scsiio_task) {
if (leapraid_scsiio_done(adapter, taskid, msix_idx, rep))
leapraid_free_taskid(adapter, taskid);
return;
@@ -6175,6 +5822,22 @@ void leapraid_sync_irqs(struct leapraid_adapter *adapter, bool poll)
}
}
+static void leapraid_sync_irqs_for_cleanup(struct leapraid_adapter *adapter)
+{
+ struct leapraid_notification_desc *desc = &adapter->notification_desc;
+ struct leapraid_int_rq *int_rq;
+ unsigned int i;
+
+ if (!adapter->mask_int && leapraid_pci_active(adapter))
+ leapraid_mask_int(adapter);
+
+ for (i = 0; i < desc->int_rqs_allocated; i++) {
+ int_rq = &desc->int_rqs[i];
+ synchronize_irq(pci_irq_vector(adapter->pdev,
+ int_rq->rq.msix_idx));
+ }
+}
+
void leapraid_mq_polling_pause(struct leapraid_adapter *adapter)
{
struct leapraid_notification_desc *desc;
@@ -6245,7 +5908,6 @@ static int leapraid_host_diag_reset(struct leapraid_adapter *adapter)
{
u32 host_diag;
- dev_info(&adapter->pdev->dev, "Entering host diag reset!\n");
pci_cfg_access_lock(adapter->pdev);
mutex_lock(&adapter->reset_desc.host_diag_mutex);
@@ -6269,14 +5931,13 @@ static int leapraid_host_diag_reset(struct leapraid_adapter *adapter)
goto out_failed;
pci_cfg_access_unlock(adapter->pdev);
- dev_info(&adapter->pdev->dev, "Host diag success!\n");
return 0;
out_cleanup:
mutex_unlock(&adapter->reset_desc.host_diag_mutex);
out_failed:
pci_cfg_access_unlock(adapter->pdev);
- dev_info(&adapter->pdev->dev, "Host diag failed!\n");
+ dev_err(&adapter->pdev->dev, "Host diag failed\n");
return -EFAULT;
}
@@ -6791,11 +6452,8 @@ static void leapraid_search_resp_sas_dev(struct leapraid_adapter *adapter)
struct leapraid_sas_dev_p0 sas_dev_p0;
u32 device_info;
- dev_info(&adapter->pdev->dev,
- "Begin searching for SAS end devices\n");
-
if (list_empty(&adapter->dev_topo.sas_dev_list))
- goto exit_search;
+ return;
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (cfgp2.handle = 0xFFFF;
@@ -6808,9 +6466,6 @@ static void leapraid_search_resp_sas_dev(struct leapraid_adapter *adapter)
leapraid_mark_resp_sas_dev(adapter, &sas_dev_p0);
}
-exit_search:
- dev_info(&adapter->pdev->dev,
- "SAS end devices searching complete\n");
}
static void leapraid_mark_resp_raid_volume(struct leapraid_adapter *adapter,
@@ -6879,14 +6534,11 @@ static void leapraid_search_resp_raid_volume(struct leapraid_adapter *adapter)
if (!adapter->adapter_attr.raid_support)
return;
- dev_info(&adapter->pdev->dev,
- "Begin searching for RAID volumes\n");
-
spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
is_empty = list_empty(&adapter->dev_topo.raid_volume_list);
spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
if (is_empty)
- goto exit_search;
+ return;
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (hdl = 0xFFFF, cfgp2.handle = hdl;
@@ -6924,9 +6576,6 @@ static void leapraid_search_resp_raid_volume(struct leapraid_adapter *adapter)
else
set_bit(hdl, adapter->dev_topo.pd_hdls);
}
-exit_search:
- dev_info(&adapter->pdev->dev,
- "RAID volumes searching complete\n");
}
static void leapraid_mark_resp_exp(struct leapraid_adapter *adapter,
@@ -6987,10 +6636,8 @@ static void leapraid_search_resp_exp(struct leapraid_adapter *adapter)
u16 hdl;
u8 port;
- dev_dbg(&adapter->pdev->dev,
- "Begin searching for expanders\n");
if (list_empty(&adapter->dev_topo.exp_list))
- goto exit_search;
+ return;
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (hdl = 0xFFFF, cfgp2.handle = hdl;
@@ -7008,9 +6655,6 @@ static void leapraid_search_resp_exp(struct leapraid_adapter *adapter)
LEAPRAID_DISABLE_MP_PORT_ID);
leapraid_mark_resp_exp(adapter, &exp_p0);
}
-exit_search:
- dev_dbg(&adapter->pdev->dev,
- "Expander searching complete\n");
}
void leapraid_wait_cmds_done(struct leapraid_adapter *adapter)
@@ -7057,6 +6701,15 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter,
mutex_lock(&adapter->reset_desc.adapter_reset_mutex);
+ if (adapter->access_ctrl.shost_recover_async) {
+ rc = adapter->reset_desc.adapter_reset_results;
+ dev_info(&adapter->pdev->dev,
+ "Skip nested hard reset, async evt running, rc=%d\n",
+ rc);
+ mutex_unlock(&adapter->reset_desc.adapter_reset_mutex);
+ return rc;
+ }
+
if (!leapraid_pci_active(adapter)) {
if (leapraid_pci_removed(adapter)) {
dev_info(&adapter->pdev->dev,
@@ -7099,7 +6752,6 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter,
dev_err(&adapter->pdev->dev,
"Previous device scan failed or driver loading\n");
adapter->access_ctrl.host_removing = 1;
- wake_up(&adapter->access_ctrl.recovery_waitq);
rc = -EFAULT;
goto out_cleanup;
}
@@ -7120,8 +6772,8 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter,
leapraid_hardreset_barrier(adapter);
}
out_cleanup:
- dev_info(&adapter->pdev->dev, "Hard reset %s\n",
- rc == 0 ? "SUCCESS" : "FAILED");
+ if (rc)
+ dev_err(&adapter->pdev->dev, "Hard reset failed\n");
spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
adapter->reset_desc.adapter_reset_results = rc;
@@ -7253,9 +6905,17 @@ static int leapraid_get_adapter_features(struct leapraid_adapter *adapter)
fw_major, fw_minor, fw_build, fw_release,
adapter->adapter_attr.features.fw_version);
- if (fw_major < 2) {
- dev_err(&adapter->pdev->dev,
- "Unsupported firmware major version, requires >= 2\n");
+ adapter->adapter_attr.features.msg_ver =
+ le16_to_cpu(leap_mpi_rep.msg_ver);
+ adapter->adapter_attr.features.product_id =
+ le16_to_cpu(leap_mpi_rep.product_id);
+ dev_info(&adapter->pdev->dev,
+ "message version: 0x%x, product id 0x%x\n",
+ adapter->adapter_attr.features.msg_ver,
+ adapter->adapter_attr.features.product_id);
+
+ if (adapter->adapter_attr.features.msg_ver < 0x1000) {
+ dev_err(&adapter->pdev->dev, "Device not supported\n");
return -EFAULT;
}
adapter->shost->max_id = LEAPRAID_INVALID_INITIAL_VALUE;
@@ -7340,13 +7000,16 @@ static void leapraid_cpus_on_irq(struct leapraid_adapter *adapter)
index++) {
int_rq = &adapter->notification_desc.int_rqs[index];
- if (cpu >= nr_cpus)
+ if (cpu >= adapter->notification_desc.msix_cpu_map_sz)
break;
this_group = base_group +
(index < (nr_cpus % total_msix) ? 1 : 0);
for (i = 0 ; i < this_group ; i++) {
+ if (cpu >= adapter->notification_desc.msix_cpu_map_sz)
+ break;
+
adapter->notification_desc.msix_cpu_map[cpu] =
int_rq->rq.msix_idx;
cpu = cpumask_next(cpu, cpu_online_mask);
@@ -7358,8 +7021,8 @@ static void leapraid_map_msix_to_cpu(struct leapraid_adapter *adapter)
{
struct leapraid_int_rq *int_rq;
const cpumask_t *affinity_mask;
+ int cpu;
u32 i;
- u16 cpu;
if (!adapter->adapter_attr.rq_cnt)
return;
@@ -7377,16 +7040,29 @@ static void leapraid_map_msix_to_cpu(struct leapraid_adapter *adapter)
for_each_cpu_and(cpu, affinity_mask, cpu_online_mask) {
if (cpu >= adapter->notification_desc.msix_cpu_map_sz)
- break;
+ continue;
adapter->notification_desc.msix_cpu_map[cpu] =
int_rq->rq.msix_idx;
}
}
+ return;
out_apply_irq_affinity:
leapraid_cpus_on_irq(adapter);
}
+static int leapraid_alloc_msix_cpu_map(struct leapraid_adapter *adapter)
+{
+ adapter->notification_desc.msix_cpu_map_sz = nr_cpu_ids;
+ adapter->notification_desc.msix_cpu_map =
+ kzalloc(adapter->notification_desc.msix_cpu_map_sz,
+ GFP_KERNEL);
+ if (!adapter->notification_desc.msix_cpu_map)
+ return -ENOMEM;
+
+ return 0;
+}
+
static void leapraid_configure_reply_queue_affinity(
struct leapraid_adapter *adapter)
{
@@ -7436,16 +7112,16 @@ static void leapraid_free_irq(struct leapraid_adapter *adapter)
static int leapraid_setup_irqs(struct leapraid_adapter *adapter)
{
+ int irq_mode = adapter->notification_desc.irq_mode;
unsigned int i;
int rc = 0;
- if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSIX) {
+ if (irq_mode == LEAPRAID_INTERRUPT_MODE_MSIX) {
rc = pci_alloc_irq_vectors_affinity(
adapter->pdev,
adapter->notification_desc.iopoll_qdex,
adapter->notification_desc.iopoll_qdex,
PCI_IRQ_MSIX | PCI_IRQ_AFFINITY, NULL);
-
if (rc < 0) {
dev_err(&adapter->pdev->dev,
"%d MSI/MSIX vectors allocated failed!\n",
@@ -7454,20 +7130,18 @@ static int leapraid_setup_irqs(struct leapraid_adapter *adapter)
}
adapter->notification_desc.irq_vectors_allocated = 1;
- adapter->notification_desc.irq_mode =
- LEAPRAID_INTERRUPT_MODE_MSIX;
}
for (i = 0; i < adapter->notification_desc.iopoll_qdex; i++) {
adapter->notification_desc.int_rqs[i].rq.adapter = adapter;
adapter->notification_desc.int_rqs[i].rq.msix_idx = i;
atomic_set(&adapter->notification_desc.int_rqs[i].rq.busy, 0);
- if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSIX)
+ if (irq_mode == LEAPRAID_INTERRUPT_MODE_MSIX)
snprintf(adapter->notification_desc.int_rqs[i].rq.name,
LEAPRAID_NAME_LENGTH, "%s%u-MSIx%u",
LEAPRAID_DRIVER_NAME,
adapter->adapter_attr.id, i);
- else if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSI)
+ else if (irq_mode == LEAPRAID_INTERRUPT_MODE_MSI)
snprintf(adapter->notification_desc.int_rqs[i].rq.name,
LEAPRAID_NAME_LENGTH, "%s%u-MSI%u",
LEAPRAID_DRIVER_NAME,
@@ -7478,7 +7152,6 @@ static int leapraid_setup_irqs(struct leapraid_adapter *adapter)
IRQF_SHARED,
adapter->notification_desc.int_rqs[i].rq.name,
&adapter->notification_desc.int_rqs[i].rq);
-
if (rc) {
dev_err(&adapter->pdev->dev,
"MSI/MSIx: request_irq %s failed!\n",
@@ -7538,12 +7211,9 @@ static int leapraid_set_legacy_int(struct leapraid_adapter *adapter)
{
int rc;
- adapter->notification_desc.msix_cpu_map_sz = num_online_cpus();
- adapter->notification_desc.msix_cpu_map =
- kzalloc(adapter->notification_desc.msix_cpu_map_sz,
- GFP_KERNEL);
- if (!adapter->notification_desc.msix_cpu_map)
- return -ENOMEM;
+ rc = leapraid_alloc_msix_cpu_map(adapter);
+ if (rc)
+ return rc;
adapter->adapter_attr.rq_cnt = 1;
adapter->notification_desc.iopoll_qdex =
@@ -7560,9 +7230,7 @@ static int leapraid_set_legacy_int(struct leapraid_adapter *adapter)
if (!adapter->notification_desc.int_rqs)
return -ENOMEM;
- rc = leapraid_setup_legacy_int(adapter);
-
- return rc;
+ return leapraid_setup_legacy_int(adapter);
}
static int leapraid_set_msix(struct leapraid_adapter *adapter)
@@ -7571,14 +7239,11 @@ static int leapraid_set_msix(struct leapraid_adapter *adapter)
unsigned int i;
int rc, msix_cnt;
- if (msix_disable == 1)
- goto apply_legacy_int;
-
msix_cnt = pci_msix_vec_count(adapter->pdev);
if (msix_cnt <= 0 ||
adapter->adapter_attr.features.max_msix_vectors == 0) {
dev_info(&adapter->pdev->dev, "MSIX unsupported!\n");
- goto apply_legacy_int;
+ return -EOPNOTSUPP;
}
msix_cnt = min_t(int, msix_cnt,
@@ -7648,31 +7313,20 @@ static int leapraid_set_msix(struct leapraid_adapter *adapter)
0);
}
- adapter->notification_desc.msix_cpu_map_sz =
- num_online_cpus();
- adapter->notification_desc.msix_cpu_map =
- kzalloc(adapter->notification_desc.msix_cpu_map_sz,
- GFP_KERNEL);
- if (!adapter->notification_desc.msix_cpu_map)
- return -ENOMEM;
-
- memset(adapter->notification_desc.msix_cpu_map, 0,
- adapter->notification_desc.msix_cpu_map_sz);
+ rc = leapraid_alloc_msix_cpu_map(adapter);
+ if (rc)
+ return rc;
+ adapter->notification_desc.irq_mode = LEAPRAID_INTERRUPT_MODE_MSIX;
adapter->notification_desc.msix_enable = 1;
rc = leapraid_setup_irqs(adapter);
if (rc) {
leapraid_free_irq(adapter);
adapter->notification_desc.msix_enable = 0;
- goto apply_legacy_int;
+ return rc;
}
return 0;
-
-apply_legacy_int:
- rc = leapraid_set_legacy_int(adapter);
-
- return rc;
}
static int leapraid_set_msi(struct leapraid_adapter *adapter)
@@ -7681,14 +7335,11 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter)
unsigned int i;
int rc, msi_cnt;
- if (msix_disable == 1)
- goto apply_legacy_int;
-
msi_cnt = pci_msi_vec_count(adapter->pdev);
if (msi_cnt <= 0 ||
adapter->adapter_attr.features.max_msix_vectors == 0) {
dev_info(&adapter->pdev->dev, "MSI unsupported!\n");
- goto apply_legacy_int;
+ return -EOPNOTSUPP;
}
msi_cnt = min_t(int, msi_cnt,
@@ -7738,10 +7389,9 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter)
"%d MSI vectors allocated failed!\n",
adapter->notification_desc.iopoll_qdex);
leapraid_free_irq(adapter);
- goto apply_legacy_int;
+ return rc;
}
adapter->notification_desc.irq_vectors_allocated = 1;
- adapter->notification_desc.irq_mode = LEAPRAID_INTERRUPT_MODE_MSI;
if (rc != adapter->notification_desc.iopoll_qdex) {
adapter->notification_desc.iopoll_qdex = rc;
adapter->adapter_attr.rq_cnt =
@@ -7781,51 +7431,46 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter)
0);
}
- adapter->notification_desc.msix_cpu_map_sz = num_online_cpus();
- adapter->notification_desc.msix_cpu_map =
- kzalloc(adapter->notification_desc.msix_cpu_map_sz,
- GFP_KERNEL);
- if (!adapter->notification_desc.msix_cpu_map)
- return -ENOMEM;
- memset(adapter->notification_desc.msix_cpu_map, 0,
- adapter->notification_desc.msix_cpu_map_sz);
+ rc = leapraid_alloc_msix_cpu_map(adapter);
+ if (rc)
+ return rc;
+ adapter->notification_desc.irq_mode = LEAPRAID_INTERRUPT_MODE_MSI;
adapter->notification_desc.msix_enable = 1;
rc = leapraid_setup_irqs(adapter);
if (rc) {
leapraid_free_irq(adapter);
adapter->notification_desc.msix_enable = 0;
- goto apply_legacy_int;
+ return rc;
}
return 0;
-
-apply_legacy_int:
- rc = leapraid_set_legacy_int(adapter);
-
- return rc;
}
-static int leapraid_set_notification(struct leapraid_adapter *adapter)
+static int leapraid_set_notification_auto(struct leapraid_adapter *adapter)
{
- int rc = 0;
+ int rc;
- if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSIX) {
- rc = leapraid_set_msix(adapter);
- if (rc)
- dev_err(&adapter->pdev->dev,
- "%s: Enable MSI-X irq failed!\n", __func__);
- } else if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSI) {
- rc = leapraid_set_msi(adapter);
- if (rc)
- dev_err(&adapter->pdev->dev,
- "%s: Enable MSI irq failed!\n", __func__);
- } else if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_LEGACY) {
- rc = leapraid_set_legacy_int(adapter);
- if (rc)
- dev_err(&adapter->pdev->dev,
- "%s: Enable legacy irq failed!\n", __func__);
- }
+ rc = leapraid_set_msix(adapter);
+ if (!rc)
+ return 0;
+
+ leapraid_free_irq(adapter);
+ dev_info(&adapter->pdev->dev,
+ "MSI-X setup failed (%d), trying MSI\n", rc);
+
+ rc = leapraid_set_msi(adapter);
+ if (!rc)
+ return 0;
+
+ leapraid_free_irq(adapter);
+ dev_info(&adapter->pdev->dev,
+ "MSI setup failed (%d), back to legacy INTx\n", rc);
+
+ rc = leapraid_set_legacy_int(adapter);
+ if (rc)
+ dev_err(&adapter->pdev->dev,
+ "%s: Enable legacy irq failed!\n", __func__);
return rc;
}
@@ -7852,7 +7497,7 @@ int leapraid_set_pcie_and_notification(struct leapraid_adapter *adapter)
goto out_fail;
}
- rc = leapraid_set_notification(adapter);
+ rc = leapraid_set_notification_auto(adapter);
if (rc)
goto out_fail;
@@ -7886,18 +7531,16 @@ static int leapraid_adapter_unit_reset(struct leapraid_adapter *adapter)
{
int rc = 0;
- dev_info(&adapter->pdev->dev, "fire unit reset\n");
writel(LEAPRAID_FUNC_ADAPTER_UNIT_RESET << LEAPRAID_DB_FUNC_SHIFT,
&adapter->iomem_base->db);
if (leapraid_db_wait_ack_and_clear_int(adapter))
rc = -EFAULT;
if (!leapraid_wait_adapter_ready(adapter)) {
- dev_info(&adapter->pdev->dev, "unit reset: FAILED\n");
+ dev_err(&adapter->pdev->dev, "unit reset failed\n");
return -EFAULT;
}
- dev_info(&adapter->pdev->dev, "unit reset: SUCCESS\n");
return rc;
}
@@ -7905,7 +7548,6 @@ static int leapraid_make_adapter_ready(struct leapraid_adapter *adapter,
enum reset_type type)
{
u32 db;
- int rc;
int count;
if (!leapraid_pci_active(adapter))
@@ -7944,8 +7586,7 @@ static int leapraid_make_adapter_ready(struct leapraid_adapter *adapter,
return 0;
full_reset:
- rc = leapraid_host_diag_reset(adapter);
- return rc;
+ return leapraid_host_diag_reset(adapter);
}
static void leapraid_fw_log_exit(struct leapraid_adapter *adapter)
@@ -7954,6 +7595,8 @@ static void leapraid_fw_log_exit(struct leapraid_adapter *adapter)
return;
if (adapter->fw_log_desc.fw_log_buffer) {
+ wait_event(adapter->fw_log_desc.mmap_waitq,
+ !atomic_read(&adapter->fw_log_desc.mmap_refcnt));
dma_free_coherent(&adapter->pdev->dev,
(LEAPRAID_SYS_LOG_BUF_SIZE +
LEAPRAID_SYS_LOG_BUF_RESERVE),
@@ -8085,16 +7728,22 @@ static void leapraid_free_host_memory(struct leapraid_adapter *adapter)
adapter->mem_desc.rep_desc_q_arr = NULL;
}
- for (i = 0; i < adapter->adapter_attr.rep_desc_q_seg_cnt; i++)
+ for (i = 0; i < adapter->adapter_attr.rep_desc_q_seg_cnt; i++) {
+ struct leapraid_mem_desc *mem_desc =
+ &adapter->mem_desc;
kfree(adapter->mem_desc.rep_desc_seg_maint[i]
.rep_desc_maint);
+ mem_desc->rep_desc_seg_maint[i].rep_desc_maint = NULL;
+ }
kfree(adapter->mem_desc.rep_desc_seg_maint);
+ adapter->mem_desc.rep_desc_seg_maint = NULL;
}
kfree(adapter->mem_desc.taskid_to_uniq_tag);
adapter->mem_desc.taskid_to_uniq_tag = NULL;
dma_pool_destroy(adapter->mem_desc.sg_chain_pool);
+ adapter->mem_desc.sg_chain_pool = NULL;
}
static inline bool leapraid_is_in_same_4g_seg(dma_addr_t start, u32 size)
@@ -8116,15 +7765,13 @@ int leapraid_internal_init_cmd_priv(struct leapraid_adapter *adapter,
return 0;
}
-int leapraid_internal_exit_cmd_priv(struct leapraid_adapter *adapter,
- struct leapraid_io_req_tracker *io_tracker)
+void leapraid_internal_exit_cmd_priv(struct leapraid_adapter *adapter,
+ struct leapraid_io_req_tracker *io_tracker)
{
if (io_tracker && io_tracker->chain)
dma_pool_free(adapter->mem_desc.sg_chain_pool,
io_tracker->chain,
io_tracker->chain_dma);
-
- return 0;
}
static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
@@ -8170,12 +7817,9 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
adapter->dynamic_task_desc.inter_cmd_qd;
/* SCSI host can queue. */
adapter->shost->can_queue = adapter->adapter_attr.io_qd -
- LEAPRAID_TASKID_OFFSET_SCSIIO_CMD;
+ LEAPRAID_TASKID_OFFSET_CTRL_CMD;
adapter->driver_cmds.ctl_cmd.taskid = adapter->shost->can_queue +
LEAPRAID_TASKID_OFFSET_CTRL_CMD;
- adapter->driver_cmds.driver_scsiio_cmd.taskid =
- adapter->shost->can_queue +
- LEAPRAID_TASKID_OFFSET_SCSIIO_CMD;
/* Allocate task descriptor. */
try_again:
@@ -8203,7 +7847,6 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
return -ENOMEM;
/* Allocate I/O tracker to SCSI I/O. */
-
adapter->mem_desc.taskid_to_uniq_tag =
kcalloc(adapter->shost->can_queue, sizeof(u16), GFP_KERNEL);
if (!adapter->mem_desc.taskid_to_uniq_tag)
@@ -8230,9 +7873,6 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
adapter->driver_cmds.transport_cmd.inter_taskid =
adapter->dynamic_task_desc.inter_taskid +
LEAPRAID_TASKID_OFFSET_TRANSPORT_CMD;
- adapter->driver_cmds.timestamp_sync_cmd.inter_taskid =
- adapter->dynamic_task_desc.inter_taskid +
- LEAPRAID_TASKID_OFFSET_TIMESTAMP_SYNC_CMD;
adapter->driver_cmds.enc_cmd.inter_taskid =
adapter->dynamic_task_desc.inter_taskid +
LEAPRAID_TASKID_OFFSET_ENC_CMD;
@@ -8292,8 +7932,11 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
LEAPRAID_REPLY_SIZE,
&adapter->mem_desc.rep_msg_dma,
GFP_KERNEL);
- if (!adapter->mem_desc.rep_msg)
- return -ENOMEM;
+ if (!adapter->mem_desc.rep_msg) {
+ rc = -ENOMEM;
+ goto out_fail;
+ }
+
if (!leapraid_is_in_same_4g_seg(adapter->mem_desc.rep_msg_dma,
adapter->adapter_attr.rep_msg_qd *
LEAPRAID_REPLY_SIZE)) {
@@ -8405,9 +8048,10 @@ static int leapraid_alloc_dev_topo_bitmaps(struct leapraid_adapter *adapter)
{
u16 pd_hdls_sz;
- pd_hdls_sz = adapter->adapter_attr.features.max_dev_handle /
- LEAPRAID_BITS_PER_BYTE;
- pd_hdls_sz++;
+ pd_hdls_sz =
+ BITS_TO_LONGS(
+ adapter->adapter_attr.features.max_dev_handle + 1) *
+ sizeof(unsigned long);
adapter->dev_topo.pd_hdls_sz = pd_hdls_sz;
adapter->dev_topo.pd_hdls =
@@ -8431,9 +8075,6 @@ static void leapraid_free_dev_topo_bitmaps(struct leapraid_adapter *adapter)
static int leapraid_init_driver_cmds(struct leapraid_adapter *adapter)
{
- u32 buffer_size;
- void *buffer;
-
INIT_LIST_HEAD(&adapter->driver_cmds.special_cmd_list);
adapter->driver_cmds.scan_dev_cmd.status = LEAPRAID_CMD_NOT_USED;
@@ -8453,45 +8094,6 @@ static int leapraid_init_driver_cmds(struct leapraid_adapter *adapter)
list_add_tail(&adapter->driver_cmds.transport_cmd.list,
&adapter->driver_cmds.special_cmd_list);
- adapter->driver_cmds.timestamp_sync_cmd.status = LEAPRAID_CMD_NOT_USED;
- adapter->driver_cmds.timestamp_sync_cmd.cb_idx =
- LEAPRAID_TIMESTAMP_SYNC_CB_IDX;
- mutex_init(&adapter->driver_cmds.timestamp_sync_cmd.mutex);
- list_add_tail(&adapter->driver_cmds.timestamp_sync_cmd.list,
- &adapter->driver_cmds.special_cmd_list);
-
- adapter->driver_cmds.raid_action_cmd.status = LEAPRAID_CMD_NOT_USED;
- adapter->driver_cmds.raid_action_cmd.cb_idx =
- LEAPRAID_RAID_ACTION_CB_IDX;
- mutex_init(&adapter->driver_cmds.raid_action_cmd.mutex);
- list_add_tail(&adapter->driver_cmds.raid_action_cmd.list,
- &adapter->driver_cmds.special_cmd_list);
-
- adapter->driver_cmds.driver_scsiio_cmd.status = LEAPRAID_CMD_NOT_USED;
- adapter->driver_cmds.driver_scsiio_cmd.cb_idx =
- LEAPRAID_DRIVER_SCSIIO_CB_IDX;
- mutex_init(&adapter->driver_cmds.driver_scsiio_cmd.mutex);
- list_add_tail(&adapter->driver_cmds.driver_scsiio_cmd.list,
- &adapter->driver_cmds.special_cmd_list);
-
- buffer_size = sizeof(struct scsi_cmnd) +
- sizeof(struct leapraid_io_req_tracker) +
- SCSI_SENSE_BUFFERSIZE +
- sizeof(struct scatterlist);
- buffer = kzalloc(buffer_size, GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
-
- adapter->driver_cmds.internal_scmd = buffer;
- buffer = (u8 *)buffer + sizeof(struct scsi_cmnd) +
- sizeof(struct leapraid_io_req_tracker);
- adapter->driver_cmds.internal_scmd->sense_buffer =
- (unsigned char *)buffer;
- buffer = (u8 *)buffer + SCSI_SENSE_BUFFERSIZE;
- adapter->driver_cmds.internal_scmd->sdb.table.sgl =
- (struct scatterlist *)buffer;
- buffer = (u8 *)buffer + sizeof(struct scatterlist);
-
adapter->driver_cmds.enc_cmd.status = LEAPRAID_CMD_NOT_USED;
adapter->driver_cmds.enc_cmd.cb_idx = LEAPRAID_ENC_CB_IDX;
mutex_init(&adapter->driver_cmds.enc_cmd.mutex);
@@ -8635,7 +8237,6 @@ static int leapraid_send_adapter_init(struct leapraid_adapter *adapter)
rc = -EIO;
}
- adapter->timestamp_sync_cnt = 0;
return rc;
}
@@ -8643,48 +8244,52 @@ static int leapraid_cfg_pages(struct leapraid_adapter *adapter)
{
union cfg_param_1 cfgp1 = {0};
union cfg_param_2 cfgp2 = {0};
- struct leapraid_manufacturing_p0 manufacturing_page0;
- struct leapraid_bios_page3 bios_page3;
- struct leapraid_bios_page2 bios_page2;
+ union {
+ struct leapraid_manufacturing_p0 manufacturing_page0;
+ struct leapraid_bios_page3 bios_page3;
+ struct leapraid_bios_page2 bios_page2;
+ } cfg_page;
int rc;
- rc = leapraid_op_config_page(adapter, &bios_page3, cfgp1,
+ rc = leapraid_op_config_page(adapter, &cfg_page.bios_page3, cfgp1,
cfgp2, GET_BIOS_PG3);
if (rc)
return rc;
- rc = leapraid_op_config_page(adapter, &bios_page2, cfgp1,
- cfgp2, GET_BIOS_PG2);
- if (rc)
- return rc;
+ adapter->adapter_attr.bios_version =
+ le32_to_cpu(cfg_page.bios_page3.bios_version);
- rc = leapraid_op_config_page(adapter, &manufacturing_page0, cfgp1,
- cfgp2, GET_MANUFACTURING_PG0);
+ rc = leapraid_op_config_page(adapter, &cfg_page.bios_page2, cfgp1,
+ cfgp2, GET_BIOS_PG2);
if (rc)
return rc;
- adapter->adapter_attr.bios_version =
- le32_to_cpu(bios_page3.bios_version);
- snprintf(adapter->adapter_attr.board_name,
- sizeof(adapter->adapter_attr.board_name),
- "%.*s",
- (int)sizeof(manufacturing_page0.board_name),
- manufacturing_page0.board_name);
adapter->boot_devs.requested_boot_dev.form =
- bios_page2.requested_boot_dev_form;
+ cfg_page.bios_page2.requested_boot_dev_form;
memcpy(adapter->boot_devs.requested_boot_dev.pg_dev,
- &bios_page2.requested_boot_dev,
+ &cfg_page.bios_page2.requested_boot_dev,
LEAPRAID_BOOT_DEV_SIZE);
adapter->boot_devs.requested_alt_boot_dev.form =
- bios_page2.requested_alt_boot_dev_form;
+ cfg_page.bios_page2.requested_alt_boot_dev_form;
memcpy(adapter->boot_devs.requested_alt_boot_dev.pg_dev,
- &bios_page2.requested_alt_boot_dev,
+ &cfg_page.bios_page2.requested_alt_boot_dev,
LEAPRAID_BOOT_DEV_SIZE);
adapter->boot_devs.current_boot_dev.form =
- bios_page2.current_boot_dev_form;
+ cfg_page.bios_page2.current_boot_dev_form;
memcpy(adapter->boot_devs.current_boot_dev.pg_dev,
- &bios_page2.current_boot_dev,
+ &cfg_page.bios_page2.current_boot_dev,
LEAPRAID_BOOT_DEV_SIZE);
+
+ rc = leapraid_op_config_page(adapter, &cfg_page.manufacturing_page0,
+ cfgp1, cfgp2, GET_MANUFACTURING_PG0);
+ if (rc)
+ return rc;
+
+ snprintf(adapter->adapter_attr.board_name,
+ sizeof(adapter->adapter_attr.board_name),
+ "%.*s",
+ (int)sizeof(cfg_page.manufacturing_page0.board_name),
+ cfg_page.manufacturing_page0.board_name);
return rc;
}
@@ -8793,8 +8398,6 @@ int leapraid_scan_dev(struct leapraid_adapter *adapter, bool async_scan_dev)
out_cleanup:
adapter->driver_cmds.scan_dev_cmd.status = LEAPRAID_CMD_NOT_USED;
- dev_info(&adapter->pdev->dev,
- "Device scan %s\n", rc == 0 ? "SUCCESS" : "FAILED");
return rc;
}
@@ -8936,11 +8539,7 @@ static int leapraid_make_adapter_available(struct leapraid_adapter *adapter)
return 0;
}
- rc = leapraid_scan_dev(adapter, false);
- if (rc)
- return rc;
-
- return rc;
+ return leapraid_scan_dev(adapter, false);
}
int leapraid_ctrl_init(struct leapraid_adapter *adapter)
@@ -8948,6 +8547,12 @@ int leapraid_ctrl_init(struct leapraid_adapter *adapter)
u32 cap;
int rc;
+ rc = leapraid_init_driver_cmds(adapter);
+ if (rc) {
+ dev_err(&adapter->pdev->dev, "Init driver cmds failure\n");
+ goto out_free;
+ }
+
rc = leapraid_set_pcie_and_notification(adapter);
if (rc)
goto out_free;
@@ -8981,12 +8586,6 @@ int leapraid_ctrl_init(struct leapraid_adapter *adapter)
goto out_free;
}
- rc = leapraid_init_driver_cmds(adapter);
- if (rc) {
- dev_err(&adapter->pdev->dev, "Init driver cmds failure\n");
- goto out_free;
- }
-
leapraid_init_event_mask(adapter);
rc = leapraid_make_adapter_available(adapter);
@@ -9006,9 +8605,7 @@ int leapraid_ctrl_init(struct leapraid_adapter *adapter)
out_free:
adapter->access_ctrl.host_removing = 1;
- wake_up(&adapter->access_ctrl.recovery_waitq);
leapraid_fw_log_exit(adapter);
- leapraid_free_internal_scsi_cmd(adapter);
leapraid_disable_controller(adapter);
leapraid_free_host_memory(adapter);
leapraid_free_dev_topo_bitmaps(adapter);
@@ -9022,18 +8619,9 @@ void leapraid_remove_ctrl(struct leapraid_adapter *adapter)
leapraid_check_scheduled_fault_stop(adapter);
leapraid_fw_log_stop(adapter);
leapraid_fw_log_exit(adapter);
- leapraid_free_internal_scsi_cmd(adapter);
leapraid_disable_controller(adapter);
leapraid_free_host_memory(adapter);
leapraid_free_dev_topo_bitmaps(adapter);
leapraid_free_enc_list(adapter);
pci_set_drvdata(adapter->pdev, NULL);
}
-
-void leapraid_free_internal_scsi_cmd(struct leapraid_adapter *adapter)
-{
- mutex_lock(&adapter->driver_cmds.driver_scsiio_cmd.mutex);
- kfree(adapter->driver_cmds.internal_scmd);
- adapter->driver_cmds.internal_scmd = NULL;
- mutex_unlock(&adapter->driver_cmds.driver_scsiio_cmd.mutex);
-}
diff --git a/drivers/scsi/leapraid/leapraid_func.h b/drivers/scsi/leapraid/leapraid_func.h
index df61bc2e994a..b4dce7e4b355 100644
--- a/drivers/scsi/leapraid/leapraid_func.h
+++ b/drivers/scsi/leapraid/leapraid_func.h
@@ -51,11 +51,11 @@
#define LEAPRAID_BOARD_NAME_LENGTH 17
#define LEAPRAID_AUTHOR "LeapIO Inc."
#define LEAPRAID_DESCRIPTION "LeapRAID Driver"
-#define LEAPRAID_DRIVER_VERSION "2.00.01.02"
+#define LEAPRAID_DRIVER_VERSION "2.00.01.10"
#define LEAPRAID_MAJOR_VERSION 2
-#define LEAPRAID_MINOR_VERSION 00
-#define LEAPRAID_BUILD_VERSION 01
-#define LEAPRAID_RELEASE_VERSION 02
+#define LEAPRAID_MINOR_VERSION 0
+#define LEAPRAID_BUILD_VERSION 1
+#define LEAPRAID_RELEASE_VERSION 10
#define LEAPRAID_MSG_VERSION 0x1021
#define LEAPRAID_HEADER_VERSION 0x0000
@@ -77,7 +77,6 @@
#define LEAPRAID_SG_DEPTH LEAPRAID_MAX_PHYS_SEGMENTS
/* Firmware and config page operations. */
-#define LEAPRAID_SET_PARAMETER_SYNC_TIMESTAMP 0x81
#define LEAPRAID_CFG_REQ_RETRY_TIMES 2
/* Hardware access helpers. */
@@ -88,8 +87,6 @@
/* Polling intervals. */
#define LEAPRAID_PCIE_LOG_POLLING_INTERVAL 1
#define LEAPRAID_FAULT_POLLING_INTERVAL 1000
-#define LEAPRAID_TIMESTAMP_SYNC_INTERVAL 900
-#define LEAPRAID_SMART_POLLING_INTERVAL (300 * 1000)
/* Init mask. */
#define LEAPRAID_RESET_IRQ_MASK 0x40000000
@@ -103,7 +100,6 @@
/* Target probe flag. */
#define LEAPRAID_NO_ULD_ATTACH_FLAG 1
-#define LEAPRAID_ULD_ATTACH_FLAG 0
/* SCSI device and queue limits. */
#define LEAPRAID_MAX_SECTORS 2048
@@ -127,7 +123,6 @@
/* SMP (Serial Management Protocol). */
#define LEAPRAID_SMP_PT_FLAG_SGL_PTR 0x80
-#define LEAPRAID_SMP_FN_REPORT_PHY_ERR_LOG 0x91
#define LEAPRAID_SMP_FRAME_HEADER_SIZE 4
#define LEAPRAID_SCSI_HOST_SHIFT 16
#define LEAPRAID_SCSI_DRIVER_SHIFT 24
@@ -171,13 +166,9 @@
/* Basic constants and limits. */
#define LEAPRAID_BUSY_LIMIT 1
-#define LEAPRAID_INDEX_FIRST 0
-#define LEAPRAID_BITS_PER_BYTE 8
#define LEAPRAID_INVALID_HOST_DIAG_VAL 0xFFFFFFFF
/* Retry/Sleep configuration. */
-#define LEAPRAID_WRITE_SEQUENCE_OFFSET 0x4
-#define LEAPRAID_WRSEQ_KEY_VALUE_MASK 0xF
#define LEAPRAID_WRSEQ_FLUSH_KEY_VALUE 0x0
#define LEAPRAID_WRSEQ_1ST_KEY_VALUE 0xF
#define LEAPRAID_WRSEQ_2ND_KEY_VALUE 0x4
@@ -187,7 +178,6 @@
#define LEAPRAID_WRSEQ_6TH_KEY_VALUE 0xD
#define LEAPRAID_UNLOCK_RETRY_LIMIT 20
#define LEAPRAID_UNLOCK_SLEEP_MS 100
-#define LEAPRAID_MSLEEP_SHORT_MS 50
#define LEAPRAID_MSLEEP_NORMAL_MS 100
#define LEAPRAID_MSLEEP_EXTRA_LONG_MS 500
#define LEAPRAID_IO_POLL_DELAY_US 500
@@ -198,17 +188,14 @@
#define LEAPRAID_INVALID_DEV_HANDLE 0xFFFF
/* Commands queue depth. */
-#define LEAPRAID_COALESCING_DEPTH_MAX 256
#define LEAPRAID_DEFAULT_CMD_QD_OFFSET 64
#define LEAPRAID_REPLY_QD_ALIGNMENT 16
/* Task ID offset. */
#define LEAPRAID_TASKID_OFFSET_CTRL_CMD 1
-#define LEAPRAID_TASKID_OFFSET_SCSIIO_CMD 2
#define LEAPRAID_TASKID_OFFSET_CFG_OP_CMD 1
#define LEAPRAID_TASKID_OFFSET_TRANSPORT_CMD 2
-#define LEAPRAID_TASKID_OFFSET_TIMESTAMP_SYNC_CMD 3
-#define LEAPRAID_TASKID_OFFSET_ENC_CMD 4
-#define LEAPRAID_TASKID_OFFSET_NOTIFY_EVENT_CMD 5
+#define LEAPRAID_TASKID_OFFSET_ENC_CMD 3
+#define LEAPRAID_TASKID_OFFSET_NOTIFY_EVENT_CMD 4
/* Task ID offset for high-priority. */
#define LEAPRAID_HP_TASKID_OFFSET_CTL_CMD 0
@@ -223,21 +210,12 @@
#define LEAPRAID_CFG_OP_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT
#define LEAPRAID_CTL_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT
#define LEAPRAID_SCAN_DEV_CMD_TIMEOUT 300
-#define LEAPRAID_TIMESTAMP_SYNC_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT
-#define LEAPRAID_RAID_ACTION_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT
#define LEAPRAID_ENC_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT
#define LEAPRAID_IO_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT
#define LEAPRAID_NOTIFY_EVENT_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT
#define LEAPRAID_TM_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT
#define LEAPRAID_TRANSPORT_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT
-/* Logsense command definitions. */
-#define LEAPRAID_LOGSENSE_DATA_LENGTH 16
-#define LEAPRAID_LOGSENSE_CDB_LENGTH 10
-#define LEAPRAID_LOGSENSE_CDB_CODE 0x6F
-#define LEAPRAID_LOGSENSE_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT
-#define LEAPRAID_LOGSENSE_SMART_CODE 0x5D
-
/* Host DMA cap. */
#define DMA_32_BITS 32
#define DMA_64_BITS 64
@@ -284,6 +262,8 @@ struct leapraid_adapter_features {
u8 max_volumes;
u16 max_dev_handle;
u16 min_dev_handle;
+ u16 msg_ver;
+ u16 product_id;
};
/**
@@ -424,7 +404,7 @@ struct leapraid_mem_desc {
};
/* internal cmd description */
-#define LEAPRAID_FIXED_INTER_CMDS 6
+#define LEAPRAID_FIXED_INTER_CMDS 5
#define LEAPRAID_FIXED_HP_CMDS 2
#define LEAPRAID_CMD_NOT_USED 0x8000
@@ -439,9 +419,6 @@ struct leapraid_mem_desc {
* @LEAPRAID_SCAN_DEV_CB_IDX: Scan device callback index.
* @LEAPRAID_CONFIG_CB_IDX: Configuration callback index.
* @LEAPRAID_TRANSPORT_CB_IDX: Transport callback index.
- * @LEAPRAID_TIMESTAMP_SYNC_CB_IDX: Timestamp sync callback index.
- * @LEAPRAID_RAID_ACTION_CB_IDX: RAID action callback index.
- * @LEAPRAID_DRIVER_SCSIIO_CB_IDX: Driver SCSI I/O callback index.
* @LEAPRAID_SAS_CTRL_CB_IDX: SAS controller callback index.
* @LEAPRAID_ENC_CB_IDX: Encryption callback index.
* @LEAPRAID_NOTIFY_EVENT_CB_IDX: Notify event callback index.
@@ -452,14 +429,11 @@ enum LEAPRAID_CB_INDEX {
LEAPRAID_SCAN_DEV_CB_IDX = 0x1,
LEAPRAID_CONFIG_CB_IDX = 0x2,
LEAPRAID_TRANSPORT_CB_IDX = 0x3,
- LEAPRAID_TIMESTAMP_SYNC_CB_IDX = 0x4,
- LEAPRAID_RAID_ACTION_CB_IDX = 0x5,
- LEAPRAID_DRIVER_SCSIIO_CB_IDX = 0x6,
- LEAPRAID_SAS_CTRL_CB_IDX = 0x7,
- LEAPRAID_ENC_CB_IDX = 0x8,
- LEAPRAID_NOTIFY_EVENT_CB_IDX = 0x9,
- LEAPRAID_CTL_CB_IDX = 0xA,
- LEAPRAID_TM_CB_IDX = 0xB,
+ LEAPRAID_SAS_CTRL_CB_IDX = 0x5,
+ LEAPRAID_ENC_CB_IDX = 0x6,
+ LEAPRAID_NOTIFY_EVENT_CB_IDX = 0x7,
+ LEAPRAID_CTL_CB_IDX = 0x8,
+ LEAPRAID_TM_CB_IDX = 0x9,
LEAPRAID_NUM_CB_IDXS
};
@@ -522,28 +496,20 @@ struct leapraid_driver_cmd {
* @scan_dev_cmd: Command used for asynchronous device scan operations.
* @cfg_op_cmd: Command for configuration operations.
* @transport_cmd: Command for transport-level operations.
- * @timestamp_sync_cmd: Command for synchronizing timestamp with firmware.
- * @raid_action_cmd: Command for RAID-related management or action requests.
- * @driver_scsiio_cmd: Command used for internal SCSI I/O processing.
* @enc_cmd: Command for enclosure management operations.
* @notify_event_cmd: Command for asynchronous event notification handling.
* @ctl_cmd: Command for generic control or maintenance operations.
* @tm_cmd: Task management command.
- * @internal_scmd: Pointer to internal SCSI command used by the driver.
*/
struct leapraid_driver_cmds {
struct list_head special_cmd_list;
struct leapraid_driver_cmd scan_dev_cmd;
struct leapraid_driver_cmd cfg_op_cmd;
struct leapraid_driver_cmd transport_cmd;
- struct leapraid_driver_cmd timestamp_sync_cmd;
- struct leapraid_driver_cmd raid_action_cmd;
- struct leapraid_driver_cmd driver_scsiio_cmd;
struct leapraid_driver_cmd enc_cmd;
struct leapraid_driver_cmd notify_event_cmd;
struct leapraid_driver_cmd ctl_cmd;
struct leapraid_driver_cmd tm_cmd;
- struct scsi_cmnd *internal_scmd;
};
/**
@@ -599,6 +565,7 @@ struct leapraid_fw_evt_work {
* @leapraid_evt_masks: Array of event masks for filtering firmware events.
*/
struct leapraid_fw_evt_struct {
+ u32 leapraid_evt_masks[4];
char fw_evt_name[48];
struct workqueue_struct *fw_evt_thread;
spinlock_t fw_evt_lock; /* protects firmware event */
@@ -606,7 +573,6 @@ struct leapraid_fw_evt_struct {
struct leapraid_fw_evt_work *cur_evt;
struct task_struct *cur_evt_task;
u8 fw_evt_cleanup;
- u32 leapraid_evt_masks[4];
};
/**
@@ -660,8 +626,8 @@ struct leapraid_blk_mq_poll_rq {
* @msix_enable: Flag indicating MSI-X is enabled.
* @irq_vectors_allocated: Flag indicating PCI IRQ vectors are allocated.
* @irq_mode: Actual interrupt mode used for allocated PCI IRQ vectors.
- * @msix_cpu_map: CPU map for MSI-X interrupts.
- * @msix_cpu_map_sz: Size of the MSI-X CPU map.
+ * @msix_cpu_map: CPU-ID indexed MSI-X queue map.
+ * @msix_cpu_map_sz: Number of CPU-ID slots allocated in @msix_cpu_map.
* @int_rqs: Array of interrupt request queues.
* @int_rqs_allocated: Count of allocated interrupt request queues.
* @blk_mq_poll_rqs: Array of blk-mq polling requests.
@@ -708,7 +674,6 @@ struct leapraid_overheat_desc {
* @pending_io_cnt: Count of pending I/O operations.
* @reset_wait_queue: Wait queue for reset operations.
* @reset_cnt: Counter for reset operations.
- * @last_reset_cnt: Last observed adapter reset counter.
*/
struct leapraid_reset_desc {
struct workqueue_struct *fault_reset_wq;
@@ -722,7 +687,6 @@ struct leapraid_reset_desc {
int pending_io_cnt;
wait_queue_head_t reset_wait_queue;
u32 reset_cnt;
- u32 last_reset_cnt;
};
/**
@@ -776,7 +740,8 @@ struct leapraid_access_ctrl {
* @fw_log_work: Delayed work structure for firmware log.
* @open_pcie_trace: Flag indicating if PCIe tracing is open.
* @fw_log_init_flag: Flag indicating if firmware log is initialized.
- * @pre_debug_log: Last DebugLog register snapshot for change detection.
+ * @mmap_refcnt: Number of active user VMAs on fw_log_buffer.
+ * @mmap_waitq: Waitqueue for fw_log_buffer VMA teardown.
*/
struct leapraid_fw_log_desc {
u8 *fw_log_buffer;
@@ -786,7 +751,8 @@ struct leapraid_fw_log_desc {
struct delayed_work fw_log_work;
int open_pcie_trace;
int fw_log_init_flag;
- u32 pre_debug_log[LEAPRAID_DEBUGLOG_SZ_MAX];
+ atomic_t mmap_refcnt;
+ wait_queue_head_t mmap_waitq;
};
#define LEAPRAID_CARD_PORT_FLG_DIRTY 0x01
@@ -939,19 +905,6 @@ struct leapraid_boot_devs {
struct leapraid_boot_dev current_boot_dev;
};
-/**
- * struct leapraid_smart_poll_desc - SMART polling descriptor
- *
- * @smart_poll_wq: Workqueue for SMART polling tasks.
- * @smart_poll_work: Delayed work for SMART polling operations.
- * @smart_poll_wq_name: Workqueue name string.
- */
-struct leapraid_smart_poll_desc {
- struct workqueue_struct *smart_poll_wq;
- struct delayed_work smart_poll_work;
- char smart_poll_wq_name[48];
-};
-
/**
* struct leapraid_adapter - Main LeapRAID adapter structure
*
@@ -961,7 +914,6 @@ struct leapraid_smart_poll_desc {
* @iomem_base: I/O memory mapped base address.
* @rep_msg_host_idx: Host index for reply messages.
* @mask_int: Interrupt masking flag.
- * @timestamp_sync_cnt: Timestamp synchronization counter.
* @adapter_attr: Adapter attributes.
* @mem_desc: Memory descriptor.
* @driver_cmds: Driver commands.
@@ -974,7 +926,6 @@ struct leapraid_smart_poll_desc {
* @fw_log_desc: Firmware log descriptor.
* @dev_topo: Device topology.
* @boot_devs: Boot devices.
- * @smart_poll_desc: SMART polling descriptor.
* @overheat_desc: Overheat processing descriptor.
*/
struct leapraid_adapter {
@@ -984,7 +935,6 @@ struct leapraid_adapter {
struct leapraid_reg_base __iomem *iomem_base;
u32 rep_msg_host_idx;
u8 mask_int;
- u32 timestamp_sync_cnt;
struct leapraid_adapter_attr adapter_attr;
struct leapraid_mem_desc mem_desc;
@@ -998,7 +948,6 @@ struct leapraid_adapter {
struct leapraid_fw_log_desc fw_log_desc;
struct leapraid_dev_topo dev_topo;
struct leapraid_boot_devs boot_devs;
- struct leapraid_smart_poll_desc smart_poll_desc;
struct leapraid_overheat_desc overheat_desc;
};
@@ -1116,6 +1065,7 @@ struct leapraid_starget_priv {
* @starget_priv: Associated target private data.
* @lun: Logical Unit Number.
* @flg: Flags.
+ * @ncq_prio_enable: Enables NCQ command priority for RT I/O.
* @block: Block flag.
* @deleted: Deletion flag.
* @sep: SEP flag.
@@ -1124,7 +1074,7 @@ struct leapraid_sdev_priv {
struct leapraid_starget_priv *starget_priv;
unsigned int lun;
u32 flg;
- u8 ncq;
+ u8 ncq_prio_enable;
u8 block;
u8 deleted;
u8 sep;
@@ -1157,7 +1107,6 @@ struct leapraid_sdev_priv {
* @enc_level: Enclosure level.
* @port_connection: Port connection.
* @connector_name: Connector name.
- * @support_smart: SMART support flag.
*/
struct leapraid_sas_dev {
struct list_head list;
@@ -1184,7 +1133,6 @@ struct leapraid_sas_dev {
u8 enc_level;
u8 port_connection;
u8 connector_name[LEAPRAID_SAS_DEV_P0_CON_NAME_LEN + 1];
- u8 support_smart;
};
static inline void leapraid_sdev_free(struct kref *ref)
@@ -1362,31 +1310,6 @@ struct leapraid_rep_manu_reply {
u8 vendor_specific[8];
};
-/**
- * struct leapraid_scsi_cmd_desc - SCSI command descriptor
- *
- * @hdl: Device handle.
- * @lun: Logical Unit Number.
- * @raid_member: RAID member flag.
- * @dir: DMA data direction.
- * @data_length: Data transfer length.
- * @data_buffer: Data buffer pointer.
- * @cdb_length: CDB length.
- * @cdb: Command Descriptor Block.
- * @time_out: Timeout.
- */
-struct leapraid_scsi_cmd_desc {
- u16 hdl;
- u32 lun;
- u8 raid_member;
- enum dma_data_direction dir;
- u32 data_length;
- void *data_buffer;
- u8 cdb_length;
- u8 cdb[32];
- u8 time_out;
-};
-
extern struct list_head leapraid_adapter_list;
extern spinlock_t leapraid_adapter_lock;
extern char driver_name[LEAPRAID_NAME_LENGTH];
@@ -1446,7 +1369,7 @@ int leapraid_get_volume_cap(struct leapraid_adapter *adapter,
int leapraid_internal_init_cmd_priv(
struct leapraid_adapter *adapter,
struct leapraid_io_req_tracker *io_tracker);
-int leapraid_internal_exit_cmd_priv(
+void leapraid_internal_exit_cmd_priv(
struct leapraid_adapter *adapter,
struct leapraid_io_req_tracker *io_tracker);
void leapraid_clean_active_fw_evt(struct leapraid_adapter *adapter);
@@ -1517,7 +1440,7 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter,
void *cfgp, union cfg_param_1 cfgp1,
union cfg_param_2 cfgp2,
enum config_page_action cfg_op);
-void leapraid_log_req_context(struct leapraid_adapter *adapter,
+void leapraid_log_req_context(struct leapraid_adapter *adapter, u16 smid,
const void *req_data);
int leapraid_change_queue_depth(struct scsi_device *sdev, int qdepth);
@@ -1557,10 +1480,7 @@ void leapraid_transport_attach_phy_to_port(
u64 sas_address,
struct leapraid_card_port *card_port);
int leapraid_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmd);
-void leapraid_smart_polling_start(struct leapraid_adapter *adapter);
-void leapraid_smart_polling_stop(struct leapraid_adapter *adapter);
void leapraid_overheat_cleanup(struct leapraid_adapter *adapter);
void leapraid_smart_fault_detect(struct leapraid_adapter *adapter, u16 hdl);
-void leapraid_free_internal_scsi_cmd(struct leapraid_adapter *adapter);
#endif /* LEAPRAID_FUNC_H_INCLUDED */
diff --git a/drivers/scsi/leapraid/leapraid_os.c b/drivers/scsi/leapraid/leapraid_os.c
index c60c5d80c7b3..6a9f97e4c63a 100644
--- a/drivers/scsi/leapraid/leapraid_os.c
+++ b/drivers/scsi/leapraid/leapraid_os.c
@@ -125,13 +125,6 @@ static int leapraid_tm_cmd_map_status(struct leapraid_adapter *adapter,
}
}
- if (taskid_task == adapter->driver_cmds.driver_scsiio_cmd.taskid &&
- (adapter->driver_cmds.driver_scsiio_cmd.status &
- LEAPRAID_CMD_DONE ||
- adapter->driver_cmds.driver_scsiio_cmd.status &
- LEAPRAID_CMD_NOT_USED))
- rc = SUCCESS;
-
if (taskid_task == adapter->driver_cmds.ctl_cmd.hp_taskid &&
(adapter->driver_cmds.ctl_cmd.status &
LEAPRAID_CMD_DONE ||
@@ -157,9 +150,8 @@ static int leapraid_tm_post_processing(struct leapraid_adapter *adapter,
leapraid_sync_irqs(adapter, true);
leapraid_unmask_int(adapter);
- rc = leapraid_tm_cmd_map_status(adapter, channel, id, lun, type,
- taskid_task);
- return rc;
+ return leapraid_tm_cmd_map_status(adapter, channel, id, lun, type,
+ taskid_task);
}
static void leapraid_build_tm_req(struct leapraid_scsi_tm_req *scsi_tm_req,
@@ -185,6 +177,7 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel,
struct leapraid_scsiio_req *scsiio_req;
struct leapraid_io_req_tracker *io_req_tracker = NULL;
u16 msix_task;
+ u16 taskid;
bool issue_reset = false;
u32 db;
int rc;
@@ -239,16 +232,15 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel,
msix_task = io_req_tracker->msix_io;
else
msix_task = 0;
- leapraid_fire_hpr_task(adapter,
- adapter->driver_cmds.tm_cmd.hp_taskid,
- msix_task);
+ taskid = adapter->driver_cmds.tm_cmd.hp_taskid;
+ leapraid_fire_hpr_task(adapter, taskid, msix_task);
wait_for_completion_timeout(&adapter->driver_cmds.tm_cmd.done,
LEAPRAID_TM_CMD_TIMEOUT * HZ);
if (!(adapter->driver_cmds.tm_cmd.status & LEAPRAID_CMD_DONE)) {
dev_err(&adapter->pdev->dev,
"%s: TM cmd timeout, status=0x%x\n",
__func__, adapter->driver_cmds.tm_cmd.status);
- leapraid_log_req_context(adapter, scsi_tm_req);
+ leapraid_log_req_context(adapter, taskid, scsi_tm_req);
issue_reset =
leapraid_check_reset(
adapter->driver_cmds.tm_cmd.status);
@@ -508,11 +500,11 @@ static void leapraid_scsiio_done_dispatch(
if (!scmd->result)
return;
- scsi_print_command(scmd);
- dev_warn(&adapter->pdev->dev,
- "SCSI I/O: hdl=0x%x, status: 0x%x, 0x%x, 0x%x\n",
- le16_to_cpu(scsiio_rep->dev_hdl), adapter_status,
- scsi_status, scsi_state);
+ dev_dbg(&adapter->pdev->dev,
+ "SCSI I/O: CDB=%*ph, hdl=0x%x, status: 0x%x, 0x%x, 0x%x\n",
+ scmd->cmd_len, scmd->cmnd,
+ le16_to_cpu(scsiio_rep->dev_hdl), adapter_status,
+ scsi_status, scsi_state);
if (scsi_state & LEAPRAID_SCSI_STATE_AUTOSENSE_VALID) {
struct scsi_sense_hdr sshdr;
@@ -521,13 +513,13 @@ static void leapraid_scsiio_done_dispatch(
le32_to_cpu(scsiio_rep->sense_count));
if (scsi_normalize_sense(scmd->sense_buffer, sz,
&sshdr))
- dev_warn(&adapter->pdev->dev,
- "Sense: key=0x%x asc=0x%x ascq=0x%x\n",
- sshdr.sense_key, sshdr.asc,
- sshdr.ascq);
+ dev_dbg(&adapter->pdev->dev,
+ "Sense: key=0x%x asc=0x%x ascq=0x%x\n",
+ sshdr.sense_key, sshdr.asc,
+ sshdr.ascq);
else
- dev_warn(&adapter->pdev->dev,
- "Sense: Invalid sense data\n");
+ dev_dbg(&adapter->pdev->dev,
+ "Sense: Invalid sense data\n");
}
}
@@ -539,10 +531,7 @@ bool leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid,
struct scsi_cmnd *scmd;
u32 response_code = 0;
- if (likely(taskid != adapter->driver_cmds.driver_scsiio_cmd.taskid))
- scmd = leapraid_get_scmd_from_taskid(adapter, taskid);
- else
- scmd = adapter->driver_cmds.internal_scmd;
+ scmd = leapraid_get_scmd_from_taskid(adapter, taskid);
if (!scmd)
return true;
@@ -569,13 +558,6 @@ bool leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid,
out_scsiio_done:
scsi_dma_unmap(scmd);
- if (unlikely(taskid ==
- adapter->driver_cmds.driver_scsiio_cmd.taskid)) {
- adapter->driver_cmds.driver_scsiio_cmd.status =
- LEAPRAID_CMD_DONE;
- complete(&adapter->driver_cmds.driver_scsiio_cmd.done);
- return false;
- }
leapraid_free_taskid(adapter, taskid);
scsi_done(scmd);
return false;
@@ -644,7 +626,6 @@ static void leapraid_probe_sas(struct leapraid_adapter *adapter)
sas_dev->hdl,
sas_dev->parent_sas_addr,
sas_dev->card_port);
-
if (!added)
goto remove_dev;
@@ -781,7 +762,6 @@ void leapraid_scan_dev_done(struct leapraid_adapter *adapter)
leapraid_fw_log_start(adapter);
adapter->scan_dev_desc.driver_loading = 0;
wake_up(&adapter->scan_dev_desc.wait_driver_loading);
- leapraid_smart_polling_start(adapter);
}
static const struct pci_device_id leapraid_pci_table[] = {
@@ -805,10 +785,7 @@ static inline bool leapraid_is_scmd_permitted(struct leapraid_adapter *adapter,
return false;
opcode = scmd->cmnd[0];
- if (opcode == SYNCHRONIZE_CACHE || opcode == START_STOP)
- return true;
-
- return false;
+ return opcode == SYNCHRONIZE_CACHE || opcode == START_STOP;
}
return true;
}
@@ -857,10 +834,7 @@ static bool leapraid_should_queuecommand(struct leapraid_adapter *adapter,
no_connect:
scmd->result = DID_NO_CONNECT << LEAPRAID_SCSI_HOST_SHIFT;
scsiio_done:
- if (likely(scmd != adapter->driver_cmds.internal_scmd))
- scsi_done(scmd);
- else
- *rc = LEAPRAID_OPERATION_FAILED;
+ scsi_done(scmd);
return false;
}
@@ -884,7 +858,7 @@ static u32 build_scsiio_req_control(struct scsi_cmnd *scmd,
control |= LEAPRAID_SCSIIO_CTRL_SIMPLEQ;
- if (sdev_priv->ncq &&
+ if (sdev_priv->ncq_prio_enable &&
(IOPRIO_PRIO_CLASS(req_get_ioprio(scsi_cmd_to_rq(scmd))) ==
IOPRIO_CLASS_RT))
control |= LEAPRAID_SCSIIO_CTRL_CMDPRI;
@@ -914,10 +888,7 @@ int leapraid_queuecommand(struct Scsi_Host *shost,
hdl = starget_priv->hdl;
control = build_scsiio_req_control(scmd, sdev_priv);
- if (unlikely(scmd == adapter->driver_cmds.internal_scmd))
- taskid = adapter->driver_cmds.driver_scsiio_cmd.taskid;
- else
- taskid = leapraid_alloc_scsiio_taskid(adapter, scmd);
+ taskid = leapraid_alloc_scsiio_taskid(adapter, scmd);
scsiio_req = leapraid_get_task_desc(adapter, taskid);
scsiio_req->func = LEAPRAID_FUNC_SCSIIO;
@@ -1101,13 +1072,15 @@ static int leapraid_error_handler(struct scsi_cmnd *scmd,
out_eh_done:
if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK) {
- dev_info(&adapter->pdev->dev,
- "EH ABORT result: %s, scmd=0x%p\n",
- rc == SUCCESS ? "success" : "failed", scmd);
+ if (rc != SUCCESS)
+ dev_err(&adapter->pdev->dev,
+ "EH ABORT result: failed, scmd=0x%p\n",
+ scmd);
} else {
- dev_info(&adapter->pdev->dev,
- "EH %s result: %s, scmd=0x%p\n",
- str, rc == SUCCESS ? "success" : "failed", scmd);
+ if (rc != SUCCESS)
+ dev_err(&adapter->pdev->dev,
+ "EH %s result: failed, scmd=0x%p\n",
+ str, scmd);
if (sas_dev)
leapraid_sdev_put(sas_dev);
}
@@ -1161,8 +1134,10 @@ static int leapraid_eh_host_reset_handler(struct scsi_cmnd *scmd)
rc = SUCCESS;
out_host_reset_done:
- dev_info(&adapter->pdev->dev, "EH HOST RESET result: %s, scmd=0x%p\n",
- rc == SUCCESS ? "success" : "failed", scmd);
+ if (rc != SUCCESS)
+ dev_err(&adapter->pdev->dev,
+ "EH HOST RESET result: failed, scmd=0x%p\n",
+ scmd);
return rc;
}
@@ -1227,7 +1202,7 @@ static int leapraid_slave_alloc(struct scsi_device *sdev)
return 0;
}
-static int leapraid_slave_cfg_volume(struct scsi_device *sdev)
+static bool leapraid_slave_cfg_volume(struct scsi_device *sdev)
{
struct Scsi_Host *shost = sdev->host;
struct leapraid_adapter *adapter = shost_priv(shost);
@@ -1276,10 +1251,10 @@ static int leapraid_slave_cfg_volume(struct scsi_device *sdev)
return 0;
}
-static int leapraid_slave_configure_extra(struct scsi_device *sdev,
- struct leapraid_sas_dev **psas_dev,
- u16 vol_hdl, u64 volume_wwid,
- bool *is_target_ssp, int *qd)
+static bool leapraid_slave_configure_extra(struct scsi_device *sdev,
+ struct leapraid_sas_dev **psas_dev,
+ u16 vol_hdl, u64 volume_wwid,
+ bool *is_target_ssp, int *qd)
{
struct leapraid_sas_dev *sas_dev;
struct leapraid_sdev_priv *sdev_priv;
@@ -1586,11 +1561,9 @@ static bool leapraid_scan_check_status(struct leapraid_adapter *adapter,
wake_up(&adapter->scan_dev_desc.wait_driver_loading);
adapter->scan_dev_desc.wait_scan_dev_done = 0;
adapter->access_ctrl.host_removing = 1;
- wake_up(&adapter->access_ctrl.recovery_waitq);
return true;
}
- dev_info(&adapter->pdev->dev, "Device scan: SUCCESS\n");
adapter->driver_cmds.scan_dev_cmd.status = LEAPRAID_CMD_NOT_USED;
leapraid_scan_dev_done(adapter);
return true;
@@ -1861,12 +1834,11 @@ static struct attribute *leapraid_shost_attrs[] = {
ATTRIBUTE_GROUPS(leapraid_shost);
-static ssize_t sas_address_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t sas_device_handle_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct scsi_device *sdev = to_scsi_device(dev);
struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata;
- u64 sas_address;
if (!sas_device_priv_data || !sas_device_priv_data->starget_priv) {
dev_err(&sdev->sdev_gendev,
@@ -1874,29 +1846,45 @@ static ssize_t sas_address_show(struct device *dev,
return -EINVAL;
}
- sas_address = sas_device_priv_data->starget_priv->sas_address;
-
- return sysfs_emit(buf, "0x%016llx\n", (unsigned long long)sas_address);
+ return sysfs_emit(buf, "0x%04x\n",
+ sas_device_priv_data->starget_priv->hdl);
}
-static ssize_t sas_device_handle_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static int leapraid_ncq_prio_supported(struct scsi_device *sdev,
+ bool *supported)
+{
+ struct scsi_vpd *vpd_pg89;
+
+ *supported = false;
+ rcu_read_lock();
+ vpd_pg89 = rcu_dereference(sdev->vpd_pg89);
+ if (vpd_pg89 && vpd_pg89->len >= LEAPRAID_VPD_PG89_MIN_LEN)
+ *supported =
+ (vpd_pg89->data[LEAPRAID_VPD_PG89_NCQ_BYTE_IDX] >>
+ LEAPRAID_VPD_PG89_NCQ_BIT_SHIFT) &
+ LEAPRAID_VPD_PG89_NCQ_BIT_MASK;
+ rcu_read_unlock();
+
+ return 0;
+}
+static ssize_t sas_ncq_prio_supported_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
struct scsi_device *sdev = to_scsi_device(dev);
- struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata;
+ bool supported;
+ int rc;
- if (!sas_device_priv_data || !sas_device_priv_data->starget_priv) {
- dev_err(&sdev->sdev_gendev,
- "%s: Invalid sdev_priv or starget_priv\n", __func__);
- return -EINVAL;
- }
+ rc = leapraid_ncq_prio_supported(sdev, &supported);
+ if (rc)
+ return rc;
- return sysfs_emit(buf, "0x%04x\n",
- sas_device_priv_data->starget_priv->hdl);
+ return sysfs_emit(buf, "%d\n", supported);
}
-static ssize_t sas_ncq_show(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t sas_ncq_prio_enable_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
struct scsi_device *sdev = to_scsi_device(dev);
struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata;
@@ -1907,18 +1895,18 @@ static ssize_t sas_ncq_show(struct device *dev, struct device_attribute *attr,
return -EINVAL;
}
- return sysfs_emit(buf, "%d\n", sas_device_priv_data->ncq);
+ return sysfs_emit(buf, "%d\n", sas_device_priv_data->ncq_prio_enable);
}
-static ssize_t sas_ncq_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t sas_ncq_prio_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct scsi_device *sdev = to_scsi_device(dev);
struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata;
- struct scsi_vpd *vpd_pg89;
- int ncq_op;
- bool ncq_supported;
+ bool supported;
+ int rc;
+ bool enable;
if (!sas_device_priv_data) {
dev_err(&sdev->sdev_gendev,
@@ -1926,45 +1914,66 @@ static ssize_t sas_ncq_store(struct device *dev,
return -EINVAL;
}
- if (kstrtoint(buf, 0, &ncq_op))
- return -EINVAL;
-
- if (ncq_op != 0 && ncq_op != 1) {
- dev_err(&sdev->sdev_gendev,
- "%s: Invalid NCQ value %d (only 0/1 allowed)\n",
- __func__, ncq_op);
+ if (kstrtobool(buf, &enable))
return -EINVAL;
- }
- rcu_read_lock();
- vpd_pg89 = rcu_dereference(sdev->vpd_pg89);
- if (!vpd_pg89 || vpd_pg89->len < LEAPRAID_VPD_PG89_MIN_LEN) {
- rcu_read_unlock();
+ rc = leapraid_ncq_prio_supported(sdev, &supported);
+ if (rc)
+ return rc;
+ if (!supported)
return -EINVAL;
- }
- ncq_supported = (vpd_pg89->data[LEAPRAID_VPD_PG89_NCQ_BYTE_IDX] >>
- LEAPRAID_VPD_PG89_NCQ_BIT_SHIFT) &
- LEAPRAID_VPD_PG89_NCQ_BIT_MASK;
- rcu_read_unlock();
- if (ncq_supported)
- sas_device_priv_data->ncq = ncq_op;
+ sas_device_priv_data->ncq_prio_enable = enable;
return count;
}
-static DEVICE_ATTR_RO(sas_address);
static DEVICE_ATTR_RO(sas_device_handle);
+static DEVICE_ATTR_RO(sas_ncq_prio_supported);
+static DEVICE_ATTR_RW(sas_ncq_prio_enable);
-static DEVICE_ATTR_RW(sas_ncq);
+static bool leapraid_sdev_is_sata(struct scsi_device *sdev)
+{
+ struct scsi_target *starget = sdev->sdev_target;
+ struct leapraid_starget_priv *starget_priv = starget->hostdata;
+ struct leapraid_sas_dev *sas_dev;
+
+ if (!starget_priv)
+ return false;
+
+ sas_dev = starget_priv->sas_dev;
+ return sas_dev && (sas_dev->dev_info & LEAPRAID_DEVTYP_SATA_DEV);
+}
static struct attribute *leapraid_sdev_attrs[] = {
- &dev_attr_sas_address.attr,
&dev_attr_sas_device_handle.attr,
- &dev_attr_sas_ncq.attr,
+ &dev_attr_sas_ncq_prio_supported.attr,
+ &dev_attr_sas_ncq_prio_enable.attr,
NULL,
};
-ATTRIBUTE_GROUPS(leapraid_sdev);
+static umode_t leapraid_sdev_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int i)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct scsi_device *sdev = to_scsi_device(dev);
+
+ if (attr == &dev_attr_sas_ncq_prio_supported.attr ||
+ attr == &dev_attr_sas_ncq_prio_enable.attr)
+ if (!leapraid_sdev_is_sata(sdev))
+ return 0;
+
+ return attr->mode;
+}
+
+static const struct attribute_group leapraid_sdev_attr_group = {
+ .attrs = leapraid_sdev_attrs,
+ .is_visible = leapraid_sdev_attr_is_visible,
+};
+
+static const struct attribute_group *leapraid_sdev_groups[] = {
+ &leapraid_sdev_attr_group,
+ NULL,
+};
static struct scsi_host_template leapraid_driver_template = {
.module = THIS_MODULE,
@@ -2053,13 +2062,12 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
adapter = shost_priv(shost);
INIT_LIST_HEAD(&adapter->list);
- spin_lock(&leapraid_adapter_lock);
- list_add_tail(&adapter->list, &leapraid_adapter_list);
- spin_unlock(&leapraid_adapter_lock);
adapter->shost = shost;
adapter->pdev = pdev;
adapter->fw_log_desc.open_pcie_trace = open_pcie_trace;
+ atomic_set(&adapter->fw_log_desc.mmap_refcnt, 0);
+ init_waitqueue_head(&adapter->fw_log_desc.mmap_waitq);
leapraid_lock_init(adapter);
leapraid_list_init(adapter);
snprintf(adapter->adapter_attr.name, LEAPRAID_NAME_LENGTH, "%s%d",
@@ -2111,6 +2119,10 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto scsi_add_shost_fail;
}
+ spin_lock(&leapraid_adapter_lock);
+ list_add_tail(&adapter->list, &leapraid_adapter_list);
+ spin_unlock(&leapraid_adapter_lock);
+
scsi_scan_host(shost);
return 0;
@@ -2120,9 +2132,6 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
leapraid_overheat_cleanup(adapter);
destroy_workqueue(adapter->fw_evt_s.fw_evt_thread);
evt_wq_fail:
- spin_lock(&leapraid_adapter_lock);
- list_del(&adapter->list);
- spin_unlock(&leapraid_adapter_lock);
scsi_host_put(shost);
return rc;
}
@@ -2205,13 +2214,13 @@ static void leapraid_remove(struct pci_dev *pdev)
wait_event(adapter->scan_dev_desc.wait_driver_loading,
!atomic_read(&adapter->overheat_desc.thermal_alert));
- adapter->access_ctrl.host_removing = 1;
- wake_up(&adapter->access_ctrl.recovery_waitq);
+ WRITE_ONCE(adapter->access_ctrl.host_removing, 1);
+ spin_lock(&leapraid_adapter_lock);
+ list_del(&adapter->list);
+ spin_unlock(&leapraid_adapter_lock);
leapraid_wait_cmds_done(adapter);
- leapraid_smart_polling_stop(adapter);
-
if (leapraid_pci_removed(adapter)) {
leapraid_mq_polling_pause(adapter);
leapraid_clean_active_scsi_cmds(adapter);
@@ -2228,9 +2237,6 @@ static void leapraid_remove(struct pci_dev *pdev)
sas_remove_host(shost);
leapraid_cleanup_lists(adapter);
leapraid_remove_ctrl(adapter);
- spin_lock(&leapraid_adapter_lock);
- list_del(&adapter->list);
- spin_unlock(&leapraid_adapter_lock);
scsi_host_put(shost);
}
@@ -2247,7 +2253,6 @@ static void leapraid_shutdown(struct pci_dev *pdev)
}
adapter->access_ctrl.host_removing = 1;
- wake_up(&adapter->access_ctrl.recovery_waitq);
leapraid_wait_cmds_done(adapter);
leapraid_clean_active_fw_evt(adapter);
leapraid_overheat_cleanup(adapter);
@@ -2283,7 +2288,6 @@ static pci_ers_result_t leapraid_pci_error_detected(struct pci_dev *pdev,
adapter->access_ctrl.pcie_recovering = 1;
scsi_block_requests(adapter->shost);
leapraid_overheat_cleanup(adapter);
- leapraid_smart_polling_stop(adapter);
leapraid_check_scheduled_fault_stop(adapter);
leapraid_fw_log_stop(adapter);
leapraid_disable_controller(adapter);
@@ -2291,7 +2295,6 @@ static pci_ers_result_t leapraid_pci_error_detected(struct pci_dev *pdev,
case pci_channel_io_perm_failure:
adapter->access_ctrl.pcie_recovering = 1;
leapraid_overheat_cleanup(adapter);
- leapraid_smart_polling_stop(adapter);
leapraid_check_scheduled_fault_stop(adapter);
leapraid_fw_log_stop(adapter);
leapraid_mq_polling_pause(adapter);
@@ -2334,7 +2337,6 @@ static pci_ers_result_t leapraid_pci_slot_reset(struct pci_dev *pdev)
dev_err(&pdev->dev, "%s PCI error slot reset\n",
adapter->adapter_attr.name);
- adapter->access_ctrl.pcie_recovering = 0;
adapter->pdev = pdev;
pci_restore_state(pdev);
if (leapraid_set_pcie_and_notification(adapter)) {
@@ -2344,13 +2346,15 @@ static pci_ers_result_t leapraid_pci_slot_reset(struct pci_dev *pdev)
return PCI_ERS_RESULT_DISCONNECT;
}
+ adapter->access_ctrl.pcie_recovering = 0;
dev_info(&pdev->dev, "%s: Hard reset triggered by PCI slot reset\n",
adapter->adapter_attr.name);
dev_info(&adapter->pdev->dev, "%s: %d: call hard_reset\n",
__func__, __LINE__);
rc = leapraid_hard_reset_handler(adapter, FULL_RESET);
- dev_info(&pdev->dev, "%s hard reset: %s\n",
- adapter->adapter_attr.name, rc == 0 ? "success" : "failed");
+ if (rc)
+ dev_err(&pdev->dev, "%s hard reset: failed\n",
+ adapter->adapter_attr.name);
return rc == 0 ? PCI_ERS_RESULT_RECOVERED :
PCI_ERS_RESULT_DISCONNECT;
@@ -2367,11 +2371,11 @@ static void leapraid_pci_resume(struct pci_dev *pdev)
}
dev_err(&pdev->dev, "PCI error resume!\n");
+
pci_aer_clear_nonfatal_status(pdev);
leapraid_check_scheduled_fault_start(adapter);
leapraid_fw_log_start(adapter);
scsi_unblock_requests(adapter->shost);
- leapraid_smart_polling_start(adapter);
}
MODULE_DEVICE_TABLE(pci, leapraid_pci_table);
@@ -2396,7 +2400,6 @@ static int leapraid_suspend(struct pci_dev *pdev, pm_message_t state)
}
leapraid_overheat_cleanup(adapter);
- leapraid_smart_polling_stop(adapter);
leapraid_check_scheduled_fault_stop(adapter);
leapraid_fw_log_stop(adapter);
scsi_block_requests(shost);
@@ -2452,7 +2455,6 @@ static int leapraid_resume(struct pci_dev *pdev)
scsi_unblock_requests(shost);
leapraid_check_scheduled_fault_start(adapter);
leapraid_fw_log_start(adapter);
- leapraid_smart_polling_start(adapter);
return 0;
}
#endif /* CONFIG_PM */
diff --git a/drivers/scsi/leapraid/leapraid_transport.c b/drivers/scsi/leapraid/leapraid_transport.c
index 738bc55df416..379029685e16 100644
--- a/drivers/scsi/leapraid/leapraid_transport.c
+++ b/drivers/scsi/leapraid/leapraid_transport.c
@@ -298,6 +298,7 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter,
dma_addr_t c2h_dma_addr;
bool issue_reset = false;
void *data_out = NULL;
+ u16 inter_taskid;
size_t c2h_size;
size_t h2c_size;
void *psge;
@@ -338,10 +339,8 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter,
rep_manu_request->allocated_response_length = 0;
rep_manu_request->request_length = 0;
- smp_passthrough_req =
- leapraid_get_task_desc(
- adapter,
- adapter->driver_cmds.transport_cmd.inter_taskid);
+ inter_taskid = adapter->driver_cmds.transport_cmd.inter_taskid;
+ smp_passthrough_req = leapraid_get_task_desc(adapter, inter_taskid);
memset(smp_passthrough_req, 0,
sizeof(struct leapraid_smp_passthrough_req));
smp_passthrough_req->func = LEAPRAID_FUNC_SMP_PASSTHROUGH;
@@ -354,8 +353,7 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter,
c2h_dma_addr, c2h_size);
init_completion(&adapter->driver_cmds.transport_cmd.done);
- leapraid_fire_task(adapter,
- adapter->driver_cmds.transport_cmd.inter_taskid);
+ leapraid_fire_task(adapter, inter_taskid);
wait_for_completion_timeout(&adapter->driver_cmds.transport_cmd.done,
LEAPRAID_TRANSPORT_CMD_TIMEOUT * HZ);
if (!(adapter->driver_cmds.transport_cmd.status & LEAPRAID_CMD_DONE)) {
@@ -363,7 +361,8 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter,
dev_err(&adapter->pdev->dev,
"%s: SMP passthrough timeout, st=0x%x\n",
__func__, adapter->driver_cmds.transport_cmd.status);
- leapraid_log_req_context(adapter, smp_passthrough_req);
+ leapraid_log_req_context(adapter, inter_taskid,
+ smp_passthrough_req);
if (!(adapter->driver_cmds.transport_cmd.status &
LEAPRAID_CMD_RESET))
issue_reset = true;
@@ -1249,20 +1248,21 @@ static void leapraid_build_smp_task(struct leapraid_adapter *adapter,
static int leapraid_send_smp_req(struct leapraid_adapter *adapter)
{
const struct leapraid_smp_passthrough_req *smp_passthrough_req;
+ u16 inter_taskid;
dev_dbg(&adapter->pdev->dev,
"%s: Sending smp request\n", __func__);
- smp_passthrough_req = leapraid_get_task_desc(
- adapter, adapter->driver_cmds.transport_cmd.inter_taskid);
+ inter_taskid = adapter->driver_cmds.transport_cmd.inter_taskid;
+ smp_passthrough_req = leapraid_get_task_desc(adapter, inter_taskid);
init_completion(&adapter->driver_cmds.transport_cmd.done);
- leapraid_fire_task(adapter,
- adapter->driver_cmds.transport_cmd.inter_taskid);
+ leapraid_fire_task(adapter, inter_taskid);
wait_for_completion_timeout(&adapter->driver_cmds.transport_cmd.done,
LEAPRAID_TRANSPORT_CMD_TIMEOUT * HZ);
if (!(adapter->driver_cmds.transport_cmd.status & LEAPRAID_CMD_DONE)) {
dev_err(&adapter->pdev->dev, "%s: timeout, st=0x%x\n",
__func__, adapter->driver_cmds.transport_cmd.status);
- leapraid_log_req_context(adapter, smp_passthrough_req);
+ leapraid_log_req_context(adapter, inter_taskid,
+ smp_passthrough_req);
if (!(adapter->driver_cmds.transport_cmd.status &
LEAPRAID_CMD_RESET)) {
dev_dbg(&adapter->pdev->dev,
@@ -1343,6 +1343,14 @@ static void leapraid_transport_smp_handler(struct bsg_job *job,
if (rc)
goto release_lock;
+ if (h2c_size < LEAPRAID_SMP_FRAME_HEADER_SIZE) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Invalid SMP request payload size=%zu\n",
+ __func__, h2c_size);
+ rc = -EINVAL;
+ goto free_req_buf;
+ }
+
if (addr_out)
sg_copy_to_buffer(job->request_payload.sg_list,
job->request_payload.sg_cnt, addr_out,
@@ -1353,6 +1361,14 @@ static void leapraid_transport_smp_handler(struct bsg_job *job,
if (rc)
goto free_req_buf;
+ if (c2h_size < LEAPRAID_SMP_FRAME_HEADER_SIZE) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Invalid SMP reply payload size=%zu\n",
+ __func__, c2h_size);
+ rc = -EINVAL;
+ goto free_rep_buf;
+ }
+
rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
__func__);
if (rc)
--
2.25.1
2
1